Вопрос по java, android, pdf – Как преобразовать страницу PDF в изображение в Android?

20

Все, что мне нужно сделать, это взять (локально сохранено)PDF-document а такжеconvert one or all of it's pages to image формат как JPG или PNG.

Я испробовал множество решений для рендеринга и просмотра PDF, таких какAPV PDF Viewer, APDFViewer, droidreader, Android-PDF, MuPdf и многие другие, но до сих пор не могли понять, чтоhow to convert a pdf-page into image?.

РЕДАКТИРОВАТЬ: Кроме того, я предпочитаю иметь конвертер PDF в изображение, а не рендер PDF, который мне нужно отредактировать для преобразования PDF в изображение.

Ты получилthose guys которые могут сделать это для вас, у них есть собственный API, так что если у вас есть подключение к Интернету, это будет делать, если нет ... Вы должны взломать их, потому что они делают действительно большую работу;) Ilya Gazman
Я не разработчик Android, но мой поиск в Интернете только сейчас обнаружил, чтоImageMagick has been ported to this platform, Возможно, стоит пойти? halfer
хммм я не проверял но если кто-нибудь подтвердит то я удалю этот ответ. Shankar Agarwal
@AgarwalShankar, не уверен, что вы сами проверили этот код.This is not gonna to work. Зачем?because the core class PDFImageWriter used in this code has dependency on java.awt.* class, проверитьsource code сам. Я надеюсь, что вы или люди, которые проголосуют за это, могут сказать мне, что я не прав, исходя из моих базовых знаний:Java awt is not supported by Android. yorkw

Ваш Ответ

6   ответов
1

В конце концов я нашел очень простое решение для этого, Скачать библиотеку сВот.

Используйте код ниже, чтобы получить изображения из 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-карте. Пожалуйста, дайте мне знать, если вам нужна помощь.

хорошо, я понял, библиотека pdfview не поддерживает
Вы можете добавить пароль в классе pdfContext следующим способом: public CodecDocument openDocument (String fileName) {return PdfDocument.openDocument (fileName, mPassword); }
извините, бхай ... не могу помочь вам с защитой паролем pdf.
работает нормально, но исключение при открытии защищенного паролем pdf pls help @ dd619
2

Используйте библиотеку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;
    }
8

Вам нужно взглянуть на этот проект с открытым исходным кодом для того же требования, которое может быть полезным для вас, чтобы сделать еще много вещей.

Проект:PdfRenderer

Существует один класс Java с именемPDFPage.java вpdfview пакет. у этого класса есть метод для получения изображения страницы.

Я также реализовал то же самое в моем тестовом проекте, и код Javahere for you, Я создал один методshowPage который принимает номер страницы и уровень масштабирования и возвращает эту страницу какBitmap.

Надеюсь, это поможет вам. Вам просто нужно получить этот проект или JAR для этого, прочитайте хорошо документированный JAVADOC для того же, а затем попытайтесь реализовать то же самое, что и я.

Не торопитесь, Happy Coding :)

Да я добавилpdf-renderer-1.0.5.jar к пути сборки. это ошибка, которую я получаю заRectangle2D: The type java.awt.geom.Rectangle2D cannot be resolved. It is indirectly referenced from required .class files и я получаю ту же ошибку для классов, упомянутых в моем предыдущем комментарии Pieter888
попробуй это:stackoverflow.com/a/16294833/2027232
Я пытаюсь использовать созданный вами метод showPage. Но у меня возникли проблемы со строкой 93 пастбина, который вы выложили. По-видимомуPDFPage пытается использовать некоторые классы (Rectangle2D, ImageObserver, Image) отjava.awt.geom которые не поддерживаются Android. Как ты получил это работает? Pieter888
Здравствуйте, MKJParekh. Я уже перепробовал так много решений, и я думаю, что большинство стековых решений для PDF в изображение, но не нашел подходящего пути. Я не смог найти ни одной бесплатной библиотеки (jar) для PDF для изображения. и как реализовать эту банку на моем классе деятельности ...? пожалуйста, чтобы вести меня ...
Спасибо за ответ, я проверю его прямо сейчас. Pieter888
6

Начиная с Android API 21PdfRenderer это то, что вы ищете.

Просто для справки, PdfRenderer не поддерживает пользовательский шрифт и стиль. Пожалуйста, посмотрите на этоgithub.com/googlesamples/android-PdfRendererBasic/issues/18
Как поддерживать более низкую версию API до 14?
1

Я скажу вам простой трюк, а не полное решение. Как только вы успешно отрендерили страницу 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());
}

Это все, надеюсь, вы поможете этому.

9

Для поддержки 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 или что-то подобное, поскольку довольно много методов требуют вычислений или времени ввода-вывода (я отметил их в комментариях).

Я действительно очень быстрый и работает, как и ожидалось. Это займет около 17 секунд только для преобразования 12 страниц PDF с тяжелыми изображениями в формате PDF. Спасибо человеку за отличный пост.
он работает нормально, но исключение при открытии защищен паролем pdf любая помощь @ vedant1811
@EbinJoy У меня были похожие сомнения, но в нынешнем виде он отлично работает. Просто у нас, вероятно, не будет больше возможностей в будущем
Этот проект больше не поддерживается.
Это очень полезно и работает очень эффективно.

Похожие вопросы