我需要做的就是获取一个(本地保存的)PDF-document
并将其中的一个或所有页面转换为JPG 或 PNG 等图像格式。
我已经尝试了很多 PDF 渲染/查看解决方案,例如APV PDF Viewer、APDFViewer、droidreader、android-pdf、MuPdf等等,但到目前为止还没有弄清楚如何将 pdf 页面转换为图像?.
编辑:另外,我宁愿拥有一个 PDF 到图像转换器,而不是一个我需要编辑以将 PDF 转换为图像的 PDF 渲染器。
我需要做的就是获取一个(本地保存的)PDF-document
并将其中的一个或所有页面转换为JPG 或 PNG 等图像格式。
我已经尝试了很多 PDF 渲染/查看解决方案,例如APV PDF Viewer、APDFViewer、droidreader、android-pdf、MuPdf等等,但到目前为止还没有弄清楚如何将 pdf 页面转换为图像?.
编辑:另外,我宁愿拥有一个 PDF 到图像转换器,而不是一个我需要编辑以将 PDF 转换为图像的 PDF 渲染器。
要支持 API 8 及更高版本,请执行以下操作:
使用此库:android-pdfview和以下代码,您可以可靠地将 PDF 页面转换为图像(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);
}
}
你应该在后台完成这项工作,即使用一个AsyncTask
或类似的东西,因为相当多的方法需要计算或 IO 时间(我在评论中标记了它们)。
您需要查看此项目的开源项目以获得相同的要求,这也有助于您做更多的事情。
项目:PdfRenderer
包中有一个名为PDFPage.java的Java 类pdfview
。该类有一个方法来获取页面的图像。
我也在我的测试项目中实现了同样的东西,Java 代码就在这里。我创建了一种方法showPage
,它接受页面编号和缩放级别并将该页面返回为Bitmap
.
希望这可以帮到你。您只需要为此获取该项目或 JAR,阅读文档齐全的 JAVADOC 以获得相同的内容,然后尝试像我一样实现相同的内容。
慢慢来,快乐编码 :)
从 Android API 21 PdfRenderer开始就是你要找的东西。
使用库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;
}
从下面的代码中,您可以使用 PDFRender 从 PDF 中将所有页面提取为图像 (PNG) 格式:
// 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();
}
}
}
您可以通过以下方式调用此方法:
// 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();
}
干杯!
我会说你一个简单的技巧不是一个完整的解决方案。一旦你成功渲染了 pdf 页面,你将从屏幕上得到它的位图,如下所示
View view = MuPDFActivity.this.getWindow().getDecorView();
if (false == view.isDrawingCacheEnabled()) {
view.setDrawingCacheEnabled(true);
}
Bitmap bitmap = view.getDrawingCache();
然后你可以保存这个位图,也就是你的pdf页面作为图片保存在本地
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());
}
就是这样,希望你能帮助这个。
使用 AppCompat 等 Android 默认库,您可以将所有 PDF 页面转换为图像。这种方式非常快速且经过优化。以下代码用于获取 PDF 页面的单独图像。这是非常快速和快速的。
我已经实现如下:
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;
}
我已经在另一个问题中发布了它:P
最后我找到了非常简单的解决方案,从这里下载库。
使用以下代码从 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;
}
}
您可以在图库或 SD 卡中查看转换后的图像。如果您需要任何帮助,请告诉我。
在经历并尝试了所有答案之后,对于所有 PDF 文件,没有一个对我有用。自定义字体 PDF 文件中存在渲染问题。然后我尝试使用library。我从 NickUncheck 的从所有 PDF 页面获取图像的答案中获得灵感。
代码如下:
在您的应用程序 build.gradle 文件中添加以下依赖项:
implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'
PDF页面转图片的代码:
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;
}
到目前为止,我尝试过的所有 PDF 文件都适用于我。