2012-01-11 91 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計算以創建更高質量的圖像。