2012-01-11 144 views
37

我需要将PDF文件(PDF页面)转换为Android中的位图(或图像文件)。在Android中将PDF页面转换为位图Java

1.使用Apache的Pdfbox jar。但它使用了一些在android中不支持的java类。 2.试过将图片转换为PDF格式的Itext jar(我需要它的反向操作) 就像我已经尝试了很多jar。但没有积极的结果。

byte[] bytes; 
    try { 

     File file = new File(this.getFilesDir().getAbsolutePath()+"/2010Q2_SDK_Overview.pdf"); 
     FileInputStream is = new FileInputStream(file); 

     // Get the size of the file 
     long length = file.length(); 
     bytes = new byte[(int) length]; 
     int offset = 0; 
     int numRead = 0; 
     while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { 
      offset += numRead; 
     } 


     ByteBuffer buffer = ByteBuffer.NEW(bytes); 
     String data = Base64.encodeToString(bytes, Base64.DEFAULT); 
     PDFFile pdf_file = new PDFFile(buffer); 
     PDFPage page = pdf_file.getPage(2); 

     RectF rect = new RectF(0, 0, (int) page.getBBox().width(), 
       (int) page.getBBox().height()); 
     // Bitmap bufferedImage = Bitmap.createBitmap((int)rect.width(), (int)rect.height(), 
     //  Bitmap.Config.ARGB_8888); 

     Bitmap image = page.getImage((int)rect.width(), (int)rect.height(), rect); 
     FileOutputStream os = new FileOutputStream(this.getFilesDir().getAbsolutePath()+"/pdf.jpg"); 
     image.compress(Bitmap.CompressFormat.JPEG, 80, os); 

     // ((ImageView) findViewById(R.id.testView)).setImageBitmap(image); 

我得到的图像文件, enter image description here

相反的, enter image description here

package com.test123; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 

import com.sun.pdfview.PDFFile; 
import com.sun.pdfview.PDFPage; 
import net.sf.andpdf.nio.ByteBuffer; 

import android.app.Activity; 
import android.graphics.Bitmap; 
import android.graphics.RectF; 
import android.os.Bundle; 
import android.util.Base64; 

public class Test123Activity extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     byte[] bytes; 
     try { 

      File file = new File(this.getFilesDir().getAbsolutePath()+"/2010Q2_SDK_Overview.pdf"); 
      FileInputStream is = new FileInputStream(file); 

      // Get the size of the file 
      long length = file.length(); 
      bytes = new byte[(int) length]; 
      int offset = 0; 
      int numRead = 0; 
      while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { 
       offset += numRead; 
      } 


      ByteBuffer buffer = ByteBuffer.NEW(bytes); 
      String data = Base64.encodeToString(bytes, Base64.DEFAULT); 
      PDFFile pdf_file = new PDFFile(buffer); 
      PDFPage page = pdf_file.getPage(2); 

      RectF rect = new RectF(0, 0, (int) page.getBBox().width(), 
        (int) page.getBBox().height()); 
      // Bitmap bufferedImage = Bitmap.createBitmap((int)rect.width(), (int)rect.height(), 
      //  Bitmap.Config.ARGB_8888); 

      Bitmap image = page.getImage((int)rect.width(), (int)rect.height(), rect); 
      FileOutputStream os = new FileOutputStream(this.getFilesDir().getAbsolutePath()+"/pdf.jpg"); 
      image.compress(Bitmap.CompressFormat.JPEG, 80, os); 

      //((ImageView) findViewById(R.id.testView)).setImageBitmap(image); 

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

否则,任何其他方式使用应用程序中的功能内置于显示Android的PDF文件?

+0

我们可以使用java.lang中的awt工具将PDF转换为图像,但awt不支持android.i我也使用itext ..如果您知道python u可以使用ghostscript将pdf转换为位图。 – 2012-01-11 06:03:47

+0

我不知道python ..有没有办法在java中做到这一点? – Neela 2012-01-11 06:19:22

+0

请参阅上面的代码..我已经使用从链接的jar,https://github.com/jblough/Android-Pdf-Viewer-Library/blob/master/PdfViewer.jar我能够将PDF页面转换为jpg文件。但转换后的图像部分转换。我不知道我错在哪里? – Neela 2012-01-11 06:25:16

回答

0

我们可以使用Qoppa PDF工具包来完成。

遵循使用Qoppa PDF工具包的步骤。

下载它从http://www.qoppa.com/android/pdfsdk/download

该文件包含四个项目:

  1. version_history.txt - 这个文本文件将与工具包的每个新版本更新。
  2. qoppapdf.jar - 这是该工具包的主要jar文件。这个jar文件需要被添加到您的项目的类路径中。
  3. 资产文件夹 - 此文件夹包含工具包使用的资产,例如字体和图标。从zip文件中提取后,您需要将此文件夹中的文件复制到项目中的assets文件夹中。
  4. libs文件夹 - 此文件夹包含原生Android库,这些库需要解码某些JPEG图像以及Android不支持的JPEG 2000图像。 libs文件夹的内容需要复制到项目中的libs文件夹中。如果您的项目中没有libs文件夹,请创建一个并将该文件夹的内容复制到其中。

代码是:

 //Converting PDF to Bitmap Image... 
     StandardFontTF.mAssetMgr = getAssets(); 
     //Load document to get the first page 
     try { 
      PDFDocument pdf = new PDFDocument("/sdcard/PDFFilename.pdf", null); 
      PDFPage page = pdf.getPage(0); 

      //creating Bitmap and canvas to draw the page into 
      int width = (int)Math.ceil(page.getDisplayWidth()); 
      int height = (int)Math.ceil(page.getDisplayHeight()); 

      Bitmap bm = Bitmap.createBitmap(width, height, Config.ARGB_8888); 
      Canvas c = new Canvas(bm); 
      page.paintPage(c); 

      //Saving the Bitmap 
      OutputStream os = new FileOutputStream("/sdcard/GeneratedImageByQoppa.jpg"); 
      bm.compress(CompressFormat.JPEG, 80, os); 
      os.close(); 
     } catch (PDFException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
+0

这种有点作品,但它不是100%,它在页面上放置水印。 – 2013-04-30 06:22:30

+0

为了得不到水印,你必须购买付费版本。 – Jagadeesh 2013-05-16 06:33:23

+0

我已经做了一个免费的图书馆。 – 2013-05-16 06:49:17

28

我解决了这个问题。它就像让设备有时间呈现每个页面一样简单。

为了解决这个问题,所有您需要做的是改变

PDFPage page = pdf_file.getPage(2); 

PDFPage page = pdf_file.getPage(2, true); 

首先在Android中查看PDF文档,你必须将PDF转换成图像,然后将它们显示给用户。 (我打算使用webview)

所以要做到这一点,我们需要这个library。这是我编辑的git版本。

将库导入到项目后,您需要创建活动。

的XML:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <WebView 
      android:id="@+id/webView1" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"/> 

</LinearLayout> 

化java:

//Imports: 
import android.app.Activity; 
import android.app.ProgressDialog; 
import android.content.Intent; 
import android.graphics.Bitmap; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Environment; 
import android.util.Base64; 
import android.util.Log; 
import android.view.View; 
import android.view.ViewTreeObserver; 
import android.webkit.WebView; 
import com.sun.pdfview.PDFFile; 
import com.sun.pdfview.PDFImage; 
import com.sun.pdfview.PDFPage; 
import com.sun.pdfview.PDFPaint; 
import net.sf.andpdf.nio.ByteBuffer; 
import net.sf.andpdf.refs.HardReference; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.RandomAccessFile; 
import java.nio.channels.FileChannel; 

//Globals: 
private WebView wv; 
private int ViewSize = 0; 

//OnCreate Method: 
@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    //Settings 
    PDFImage.sShowImages = true; // show images 
    PDFPaint.s_doAntiAlias = true; // make text smooth 
    HardReference.sKeepCaches = true; // save images in cache 

    //Setup webview 
    wv = (WebView)findViewById(R.id.webView1); 
    wv.getSettings().setBuiltInZoomControls(true);//show zoom buttons 
    wv.getSettings().setSupportZoom(true);//allow zoom 
    //get the width of the webview 
    wv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() 
    { 
     @Override 
     public void onGlobalLayout() 
     { 
      ViewSize = wv.getWidth(); 
      wv.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
     } 
    }); 

    try 
    { 
     File file = new File(Environment.getExternalStorageDirectory().getPath() + "/randompdf.pdf"); 
     RandomAccessFile f = new RandomAccessFile(file, "r"); 
     byte[] data = new byte[(int)f.length()]; 
     f.readFully(data); 
     pdfLoadImages(data); 
    } 
    catch(Exception ignored) 
    { 
    } 
} 

//Load Images: 
private void pdfLoadImages(final byte[] data) 
{ 
    try 
    { 
     // run async 
     new AsyncTask<Void, Void, String>() 
     { 
      // create and show a progress dialog 
      ProgressDialog progressDialog = ProgressDialog.show(MainActivity.this, "", "Opening..."); 

      @Override 
      protected void onPostExecute(String html) 
      { 
       //after async close progress dialog 
       progressDialog.dismiss(); 
       //load the html in the webview 
       wv.loadDataWithBaseURL("", html, "text/html","UTF-8", ""); 
      } 

      @Override 
      protected String doInBackground(Void... params) 
      { 
       try 
       { 
        //create pdf document object from bytes 
        ByteBuffer bb = ByteBuffer.NEW(data); 
        PDFFile pdf = new PDFFile(bb); 
        //Get the first page from the pdf doc 
        PDFPage PDFpage = pdf.getPage(1, true); 
        //create a scaling value according to the WebView Width 
        final float scale = ViewSize/PDFpage.getWidth() * 0.95f; 
        //convert the page into a bitmap with a scaling value 
        Bitmap page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true); 
        //save the bitmap to a byte array 
        ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
        page.compress(Bitmap.CompressFormat.PNG, 100, stream); 
        byte[] byteArray = stream.toByteArray(); 
        stream.reset(); 
        //convert the byte array to a base64 string 
        String base64 = Base64.encodeToString(byteArray, Base64.NO_WRAP); 
        //create the html + add the first image to the html 
        String html = "<!DOCTYPE html><html><body bgcolor=\"#b4b4b4\"><img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>"; 
        //loop though the rest of the pages and repeat the above 
        for(int i = 2; i <= pdf.getNumPages(); i++) 
        { 
         PDFpage = pdf.getPage(i, true); 
         page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true); 
         page.compress(Bitmap.CompressFormat.PNG, 100, stream); 
         byteArray = stream.toByteArray(); 
         stream.reset(); 
         base64 = Base64.encodeToString(byteArray, Base64.NO_WRAP); 
         html += "<img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>"; 
        } 
        stream.close(); 
        html += "</body></html>"; 
        return html; 
       } 
       catch (Exception e) 
       { 
        Log.d("error", e.toString()); 
       } 
       return null; 
      } 
     }.execute(); 
     System.gc();// run GC 
    } 
    catch (Exception e) 
    { 
     Log.d("error", e.toString()); 
    } 
} 
+0

此解决方案可以工作,但图像不会在位图中绘制,即使'.sShowImages'set为'true',以及您的图库版本。你知道为什么会发生这种情况吗? – Agos 2013-06-27 14:20:59

+0

我已经下载了您的图书馆,现在请告诉我,您使用的是什么进口? – 2013-07-09 17:05:09

+0

为什么不使用IDE附带的添加缺少导入功能? – 2013-07-09 17:29:16

2

这个问题是有点老了,但我今天不得不做的一样,所以这是我的解决方案:

/** 
* Use this to load a pdf file from your assets and render it to a Bitmap. 
* 
* @param context 
*   current context. 
* @param filePath 
*   of the pdf file in the assets. 
* @return a bitmap. 
*/ 
@Nullable 
public static Bitmap renderToBitmap(Context context, String filePath) { 
    Bitmap bi = null; 
    InputStream inStream = null; 
    try { 
     AssetManager assetManager = context.getAssets(); 
     Log.d(TAG, "Attempting to copy this file: " + filePath); 
     inStream = assetManager.open(filePath); 
     bi = renderToBitmap(context, inStream); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      inStream.close(); 
     } catch (IOException e) { 
      // do nothing because the stream has already been closed 
     } 
    } 
    return bi; 
} 

/** 
* Use this to render a pdf file given as InputStream to a Bitmap. 
* 
* @param context 
*   current context. 
* @param inStream 
*   the inputStream of the pdf file. 
* @return a bitmap. 
* @see https://github.com/jblough/Android-Pdf-Viewer-Library/ 
*/ 
@Nullable 
public static Bitmap renderToBitmap(Context context, InputStream inStream) { 
    Bitmap bi = null; 
    try { 
     byte[] decode = IOUtils.toByteArray(inStream); 
     ByteBuffer buf = ByteBuffer.wrap(decode); 
     PDFPage mPdfPage = new PDFFile(buf).getPage(0); 
     float width = mPdfPage.getWidth(); 
     float height = mPdfPage.getHeight(); 
     RectF clip = null; 
     bi = mPdfPage.getImage((int) (width), (int) (height), clip, true, 
       true); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      inStream.close(); 
     } catch (IOException e) { 
      // do nothing because the stream has already been closed 
     } 
    } 
    return bi; 
} 

此外,我正在使用此library。而我的PDF文件只包含一个页面,并且是一个图像,可能在其他情况下,您必须更新您的代码。

我希望这会帮助别人。

+0

嗨,有没有像这样的图书馆,而不是点击按钮上一页和下一页用户可以滚动页面之间的PDF?我正在使用相同的库。 – 2016-04-10 00:45:36

+0

抱歉,我不知道,我只需要将PDF图像转换为位图。我建议创建一个关于pdf分页的新问题...祝你好运。 – 2016-04-11 11:18:38

+1

很多感谢你的,代码工作与LIB https://github.com/jblough/Android-Pdf-Viewer-Library/ – NickUnuchek 2018-01-31 21:43:00

0

这是代码,希望它有帮助。我设法使所有页面进入Bitmap.Cheers

try { 
     pdfViewer = (ImageView) findViewById(R.id.pdfViewer); 
     int x = pdfViewer.getWidth(); 
     int y = pdfViewer.getHeight(); 
     Bitmap bitmap = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_4444); 
     String StoragePath= Environment.getExternalStorageDirectory()+ "/sample.pdf"; 
     File file = new File(StoragePath); 
     PdfRenderer renderer = new PdfRenderer(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)); 
     if (currentPage < 0) { 
      currentPage = 0; 
     } else if (currentPage > renderer.getPageCount()) { 
     } 


     Matrix m = pdfViewer.getImageMatrix(); 
     Rect r = new Rect(0, 0, x, y); 
     renderer.openPage(currentPage).render(bitmap, r, m, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY); 
     pdfViewer.setImageMatrix(m); 
     pdfViewer.setImageBitmap(bitmap); 
     pdfViewer.invalidate(); 


    } catch (Exception ex) { 
     Log.v(TAG, ex.getMessage()); 
    } finally { 

    } 
+0

你的代码不支持api 19以下的版本 – Vicky 2017-06-07 08:37:09

2

我知道这个问题是旧的,但我上周就遇到了这个问题,并没有一个答案确实为我工作。

下面是我如何解决这个问题,而不使用第三方库。

基于使用Android的PDFRenderer类(API 21+)Android开发者site的代码,我写了下面的方法:

private ArrayList<Bitmap> pdfToBitmap(File pdfFile) { 
    ArrayList<Bitmap> bitmaps = new ArrayList<>(); 

    try { 
     PdfRenderer renderer = new PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)); 

     Bitmap bitmap; 
     final int pageCount = renderer.getPageCount(); 
     for (int i = 0; i < pageCount; i++) { 
      PdfRenderer.Page page = renderer.openPage(i); 

      int width = getResources().getDisplayMetrics().densityDpi/72 * page.getWidth(); 
      int height = getResources().getDisplayMetrics().densityDpi/72 * page.getHeight(); 
      bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 

      page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY); 

      bitmaps.add(bitmap); 

      // close the page 
      page.close(); 

     } 

     // close the renderer 
     renderer.close(); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 

    return bitmaps; 

} 

该方法返回位图的数组,一个位图中的每一页pdf文件。

高度和宽度根据this answer计算以创建更高质量的图像。