Как конвертировать изображение в PDF?

Я разрабатываю приложение, в котором мне нужно преобразовать изображение в PDF. Я что-то пробовал, но проблема в том, что размер изображения в этом PDF-файле очень-очень маленький. Мне нужно решение, чтобы это исправить. Также я ищу преобразование нескольких изображений в один документ PDF. Выложу код, который пробовал.

    public void convertPDF(byte[] path)
{
 String FILE = "mnt/sdcard/FirstPdf.pdf";
    Document document=new Document();
    try {
        PdfWriter.getInstance(document, new FileOutputStream(FILE));
        document.open();

        try {
            image=Image.getInstance(path);
            document.add(new Paragraph("My Heading"));
            document.add(image);
            document.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    } catch (DocumentException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
}

Когда я конвертирую Bitmap в массив байтов, я сжимаю изображение, и я думаю, в этом причина. Без сжатия изображения я не могу преобразовать растровое изображение в байтовый массив.

 ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG,100,stream);
        byte[] byteArray=stream.toByteArray();
        convertPDF(byteArray);

Есть ли решение для этого?

ОБНОВЛЕНО

Здесь я реализовал ответ, предложенный @Burak Cakir в ответе. Но теперь я получаю увеличенное изображение в формате PDF. Для лучшего понимания, пожалуйста, найдите изображения ниже. введите описание изображения здесь

Фактическое изображение -  введите описание изображения здесь


person Anish Kumar    schedule 30.03.2016    source источник
comment
Возможный дубликат конвертировать изображение в PDF на Android   -  person Murat Karagöz    schedule 30.03.2016
comment
вы можете использовать для этого библиотеку itext. вот пример этого. cretepage.com/itext/add-image- in-pdf-using-itext-in-java   -  person Ankur1994a    schedule 30.03.2016
comment
Я пробовал это. Я реализовал этот код здесь. Моя проблема в том, что изображение в PDF очень маленькое.   -  person Anish Kumar    schedule 30.03.2016


Ответы (5)


Я бы посоветовал вам использовать pdf-библиотеку iText. Вот зависимость gradle:

implementation 'com.itextpdf:itextg:5.5.10'

 Document document = new Document();

 String directoryPath = android.os.Environment.getExternalStorageDirectory().toString();

 PdfWriter.getInstance(document, new FileOutputStream(directoryPath + "/example.pdf")); //  Change pdf's name.

 document.open();

 Image image = Image.getInstance(directoryPath + "/" + "example.jpg");  // Change image's name and extension.

 float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
               - document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it.
 image.scalePercent(scaler);
 image.setAlignment(Image.ALIGN_CENTER | Image.ALIGN_TOP); 

 document.add(image);
 document.close();
person Burak Cakir    schedule 30.03.2016
comment
Я пробовал код. Частично работает, теперь изображение слишком велико. Найдите обновленный вопрос. Я разместил несколько изображений - person Anish Kumar; 30.03.2016
comment
Но это меняется от картинки к картинке. Если я выберу изображение с камеры, выравнивание будет неправильным. Если я выберу другое изображение с разным качеством, выравнивание снова изменится. Как я могу это исправить динамически? - person Anish Kumar; 31.03.2016
comment
Я не знаю, почему это имеет какое-то значение от изображения к другому. В любом случае, вы можете исправить это с помощью метода setAlignment. Обновился снова, проверьте ответ, пожалуйста. - person Burak Cakir; 31.03.2016
comment
Привет @Baruk, очень полезный ответ, но я передаю изображение выше 4 МБ, но получаю .58 МБ pdf. Я хочу, чтобы этот pdf был выше 4 МБ. Есть ли какое-нибудь решение? - person Suman; 05.10.2016
comment
Привет, @Suman, насколько я знаю, нет способа изменить размер pdf. Если вы используете приведенные выше строки кода, есть масштабная часть, которая масштабирует изображение, поэтому размер pdf намного меньше размера изображения. Поэтому, если вы удалите его, pdf будет иметь больший размер. Но я не знаю, как это выглядит. - person Burak Cakir; 05.10.2016
comment
хорошо, спасибо @Baruk, вы можете подтвердить, что мне кажется, что ... когда я создаю PDF-файл из изображения, качество изображения ухудшается или нет? - person Suman; 05.10.2016
comment
@Suman, когда вы масштабируете объект Image в iText, вы не теряете никакой информации: количество пикселей остается прежним. В то время как у PDF нет разрешения, у изображений внутри PDF есть. Когда вы уменьшаете масштаб изображения (то есть помещаете такое же количество пикселей на меньший холст), разрешение увеличивается; при увеличении разрешение уменьшается. Так что качество будет одинаковым, разрешение будет соответствовать размеру изображения и размеру страницы документа. - person Burak Cakir; 05.10.2016
comment
Просто чтобы вы знали, теперь это реализация com.itextpdf: itextpdf: 5.5.13. - person Aradhna; 22.03.2018
comment
привет, эта библиотека может конвертировать несколько изображений в один файл PDF? - person Borom1r; 31.10.2018
comment
Раньше я не пробовал использовать несколько версий изображений, но если вы правильно измените приведенный выше код, я не вижу конкретной причины, чтобы не работать. - person Burak Cakir; 31.10.2018
comment
Здравствуйте, я пробовал этот код, он работает нормально, если я выберу изображение из моей галереи, но очень плохо, если я захватил изображение с моей камеры. Изображение размывается и не может прочитать ни одного текста из этого изображения. - person Rohan Shinde; 23.12.2020
comment
Прошло 4 года с тех пор, как я написал этот ответ. Я не уверен, хорошо ли работает эта библиотека сегодня. Не думаю, что этот ответ размывает изображение. Предлагаю вам взглянуть на код изображения, полученный вами из галереи. Или вы можете проверить это так: после получения изображения из галереи установите изображение отдельно для ImageView и Pdf. Если результаты отличаются, вы можете указать некоторые конкретные детали. - person Burak Cakir; 24.12.2020

Загрузите исходный код отсюда (Конвертировать изображение в pdf в android программно)

MainActivity.java:

package com.deepshikha.convertbitmap;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.pdf.PdfDocument;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    public static final int GALLERY_PICTURE = 1;
    Button btn_select, btn_convert;
    ImageView iv_image;
    boolean boolean_permission;
    boolean boolean_save;
    Bitmap bitmap;
    public static final int REQUEST_PERMISSIONS = 1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        listener();
        fn_permission();
    }

    private void init() {
        btn_select = (Button) findViewById(R.id.btn_select);
        btn_convert = (Button) findViewById(R.id.btn_convert);
        iv_image = (ImageView) findViewById(R.id.iv_image);
    }

    private void listener() {
        btn_select.setOnClickListener(this);
        btn_convert.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_select:
                Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(intent, GALLERY_PICTURE);
                break;

            case R.id.btn_convert:
                if (boolean_save){

                    Intent intent1=new Intent(getApplicationContext(),PDFViewActivity.class);
                    startActivity(intent1);

                }else {
                    createPdf();
                }
                break;


        }
    }

    private void createPdf(){
        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        DisplayMetrics displaymetrics = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        float hight = displaymetrics.heightPixels ;
        float width = displaymetrics.widthPixels ;

        int convertHighet = (int) hight, convertWidth = (int) width;

//        Resources mResources = getResources();
//        Bitmap bitmap = BitmapFactory.decodeResource(mResources, R.drawable.screenshot);

        PdfDocument document = new PdfDocument();
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), 1).create();
        PdfDocument.Page page = document.startPage(pageInfo);

        Canvas canvas = page.getCanvas();


        Paint paint = new Paint();
        paint.setColor(Color.parseColor("#ffffff"));
        canvas.drawPaint(paint);



        bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);

        paint.setColor(Color.BLUE);
        canvas.drawBitmap(bitmap, 0, 0 , null);
        document.finishPage(page);


        // write the document content
        String targetPdf = "/sdcard/test.pdf";
        File filePath = new File(targetPdf);
        try {
            document.writeTo(new FileOutputStream(filePath));
            btn_convert.setText("Check PDF");
            boolean_save=true;
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Something wrong: " + e.toString(), Toast.LENGTH_LONG).show();
        }

        // close the document
        document.close();
    }



    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == GALLERY_PICTURE && resultCode == RESULT_OK) {

            if (resultCode == RESULT_OK) {
                Uri selectedImage = data.getData();
                String[] filePathColumn = {MediaStore.Images.Media.DATA};

                Cursor cursor = getContentResolver().query(
                        selectedImage, filePathColumn, null, null, null);
                cursor.moveToFirst();

                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                String filePath = cursor.getString(columnIndex);
                cursor.close();


                bitmap = BitmapFactory.decodeFile(filePath);
                iv_image.setImageBitmap(bitmap);


                btn_convert.setClickable(true);
            }
        }
    }

    private void fn_permission() {
        if ((ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)||
                (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {

            if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.READ_EXTERNAL_STORAGE))) {
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
                        REQUEST_PERMISSIONS);

            }

            if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE))) {
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        REQUEST_PERMISSIONS);

            }
        } else {
            boolean_permission = true;


        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERMISSIONS) {

            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                boolean_permission = true;


            } else {
                Toast.makeText(getApplicationContext(), "Please allow the permission", Toast.LENGTH_LONG).show();

            }
        }
    }


}

Спасибо!

person Deepshikha Puri    schedule 28.06.2017
comment
Спасибо за код, попробовал, работает! но качество изображения плохое .. Я использую камеру, чтобы получить растровое изображение, вместо того, чтобы выбирать файл. Для качества это может быть из-за того, что вы изменяете размер растрового изображения, когда делаете это bitmap = Bitmap.createScaledBitmap (bitmap, bitmap.getWidth (), bitmap.getHeight (), true); - person Dagnogo Jean-François; 15.11.2017
comment
В конце концов, этот код у меня отлично сработал. У меня было изображение, которое было создано с помощью scrollView, так как это был планшет, он имел разрешение более 3000 * 10000. Принятый ответ распечатал только одну часть изображения, но это решение распечатало все. - person March3April4; 08.11.2018
comment
Не могли бы вы обновить приведенную выше ссылку на исходный код, она недоступна или может предложить какое-либо надлежащее руководство по созданию приложения для преобразования изображений в pdf для Android. - person Mayur Satav; 15.07.2020

Вы можете преобразовать JPG в PDF, настроив минимальный SDK 19 (KitKat 4.4) и используя API Google PdfDocument (https://developer.android.com/reference/android/graphics/pdf/PdfDocument), как показано ниже в Kotlin:

    // Load JPG file into bitmap
    val f: File = myJPGFile
    val bitmap: Bitmap  = BitmapFactory.decodeFile(f.absolutePath)

    // Create a PdfDocument with a page of the same size as the image
    val document: PdfDocument = PdfDocument()
    val pageInfo: PdfDocument.PageInfo  = PdfDocument.PageInfo.Builder(bitmap.width, bitmap.height, 1).create()
    val page: PdfDocument.Page  = document.startPage(pageInfo)

    // Draw the bitmap onto the page
    val canvas: Canvas = page.canvas
    canvas.drawBitmap(bitmap, 0f, 0f, null)
    document.finishPage(page)

    // Write the PDF file to a file
    val directoryPath: String  = android.os.Environment.getExternalStorageDirectory().toString()
    document.writeTo( FileOutputStream(directoryPath + "/example.pdf"))
    document.close()
person Anthony.    schedule 01.05.2019

Добавить библиотеку в Gradle

implementation 'com.itextpdf:itextg:5.5.10'

Создать путь к папке - он будет создавать pdf из всех изображений папки

File folderPath = new File(Environment.getExternalStorageDirectory() + "/YourImagesFolder");

File[] imageList = folderPath .listFiles();
ArrayList<File> imagesArrayList = new ArrayList<>();
for (File absolutePath : imageList) {
          imagesArrayList.add(absolutePath);
}
new CreatePdfTask(context, imagesArrayList).execute();

AsyncTask

 public class CreatePdfTask extends AsyncTask<String, Integer, File> {
    Context context;
    ArrayList<File> files;
    ProgressDialog progressDialog;

    public CreatePdfTask(Context context2, ArrayList<File> arrayList) {
        context = context2;
        files = arrayList;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = new ProgressDialog(context);
        progressDialog.setTitle("Please wait...");
        progressDialog.setMessage("Creating pdf...");
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setIndeterminate(false);
        progressDialog.setMax(100);
        progressDialog.setCancelable(true);
        progressDialog.show();
    }

    @Override
    protected File doInBackground(String... strings) {
        File outputMediaFile = Constant.getPdfPath();//path in which you want to save pdf

        Document document = new Document(PageSize.A4, 38.0f, 38.0f, 50.0f, 38.0f);
        try {
            PdfWriter.getInstance(document, new FileOutputStream(outputMediaFile));
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }
        document.open();

        int i = 0;
        while (true) {
            if (i < this.files.size()) {
                try {
                    Image image = Image.getInstance(files.get(i).getAbsolutePath());

                    float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
                            - document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it.
                    image.scalePercent(scaler);
                    image.setAlignment(Image.ALIGN_CENTER | Image.ALIGN_TOP);
                    image.setAbsolutePosition((document.getPageSize().getWidth() - image.getScaledWidth()) / 2.0f,
                            (document.getPageSize().getHeight() - image.getScaledHeight()) / 2.0f);

                    document.add(image);
                    document.newPage();
                    publishProgress(i);
                    i++;
                } catch (BadElementException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (DocumentException e) {
                    e.printStackTrace();
                }
            } else {
                document.close();
                return outputMediaFile;
            }
        }
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        this.progressDialog.setProgress(((values[0] + 1) * 100) / this.files.size());
        StringBuilder sb = new StringBuilder();
        sb.append("Processing images (");
        sb.append(values[0] + 1);
        sb.append("/");
        sb.append(this.files.size());
        sb.append(")");
        progressDialog.setTitle(sb.toString());
    }

    @Override
    protected void onPostExecute(File file) {
        super.onPostExecute(file);
        progressDialog.dismiss();
        Toast.makeText(context, "Pdf store at " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
    }
}
person jay patoliya    schedule 13.08.2020
comment
Вы должны сделать свое приложение с открытым исходным кодом, если вы используете эту библиотеку в соответствии с их лицензией !!!! - person Omkar; 24.07.2021

Просто передайте контекст и список файлов. Он создаст файл PDF в каталоге кеша. Добавьте свою логику для совместного использования / открытия PDF. Работает быстро и надежно.

  • Библиотека не требуется (используются внутренние классы android.graphics.pdf.PdfDocument для Android)
  • Работает в фоновом режиме, интерфейс не зависает
  • Не нужно объявлять и предоставлять разрешение на хранение :)
private static void createPdf(Context context,ArrayList<File> data){
    File pdfFile = new File(context.getExternalCacheDir().getAbsolutePath() + File.separator + "TemperoryPDF_"+System.currentTimeMillis()+".pdf");
    Toast.makeText(context, "Creating PDF,Please wait..", Toast.LENGTH_SHORT).show();
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... voids) {
            PdfDocument document = new PdfDocument();
            try {
                for(File item:data) {
                    Bitmap bitmap = BitmapFactory.decodeFile(item.getAbsolutePath());
                    PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), 1).create();
                    PdfDocument.Page page = document.startPage(pageInfo);
                    Canvas canvas = page.getCanvas();
                    Paint paint = new Paint();
                    paint.setColor(Color.parseColor("#ffffff"));
                    canvas.drawPaint(paint);
                    bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);
                    canvas.drawBitmap(bitmap, 0, 0, null);
                    document.finishPage(page);
                }
                document.writeTo(new FileOutputStream(pdfFile));
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                document.close();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void unused) {
            super.onPostExecute(unused);
            if(pdfFile.exists() && pdfFile.length()>0) {
                FileUtil.openFile(context, pdfFile.getAbsolutePath()); // See: https://gist.github.com/omkar-tenkale/34d3aa1966653e6949d1ddaee1ba3355
            }else {
                Toast.makeText(context, "Something went wrong creating the PDF :(", Toast.LENGTH_SHORT).show();
            }
        }
    }.execute();

}
person Omkar    schedule 23.07.2021