32

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.

7
  • 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. Perhaps worth a go? Commented May 24, 2012 at 16:31
  • stackoverflow.com/questions/6757434/… Commented May 26, 2012 at 6:39
  • You got those guys 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 ;) Commented May 28, 2012 at 17:21
  • 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 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. Commented May 29, 2012 at 10:53
  • hmmm i didnt tested but if any one confirms then i will delete this answer. Commented May 29, 2012 at 10:59

9 Answers 9

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).

Sign up to request clarification or add additional context in comments.

5 Comments

Ya its really very fast and working as expected. It only takes around 17 seconds only to convert 12 PDF pages with heavy images in PDF. Thanks man for the great post.
This project is no longer maintained.
@EbinJoy I had similar doubts, but it works perfectly in its current form. Just that we probably will not have more features in the future
its working fine but exception while opening the password protected pdf any help @vedant1811
AndroidUtils class not found
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 :)

11 Comments

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?
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
It feels like I'm missing something on my own system
Thanks, I will try to add the project as a whole
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...
|
7

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

2 Comments

How to support lower API version upto 14?
Just for FYI, PdfRenderer is not supported custom font and style. Please look into it github.com/googlesamples/android-PdfRendererBasic/issues/18
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; } 

Comments

5

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!

1 Comment

Does this work ? Looks like nobody tried this solution.
3

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

3 Comments

Thanks for your code. All working perfectly, but images quality is not good. How to get better quality?
This code is not working for some of the pdfs
Thanks, it seems to work well and save my day. Other library take over 40MB , so this solution is what I need ;)
2

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.

3 Comments

its working fine but exception while opening the password protected pdf pls help @dd619
sorry bhai...can't help you on password protected pdf.
you can add the password in the pdfContext class in the following method: public CodecDocument openDocument(String fileName) { return PdfDocument.openDocument(fileName, mPassword); }
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.

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.