29

All I need to do is take a (locally saved) PDF-document and convert one or all of it's pages to image format like JPG or PNG.

I've tried lot's of PDF Rendering/viewing solutions like APV PDF Viewer, APDFViewer, droidreader, android-pdf, MuPdf and many others but couldn't figure it out so far that how to convert a pdf-page into image?.

EDIT: Also I'd rather have a PDF to image converter than a PDF renderer that I need to edit to convert PDF to image.

Community
  • 1
  • 1
Pieter888
  • 4,882
  • 13
  • 53
  • 74
  • http://stackoverflow.com/questions/6757434/how-to-convert-pdf-into-image – Bugs bunny May 26 '12 at 06:39
  • 1
    @AgarwalShankar, not sure if you have tested this code yourself. **This is not gonna to work.** Why? **because the core class PDFImageWriter used in this code has dependency on java.awt.* class,** check out the [source code](http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.6.0/org/apache/pdfbox/util/PDFImageWriter.java) yourself. I hope you or people who vote this up can tell me I am wrong, from my basic knowledge: **Java awt is not supported by Android.** – yorkw May 29 '12 at 10:53
  • hmmm i didnt tested but if any one confirms then i will delete this answer. – Shankar Agarwal May 29 '12 at 10:59
  • You got [those guys](http://www.pdf-tools.com/pdf/pdf-to-image-converter-tiff.aspx) that can do it for you, they got they own API, so if you have internet connection it will do, if not...You should hack them, coz they doing a really great job ;) – Ilya Gazman May 28 '12 at 17:21
  • 1
    I'm not an Android dev, but my just-on-the-offchance web search just now reveals that [ImageMagick has been ported to this platform](http://stackoverflow.com/questions/5832217/compile-imagemagick-for-android-using-ndk). Perhaps worth a go? – halfer May 24 '12 at 16:31
  • why is this even closed? and where are the other answers man.. – Andro Selva May 29 '12 at 12:01
  • Hey can someone reopen this? I'm still looking for a solution. This is not a duplicate. Show me the duplicate! Also It still had a bounty open! – Pieter888 May 29 '12 at 22:32

9 Answers9

10

To support API 8 and above, follow:

Using this library: android-pdfview and the following code, you can reliably convert the PDF pages into images (JPG, PNG):

DecodeServiceBase decodeService = new DecodeServiceBase(new PdfContext());
decodeService.setContentResolver(mContext.getContentResolver());

// a bit long running
decodeService.open(Uri.fromFile(pdf));

int pageCount = decodeService.getPageCount();
for (int i = 0; i < pageCount; i++) {
    PdfPage page = decodeService.getPage(i);
    RectF rectF = new RectF(0, 0, 1, 1);

    // do a fit center to 1920x1080
    double scaleBy = Math.min(AndroidUtils.PHOTO_WIDTH_PIXELS / (double) page.getWidth(), //
            AndroidUtils.PHOTO_HEIGHT_PIXELS / (double) page.getHeight());
    int with = (int) (page.getWidth() * scaleBy);
    int height = (int) (page.getHeight() * scaleBy);

    // you can change these values as you to zoom in/out
    // and even distort (scale without maintaining the aspect ratio)
    // the resulting images

    // Long running
    Bitmap bitmap = page.renderBitmap(with, height, rectF);

    try {
        File outputFile = new File(mOutputDir, System.currentTimeMillis() + FileUtils.DOT_JPEG);
        FileOutputStream outputStream = new FileOutputStream(outputFile);

        // a bit long running
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);

        outputStream.close();
    } catch (IOException e) {
        LogWrapper.fatalError(e);
    }
}

You should do this work in the background i.e. by using an AsyncTask or something similar as quite a few methods take computation or IO time (I have marked them in comments).

Vedant Agarwala
  • 18,146
  • 4
  • 66
  • 89
9

You need to have look at this open-source for project for the same requirement, that can be helpful to you to do many more things also.

Project : PdfRenderer

There is one Java class named PDFPage.java in pdfview package. that class have a method to get Image of the page.

I have also implemented the same thing in my test project and the java code is here for you. I have created one method showPage which accepts the page no and zoom level and return that page as Bitmap.

Hope this can help you. You just need to get that Project or JAR for that, Read the well-documented JAVADOC for the same and then try and implement the same as I did.

Take your time, Happy Coding :)

MKJParekh
  • 34,073
  • 11
  • 87
  • 98
  • 2
    I'm trying to use the showPage method you made. But I'm having trouble on line 93 of the pastebin you posted. Apparently `PDFPage` is trying to use some classes (`Rectangle2D`, `ImageObserver`, `Image`) from `java.awt.geom` that are not supported by Android. How did you got it working? – Pieter888 May 24 '12 at 12:22
  • Yes, I added `pdf-renderer-1.0.5.jar` to the build path. this is the error I'm getting for `Rectangle2D`: `The type java.awt.geom.Rectangle2D cannot be resolved. It is indirectly referenced from required .class files` and I'm getting the same error for the classes I mentioned in my previous comment – Pieter888 May 24 '12 at 12:26
  • It feels like I'm missing something on my own system – Pieter888 May 24 '12 at 12:27
  • Thanks, I will try to add the project as a whole – Pieter888 May 24 '12 at 13:14
  • I'm sorry but the link is broken in that comment, could you paste it again? – Pieter888 May 24 '12 at 13:25
  • http://pastebin.com/N9EgUz7D see here no Rectangle,Observer,Image class is used..so i think i would have changed it accordingly.. – MKJParekh May 24 '12 at 13:28
  • Have you got any thing in your way, in loading those packages into your proejct? – MKJParekh May 29 '12 at 07:14
  • 1
    Hello MKJParekh i already tried so many solutions and i think most of stack solutions for PDF to image but not getting any proper way. I couldn't find any free library(jar) for PDF to image. and how to implement that jar on my activity class...? please to guide me... – Mihir Trivedi Sep 16 '13 at 07:32
  • will you please provide step by step procedure......... I am getting lots of error – Faiz Anwar Mar 27 '14 at 11:37
  • @MDFAIZANWAR Sorry, can't help as I have created demo years ago so I doesn't remember it. – MKJParekh Mar 27 '14 at 11:46
  • PdfRenderer uses Java AWT, which is not included in Android. – Cardinal System Sep 16 '19 at 18:07
7

Starting from Android API 21 PdfRenderer is what you are looking for.

amukhachov
  • 5,822
  • 1
  • 41
  • 60
6

Use the lib https://github.com/barteksc/PdfiumAndroid

public Bitmap getBitmap(File file){
 int pageNum = 0;
            PdfiumCore pdfiumCore = new PdfiumCore(context);
            try {
                PdfDocument pdfDocument = pdfiumCore.newDocument(openFile(file));
                pdfiumCore.openPage(pdfDocument, pageNum);

                int width = pdfiumCore.getPageWidthPoint(pdfDocument, pageNum);
                int height = pdfiumCore.getPageHeightPoint(pdfDocument, pageNum);


                // ARGB_8888 - best quality, high memory usage, higher possibility of OutOfMemoryError
                // RGB_565 - little worse quality, twice less memory usage
                Bitmap bitmap = Bitmap.createBitmap(width , height ,
                        Bitmap.Config.RGB_565);
                pdfiumCore.renderPageBitmap(pdfDocument, bitmap, pageNum, 0, 0,
                        width, height);
                //if you need to render annotations and form fields, you can use
                //the same method above adding 'true' as last param

                pdfiumCore.closeDocument(pdfDocument); // important!
                return bitmap;
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return null;
}

 public static ParcelFileDescriptor openFile(File file) {
        ParcelFileDescriptor descriptor;
        try {
            descriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }
        return descriptor;
    }
NickUnuchek
  • 11,794
  • 12
  • 98
  • 138
2

Using Android default libraries like AppCompat, you can convert all the PDF pages into images. This way is very fast and optimized. The below code is for getting separate images of a PDF page. It is very fast and quick.

I have implemented like below:

ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.open(new File("pdfFilePath.pdf"), MODE_READ_ONLY);
    PdfRenderer renderer = new PdfRenderer(fileDescriptor);
    final int pageCount = renderer.getPageCount();
    for (int i = 0; i < pageCount; i++) {
        PdfRenderer.Page page = renderer.openPage(i);
        Bitmap bitmap = Bitmap.createBitmap(page.getWidth(), page.getHeight(),Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(Color.WHITE);
        canvas.drawBitmap(bitmap, 0, 0, null);
        page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
        page.close();

        if (bitmap == null)
            return null;

        if (bitmapIsBlankOrWhite(bitmap))
            return null;

        String root = Environment.getExternalStorageDirectory().toString();
        File file = new File(root + filename + ".png");

        if (file.exists()) file.delete();
        try {
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            Log.v("Saved Image - ", file.getAbsolutePath());
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

=======================================================

private static boolean bitmapIsBlankOrWhite(Bitmap bitmap) {
    if (bitmap == null)
        return true;

    int w = bitmap.getWidth();
    int h = bitmap.getHeight();
    for (int i =  0; i < w; i++) {
        for (int j = 0; j < h; j++) {
            int pixel =  bitmap.getPixel(i, j);
            if (pixel != Color.WHITE) {
                return false;
            }
        }
    }
    return true;
}

I have already posted it in another question :P

Link is - https://stackoverflow.com/a/58420401/12228284

Rahul
  • 579
  • 1
  • 8
  • 18
2

from below code, you can extract all pages as image (PNG) format from PDF using PDFRender:

// This method is used to extract all pages in image (PNG) format.
    private void getImagesFromPDF(File pdfFilePath, File DestinationFolder) throws IOException {

        // Check if destination already exists then delete destination folder.
        if(DestinationFolder.exists()){
            DestinationFolder.delete();
        }

        // Create empty directory where images will be saved.
        DestinationFolder.mkdirs();

        // Reading pdf in READ Only mode.
        ParcelFileDescriptor fileDescriptor = ParcelFileDescriptor.open(pdfFilePath, ParcelFileDescriptor.MODE_READ_ONLY);

        // Initializing PDFRenderer object.
        PdfRenderer renderer = new PdfRenderer(fileDescriptor);

        // Getting total pages count.
        final int pageCount = renderer.getPageCount();

        // Iterating pages
        for (int i = 0; i < pageCount; i++) {

            // Getting Page object by opening page.
            PdfRenderer.Page page = renderer.openPage(i);

            // Creating empty bitmap. Bitmap.Config can be changed.
            Bitmap bitmap = Bitmap.createBitmap(page.getWidth(), page.getHeight(),Bitmap.Config.ARGB_8888);

            // Creating Canvas from bitmap.
            Canvas canvas = new Canvas(bitmap);

            // Set White background color.
            canvas.drawColor(Color.WHITE);

            // Draw bitmap.
            canvas.drawBitmap(bitmap, 0, 0, null);

            // Rednder bitmap and can change mode too.
            page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);

            // closing page
            page.close();

            // saving image into sdcard.
            File file = new File(DestinationFolder.getAbsolutePath(), "image"+i + ".png");

            // check if file already exists, then delete it.
            if (file.exists()) file.delete();

            // Saving image in PNG format with 100% quality.
            try {
                FileOutputStream out = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
                Log.v("Saved Image - ", file.getAbsolutePath());
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

You can call this method in below way:

// Getting images from Test.pdf file.
        File source = new File(Environment.getExternalStorageDirectory() + "/" + "Test" + ".pdf");

        // Images will be saved in Test folder.
        File destination = new File(Environment.getExternalStorageDirectory() + "/Test");

        // Getting images from pdf in png format.
        try {
            getImagesFromPDF(source, destination);
        } catch (IOException e) {
            e.printStackTrace();
        }

Cheers!

Naimatullah
  • 3,749
  • 2
  • 13
  • 12
1

I will say you a simple trick not a complete solution.Once if you successfully rendered the pdf page you will get its bitmap from screen as follow

View view = MuPDFActivity.this.getWindow().getDecorView();
if (false == view.isDrawingCacheEnabled()) {
    view.setDrawingCacheEnabled(true);
}
Bitmap bitmap = view.getDrawingCache();

Then you can save this bitmap, that is your pdf page as image in locally

try {
    new File(Environment.getExternalStorageDirectory()+"/PDF Reader").mkdirs();
    File outputFile = new File(Environment.getExternalStorageDirectory()+"/PDF Reader", System.currentTimeMillis()+"_pdf.jpg");
    FileOutputStream outputStream = new FileOutputStream(outputFile);

    // a bit long running
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
        outputStream.close();
} catch (IOException e) {
    Log.e("During IMAGE formation", e.toString());
}

that's all, hope you help this.

V-rund Puro-hit
  • 5,518
  • 9
  • 31
  • 50
Ebin Joy
  • 2,690
  • 5
  • 26
  • 39
1

Finally I found very simple solution to this, Download library from here.

Use below code to get images from PDF:

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.RectF;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.provider.MediaStore;

import org.vudroid.core.DecodeServiceBase;
import org.vudroid.core.codec.CodecPage;
import org.vudroid.pdfdroid.codec.PdfContext;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;

/**
 * Created by deepakd on 06-06-2016.
 */
public class PrintUtils extends AsyncTask<Void, Void, ArrayList<Uri>>
{
    File file;
    Context context;
    ProgressDialog progressDialog;

    public PrintUtils(File file, Context context)
    {

        this.file = file;
        this.context = context;
    }

    @Override
    protected void onPreExecute()
    {
        super.onPreExecute();
        // create and show a progress dialog
        progressDialog = ProgressDialog.show(context, "", "Please wait...");
        progressDialog.show();
    }

    @Override
    protected ArrayList<Uri> doInBackground(Void... params)
    {
        ArrayList<Uri> uris = new ArrayList<>();

        DecodeServiceBase decodeService = new DecodeServiceBase(new PdfContext());
        decodeService.setContentResolver(context.getContentResolver());
        // a bit long running
        decodeService.open(Uri.fromFile(file));
        int pageCount = decodeService.getPageCount();
        for (int i = 0; i < pageCount; i++)
        {
            CodecPage page = decodeService.getPage(i);
            RectF rectF = new RectF(0, 0, 1, 1);
            // do a fit center to A4 Size image 2480x3508
            double scaleBy = Math.min(UIUtils.PHOTO_WIDTH_PIXELS / (double) page.getWidth(), //
                    UIUtils.PHOTO_HEIGHT_PIXELS / (double) page.getHeight());
            int with = (int) (page.getWidth() * scaleBy);
            int height = (int) (page.getHeight() * scaleBy);
            // Long running
            Bitmap bitmap = page.renderBitmap(with, height, rectF);
            try
            {
                OutputStream outputStream = FileUtils.getReportOutputStream(System.currentTimeMillis() + ".JPEG");
                // a bit long running
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
                outputStream.close();
               // uris.add(getImageUri(context, bitmap));
                uris.add(saveImageAndGetURI(bitmap));
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        return uris;
    }

    @Override
    protected void onPostExecute(ArrayList<Uri> uris)
    {
        progressDialog.hide();
        //get all images by uri 
        //ur implementation goes here
    }




    public void shareMultipleFilesToBluetooth(Context context, ArrayList<Uri> uris)
    {
        try
        {
            Intent sharingIntent = new Intent();
            sharingIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
            sharingIntent.setType("image/*");
           // sharingIntent.setPackage("com.android.bluetooth");
            sharingIntent.putExtra(Intent.EXTRA_STREAM, uris);
            context.startActivity(Intent.createChooser(sharingIntent,"Print PDF using..."));
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }





    private Uri saveImageAndGetURI(Bitmap finalBitmap) {
        String root = Environment.getExternalStorageDirectory().toString();
        File myDir = new File(root + "/print_images");
        myDir.mkdirs();
        String fname = "Image-"+ MathUtils.getRandomID() +".jpeg";
        File file = new File (myDir, fname);
        if (file.exists ()) file.delete ();
        try {
            FileOutputStream out = new FileOutputStream(file);
            finalBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
            out.flush();
            out.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return Uri.parse("file://"+file.getPath());
    }

}

FileUtils.java

package com.airdata.util;

import android.net.Uri;
import android.os.Environment;
import android.support.annotation.NonNull;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

/**
 * Created by DeepakD on 21-06-2016.
 */
public class FileUtils
{

    @NonNull
    public static OutputStream getReportOutputStream(String fileName) throws FileNotFoundException
{
    // create file
    File pdfFolder = getReportFilePath(fileName);
    // create output stream
    return new FileOutputStream(pdfFolder);
}

    public static Uri getReportUri(String fileName)
    {
        File pdfFolder = getReportFilePath(fileName);
        return Uri.fromFile(pdfFolder);
    }
    public static File getReportFilePath(String fileName)
    {
        /*File file = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOWNLOADS), FileName);*/
        File file = new File(Environment.getExternalStorageDirectory() + "/AirPlanner/Reports");
        //Create report directory if does not exists
        if (!file.exists())
        {
            //noinspection ResultOfMethodCallIgnored
            file.mkdirs();
        }
        file = new File(Environment.getExternalStorageDirectory() + "/AirPlanner/Reports/" + fileName);
        return file;
    }
}

You can view converted images in Gallery or in SD card. Please let me know if you need any help.

dd619
  • 5,910
  • 8
  • 35
  • 60
  • its working fine but exception while opening the password protected pdf pls help @dd619 – Sunil Chaudhary Mar 06 '17 at 08:18
  • sorry bhai...can't help you on password protected pdf. – dd619 Mar 07 '17 at 10:11
  • you can add the password in the pdfContext class in the following method: public CodecDocument openDocument(String fileName) { return PdfDocument.openDocument(fileName, mPassword); } – coder Jul 26 '17 at 08:18
1

After going through and trying all the answers, none worked for me for all the PDF files. Rendering issues were there in custom font PDF files. Then I tried using library. I took inspiration from NickUncheck's answer for getting Images from all PDF pages.

The code is as follows:

In your app build.gradle file add the following dependency:

implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'

The code for converting PDF pages to images:

      public static List<Bitmap> renderToBitmap(Context context, String filePath) {
            List<Bitmap> images = new ArrayList<>();
            PdfiumCore pdfiumCore = new PdfiumCore(context);
            try {
                File f = new File(pdfPath);
                ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
                PdfDocument pdfDocument = pdfiumCore.newDocument(fd);
                final int pageCount = pdfiumCore.getPageCount(pdfDocument);
                for (int i = 0; i < pageCount; i++) {
                    pdfiumCore.openPage(pdfDocument, i);
                    int width = pdfiumCore.getPageWidthPoint(pdfDocument, i);
                    int height = pdfiumCore.getPageHeightPoint(pdfDocument, i);
                    Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                    pdfiumCore.renderPageBitmap(pdfDocument, bmp, i, 0, 0, width, height);
                    images.add(bmp);
                }
                pdfiumCore.closeDocument(pdfDocument);
            } catch(Exception e) {
                //todo with exception
            }
     return images;
   }

So far it is working for me all the PDF files that I tried.