21

I am developing an application where I need to convert an Image to PDF. I tried something, but the issue is, Image size in that PDF is very very small. I need solution to fix this. Also I am looking for converting multiple Images into single PDF document. I will post the code which I tried.

    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();
    }
}

When I convert Bitmap to Byte array, I am compressing the image and I guess, that's the reason. Without compressing the image, I am unable to convert Bitmap to Byte Array.

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

Is there any solution for this?

UPDATED

Here I have implemented the answer which suggested by @Burak Cakir in the answer. But now I am getting larger image in PDF. For better understanding, Please find the images below. enter image description here

The actually Image is enter image description here

Anish Kumar
  • 478
  • 4
  • 12
  • 27
  • 1
    Possible duplicate of [Convert image to PDF in Android](http://stackoverflow.com/questions/5389994/convert-image-to-pdf-in-android) – Murat Karagöz Mar 30 '16 at 10:04
  • you can use itext library for this. here is an example of this. http://www.concretepage.com/itext/add-image-in-pdf-using-itext-in-java – Ankur1994a Mar 30 '16 at 10:11
  • I tried that. I implemented that code here. My problem is, Image is very small in PDF. – Anish Kumar Mar 30 '16 at 10:12

6 Answers6

24

I would suggest you to use iText pdf library. Here is the gradle dependency:

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();
Burak Cakir
  • 918
  • 12
  • 22
  • 1
    I tried the code. Partially working, now Image is too big. Please find the updated question. I have posted few images – Anish Kumar Mar 30 '16 at 10:39
  • But, it varies from picture to picture. If I choose the image from camera, alignment is not proper. If I choose different image with different quality, again alignment differs. How can I dynamically fix this? – Anish Kumar Mar 31 '16 at 05:51
  • I dont know why it makes any difference from image to another image. Anyway, you can fix it by using setAlignment method. Updated again, check the answer pls. – Burak Cakir Mar 31 '16 at 06:34
  • Hi @Baruk ,very useful answer, but i pass a above 4mb picture but get .58mb pdf .i want that pdf must be above 4mb .is there any solution? – Suman Oct 05 '16 at 06:03
  • Hi @Suman, as far as i know, there is no method to change the pdf size. If you use the code lines above, there is scale part that scales the picture that's why the pdf size is much less than the picture size. So if you remove it, pdf has bigger size. But i'm not sure how it looks like. – Burak Cakir Oct 05 '16 at 07:49
  • ok thank you @Baruk , can you confirm me one think that..when i create pdf from image then image quality decreased or not? – Suman Oct 05 '16 at 07:57
  • 1
    @Suman, when you scale an Image object in iText, you don't lose any information: the number of pixels remains the same. Whereas PDF doesn't have a resolution, the images inside a PDF do. When you the image scale down (that is: you put the same number of pixels on a smaller canvas), the resolution increases; when you scale up, the resolution decreases. So quality ll be the same, the resolution is up to image size and document page size. – Burak Cakir Oct 05 '16 at 08:19
  • 1
    Just so you know, it's now implementation 'com.itextpdf:itextpdf:5.5.13' – Aradhna Mar 22 '18 at 07:39
  • hello, is this library can convert multiple images to single PDF file ? – Borom1r Oct 31 '18 at 04:22
  • I haven't tried multiple images version before but if you change the above code correctly, i don't see any specific reason not to work. – Burak Cakir Oct 31 '18 at 08:33
  • 1
    Hello, I've tried this code, It is working fine if I choose an Image from my Gallary, But very worst if I have captured an Image from my Camera. The Image get blured and cant read even a single text from that Image. – Rohan Shinde Dec 23 '20 at 11:29
  • It has been 4 years since I wrote this answer. I'm not sure if this library still works well today. I don't think this answer will blur the image. I suggest you take a look at the code you got the image from the gallery. Or you can check it like this, after getting the image from the gallery, set an image to ImageView and Pdf separately. If the results are different, you can give some specific details. – Burak Cakir Dec 24 '20 at 18:19
19

Download source code from here (Convert Image to pdf in android programmatically)

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();

            }
        }
    }


}

Thanks!

Deepshikha Puri
  • 2,104
  • 22
  • 23
  • Thanks for the code , I tried and it works ! but the quality of the image is poor.. I use the camera intent to get the bitmap instead of choosing the file. For the quality it may be because you resize the bitmap when you do that bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true); – Dagnogo Jean-François Nov 15 '17 at 16:18
  • 1
    Eventually, this code worked perfectly for me. I had an image which was created using a scrollView, Since it was a tablet, it had over 3000 * 10000 resolution. The accepted answer only printed out one portion of the image, but this solution printed out everything. – March3April4 Nov 08 '18 at 03:08
  • Could you please update above source code link , it is not accessible or could suggest any proper tutorial for creating image to pdf converter app for android – Mayur Satav Jul 15 '20 at 12:56
16

You can convert a JPG to a PDF by targeting a minimum SDK of 19 (KitKat 4.4) and using Google's PdfDocument API ( https://developer.android.com/reference/android/graphics/pdf/PdfDocument ), as shown below in 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()
Anthony.
  • 643
  • 7
  • 14
6

Just pass context and list of file It will create a PDF file in cache dir Add your own logic to share/open PDF Works fast and reliable method

  • No library needed (Uses android internal android.graphics.pdf.PdfDocument classes)
  • Works in background, Doesn''t freeze UI
  • No need to declare and grant storage permission :)
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);
                    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();

}
Mohammed Junaid
  • 1,362
  • 14
  • 18
Omkar T
  • 755
  • 8
  • 19
1

Add library in gradle

implementation 'com.itextpdf:itextg:5.5.10'

Create folder path - it will create pdf from all images of folder

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();
    }
}
jay patoliya
  • 611
  • 7
  • 8
0

this is how I convert image into pdf very easy , you need to declare the user permission first in the manifest

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

then in your main activity, you must check for permission is granted or not if you don't know how to do it just search on youtube you will find a lot of videos about that topic, after that, I use this method to pic image that i want to convert into pdf from the gallery.

public void pickImage() {
    Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent,120);
}

After that I override the onActivityResult() method to retrieve the selected image .

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 120 && resultCode == RESULT_OK && data != null) {
        Uri selectedImageUri = data.getData();

        String[] filePath = {MediaStore.Images.Media.DATA};
        Cursor cursor =getContentResolver().query(selectedImageUri,filePath,null,null,null);
        cursor.moveToFirst();

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

        Bitmap bitmap = BitmapFactory.decodeFile(myPath);
        imageView.setImageBitmap(bitmap);

        PdfDocument pdfDocument = new PdfDocument();
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(),
                bitmap.getHeight(),1).create();
        PdfDocument.Page page = pdfDocument.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);

        pdfDocument.finishPage(page);

        //save the bitmap image
        File root = new File(Environment.getExternalStorageDirectory(),"PDF folder 12");
        if (!root.exists()){
            root.mkdir();
        }
        File file = new File(root,"picture.pdf");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            pdfDocument.writeTo(fileOutputStream);
        }catch (Exception e){
            e.getStackTrace();
        }
        pdfDocument.close();
    }
}

don't forget the permission and ask the user to grant the permission

If you want to open pdf file automatically use this method after given the right path to the folder and pdf file name

 String path ="/sdcard/PDF folder 12/picture.pdf";
public void openPDF (){
    File pdfFile = new File(path);//File path
    if (pdfFile.exists()) //Checking if the file exists or not
    {
        Uri path = Uri.fromFile(pdfFile);
        Intent objIntent = new Intent(Intent.ACTION_VIEW);
        objIntent.setDataAndType(path, "application/pdf");
        objIntent.setFlags(Intent. FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(objIntent);//Starting the pdf viewer
    } else {

        Toast.makeText(GenerateQRActivity.this, "The file not exists! ", Toast.LENGTH_SHORT).show();

    }
}
jenos kon
  • 504
  • 4
  • 7