【问题标题】:How to convert Image to PDF?如何将图像转换为PDF?
【发布时间】:2016-07-18 06:02:34
【问题描述】:

我正在开发一个需要将图像转换为 PDF 的应用程序。我尝试了一些方法,但问题是,该 PDF 中的图像尺寸非常小。我需要解决方案来解决这个问题。我也在寻找将多个图像转换为单个 PDF 文档。 我将发布我尝试过的代码。

    public void convertPDF(byte[] path)
{
 String FILE = "mnt/sdcard/FirstPdf.pdf";
    Document document=new Document();
    try {
        PdfWriter.getInstance(document, new FileOutputStream(FILE));
        document.open();

        try {
            image=Image.getInstance(path);
            document.add(new Paragraph("My Heading"));
            document.add(image);
            document.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    } catch (DocumentException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
}

当我将位图转换为字节数组时,我正在压缩图像,我猜这就是原因。如果不压缩图像,我无法将位图转换为字节数组。

 ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG,100,stream);
        byte[] byteArray=stream.toByteArray();
        convertPDF(byteArray);

有什么解决办法吗?

更新

在这里,我已经实现了@Burak Cakir 在答案中建议的答案。但现在我在 PDF 中获得了更大的图像。为了更好地理解,请找到下面的图片。

实际的图像是

【问题讨论】:

标签: android android-image android-bitmap android-pdf-api


【解决方案1】:

我建议你使用iText pdf 库。这是gradle 依赖:

implementation 'com.itextpdf:itextg:5.5.10'

 Document document = new Document();

 String directoryPath = android.os.Environment.getExternalStorageDirectory().toString();

 PdfWriter.getInstance(document, new FileOutputStream(directoryPath + "/example.pdf")); //  Change pdf's name.

 document.open();

 Image image = Image.getInstance(directoryPath + "/" + "example.jpg");  // Change image's name and extension.

 float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
               - document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it.
 image.scalePercent(scaler);
 image.setAlignment(Image.ALIGN_CENTER | Image.ALIGN_TOP); 

 document.add(image);
 document.close();

【讨论】:

  • 我试过代码。部分工作,现在图像太大了。请找到更新的问题。我发布了几张图片
  • 但是,它因图片而异。如果我从相机中选择图像,则对齐不正确。如果我选择不同质量的不同图像,对齐方式也会不同。如何动态解决此问题?
  • 我不知道为什么它对另一个图像有任何影响。无论如何,您可以使用 setAlignment 方法修复它。再次更新,请检查答案。
  • @Suman,当您在 iText 中缩放 Image 对象时,您不会丢失任何信息:像素数保持不变。虽然 PDF 没有分辨率,但 PDF 中的图像有。当您缩小图像时(即:将相同数量的像素放在较小的画布上),分辨率会增加;放大时,分辨率会降低。所以质量是一样的,分辨率取决于图像大小和文档页面大小。
  • 如您所知,它现在是实施 'com.itextpdf:itextpdf:5.5.13'
【解决方案2】:

从这里下载源代码 (Convert Image to pdf in android programmatically)

MainActivity.java:

package com.deepshikha.convertbitmap;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.pdf.PdfDocument;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    public static final int GALLERY_PICTURE = 1;
    Button btn_select, btn_convert;
    ImageView iv_image;
    boolean boolean_permission;
    boolean boolean_save;
    Bitmap bitmap;
    public static final int REQUEST_PERMISSIONS = 1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        listener();
        fn_permission();
    }

    private void init() {
        btn_select = (Button) findViewById(R.id.btn_select);
        btn_convert = (Button) findViewById(R.id.btn_convert);
        iv_image = (ImageView) findViewById(R.id.iv_image);
    }

    private void listener() {
        btn_select.setOnClickListener(this);
        btn_convert.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_select:
                Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(intent, GALLERY_PICTURE);
                break;

            case R.id.btn_convert:
                if (boolean_save){

                    Intent intent1=new Intent(getApplicationContext(),PDFViewActivity.class);
                    startActivity(intent1);

                }else {
                    createPdf();
                }
                break;


        }
    }

    private void createPdf(){
        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        DisplayMetrics displaymetrics = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        float hight = displaymetrics.heightPixels ;
        float width = displaymetrics.widthPixels ;

        int convertHighet = (int) hight, convertWidth = (int) width;

//        Resources mResources = getResources();
//        Bitmap bitmap = BitmapFactory.decodeResource(mResources, R.drawable.screenshot);

        PdfDocument document = new PdfDocument();
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), 1).create();
        PdfDocument.Page page = document.startPage(pageInfo);

        Canvas canvas = page.getCanvas();


        Paint paint = new Paint();
        paint.setColor(Color.parseColor("#ffffff"));
        canvas.drawPaint(paint);



        bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);

        paint.setColor(Color.BLUE);
        canvas.drawBitmap(bitmap, 0, 0 , null);
        document.finishPage(page);


        // write the document content
        String targetPdf = "/sdcard/test.pdf";
        File filePath = new File(targetPdf);
        try {
            document.writeTo(new FileOutputStream(filePath));
            btn_convert.setText("Check PDF");
            boolean_save=true;
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Something wrong: " + e.toString(), Toast.LENGTH_LONG).show();
        }

        // close the document
        document.close();
    }



    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == GALLERY_PICTURE && resultCode == RESULT_OK) {

            if (resultCode == RESULT_OK) {
                Uri selectedImage = data.getData();
                String[] filePathColumn = {MediaStore.Images.Media.DATA};

                Cursor cursor = getContentResolver().query(
                        selectedImage, filePathColumn, null, null, null);
                cursor.moveToFirst();

                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                String filePath = cursor.getString(columnIndex);
                cursor.close();


                bitmap = BitmapFactory.decodeFile(filePath);
                iv_image.setImageBitmap(bitmap);


                btn_convert.setClickable(true);
            }
        }
    }

    private void fn_permission() {
        if ((ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)||
                (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {

            if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.READ_EXTERNAL_STORAGE))) {
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
                        REQUEST_PERMISSIONS);

            }

            if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE))) {
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        REQUEST_PERMISSIONS);

            }
        } else {
            boolean_permission = true;


        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERMISSIONS) {

            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                boolean_permission = true;


            } else {
                Toast.makeText(getApplicationContext(), "Please allow the permission", Toast.LENGTH_LONG).show();

            }
        }
    }


}

谢谢!

【讨论】:

  • 感谢代码,我试过了,它可以工作!但图像质量很差。我使用相机意图获取位图而不是选择文件。对于质量,可能是因为您在执行该操作时调整了位图的大小 bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);
  • 最终,这段代码非常适合我。我有一张使用滚动视图创建的图像,因为它是平板电脑,所以它的分辨率超过 3000 * 10000。接受的答案只打印出图像的一部分,但这个解决方案打印出所有内容。
  • 能否请您更新上面的源代码链接,它无法访问,或者可以建议任何适当的教程来创建适用于 android 的图像到 pdf 转换器应用程序
【解决方案3】:

您可以将 JPG 转换为 PDF,方法是使用至少 19 个 SDK (KitKat 4.4) 并使用 Google 的 PdfDocument API (https://developer.android.com/reference/android/graphics/pdf/PdfDocument),如下面的 Kotlin 所示:

    // Load JPG file into bitmap
    val f: File = myJPGFile
    val bitmap: Bitmap  = BitmapFactory.decodeFile(f.absolutePath)

    // Create a PdfDocument with a page of the same size as the image
    val document: PdfDocument = PdfDocument()
    val pageInfo: PdfDocument.PageInfo  = PdfDocument.PageInfo.Builder(bitmap.width, bitmap.height, 1).create()
    val page: PdfDocument.Page  = document.startPage(pageInfo)

    // Draw the bitmap onto the page
    val canvas: Canvas = page.canvas
    canvas.drawBitmap(bitmap, 0f, 0f, null)
    document.finishPage(page)

    // Write the PDF file to a file
    val directoryPath: String  = android.os.Environment.getExternalStorageDirectory().toString()
    document.writeTo( FileOutputStream(directoryPath + "/example.pdf"))
    document.close()

【讨论】:

    【解决方案4】:

    只需传递上下文和文件列表 它将在缓存目录中创建一个 PDF 文件 添加您自己的逻辑以共享/打开 PDF 工作快速可靠的方法

    • 无需库(使用 android 内部 android.graphics.pdf.PdfDocument 类)
    • 在后台工作,不会冻结 UI
    • 无需声明和授予存储权限:)
    private static void createPdf(Context context,ArrayList<File> data){
        File pdfFile = new File(context.getExternalCacheDir().getAbsolutePath() + File.separator + "TemperoryPDF_"+System.currentTimeMillis()+".pdf");
        Toast.makeText(context, "Creating PDF,Please wait..", Toast.LENGTH_SHORT).show();
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... voids) {
                PdfDocument document = new PdfDocument();
                try {
                    for(File item:data) {
                        Bitmap bitmap = BitmapFactory.decodeFile(item.getAbsolutePath());
                        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), 1).create();
                        PdfDocument.Page page = document.startPage(pageInfo);
                        Canvas canvas = page.getCanvas();
                        Paint paint = new Paint();
                        paint.setColor(Color.parseColor("#ffffff"));
                        canvas.drawPaint(paint);
                        canvas.drawBitmap(bitmap, 0, 0, null);
                        document.finishPage(page);
                    }
                    document.writeTo(new FileOutputStream(pdfFile));
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    document.close();
                }
                return null;
            }
    
            @Override
            protected void onPostExecute(Void unused) {
                super.onPostExecute(unused);
                if(pdfFile.exists() && pdfFile.length()>0) {
                    FileUtil.openFile(context, pdfFile.getAbsolutePath()); // See: https://gist.github.com/omkar-tenkale/34d3aa1966653e6949d1ddaee1ba3355
                }else {
                    Toast.makeText(context, "Something went wrong creating the PDF :(", Toast.LENGTH_SHORT).show();
                }
            }
        }.execute();
    
    }
    

    【讨论】:

    • 在 android 12 上测试,工作正常
    • 非常感谢,正是我想要的:)
    【解决方案5】:

    在 gradle 中添加库

    implementation 'com.itextpdf:itextg:5.5.10'
    

    创建文件夹路径 - 它将从文件夹的所有图像创建 pdf

    File folderPath = new File(Environment.getExternalStorageDirectory() + "/YourImagesFolder");
    
    File[] imageList = folderPath .listFiles();
    ArrayList<File> imagesArrayList = new ArrayList<>();
    for (File absolutePath : imageList) {
              imagesArrayList.add(absolutePath);
    }
    new CreatePdfTask(context, imagesArrayList).execute();
    

    异步任务

     public class CreatePdfTask extends AsyncTask<String, Integer, File> {
        Context context;
        ArrayList<File> files;
        ProgressDialog progressDialog;
    
        public CreatePdfTask(Context context2, ArrayList<File> arrayList) {
            context = context2;
            files = arrayList;
        }
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog = new ProgressDialog(context);
            progressDialog.setTitle("Please wait...");
            progressDialog.setMessage("Creating pdf...");
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.setIndeterminate(false);
            progressDialog.setMax(100);
            progressDialog.setCancelable(true);
            progressDialog.show();
        }
    
        @Override
        protected File doInBackground(String... strings) {
            File outputMediaFile = Constant.getPdfPath();//path in which you want to save pdf
    
            Document document = new Document(PageSize.A4, 38.0f, 38.0f, 50.0f, 38.0f);
            try {
                PdfWriter.getInstance(document, new FileOutputStream(outputMediaFile));
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return null;
            }
            document.open();
    
            int i = 0;
            while (true) {
                if (i < this.files.size()) {
                    try {
                        Image image = Image.getInstance(files.get(i).getAbsolutePath());
    
                        float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
                                - document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it.
                        image.scalePercent(scaler);
                        image.setAlignment(Image.ALIGN_CENTER | Image.ALIGN_TOP);
                        image.setAbsolutePosition((document.getPageSize().getWidth() - image.getScaledWidth()) / 2.0f,
                                (document.getPageSize().getHeight() - image.getScaledHeight()) / 2.0f);
    
                        document.add(image);
                        document.newPage();
                        publishProgress(i);
                        i++;
                    } catch (BadElementException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (DocumentException e) {
                        e.printStackTrace();
                    }
                } else {
                    document.close();
                    return outputMediaFile;
                }
            }
        }
    
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            this.progressDialog.setProgress(((values[0] + 1) * 100) / this.files.size());
            StringBuilder sb = new StringBuilder();
            sb.append("Processing images (");
            sb.append(values[0] + 1);
            sb.append("/");
            sb.append(this.files.size());
            sb.append(")");
            progressDialog.setTitle(sb.toString());
        }
    
        @Override
        protected void onPostExecute(File file) {
            super.onPostExecute(file);
            progressDialog.dismiss();
            Toast.makeText(context, "Pdf store at " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
        }
    }
    

    【讨论】:

    • 如果你按照他们的许可使用这个库,你必须让你的应用开源!!!!
    【解决方案6】:

    这就是我将图片转换成pdf的方法,你需要先在manifest中声明用户权限

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    

    然后在您的主要活动中,您必须检查是否已授予权限,如果您不知道该怎么做,只需在 youtube 上搜索,您会发现很多关于该主题的视频,然后,我使用此方法将我想从图库中转换为 pdf 的图片。

    public void pickImage() {
        Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent,120);
    }
    

    之后我重写 onActivityResult() 方法来检索所选图像。

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 120 && resultCode == RESULT_OK && data != null) {
            Uri selectedImageUri = data.getData();
    
            String[] filePath = {MediaStore.Images.Media.DATA};
            Cursor cursor =getContentResolver().query(selectedImageUri,filePath,null,null,null);
            cursor.moveToFirst();
    
            int columnIndex = cursor.getColumnIndex(filePath[0]);
            String myPath = cursor.getString(columnIndex);
            cursor.close();
    
            Bitmap bitmap = BitmapFactory.decodeFile(myPath);
            imageView.setImageBitmap(bitmap);
    
            PdfDocument pdfDocument = new PdfDocument();
            PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(),
                    bitmap.getHeight(),1).create();
            PdfDocument.Page page = pdfDocument.startPage(pageInfo);
    
            Canvas canvas = page.getCanvas();
            Paint paint = new Paint();
            paint.setColor(Color.parseColor("#FFFFFF"));
            canvas.drawPaint(paint);
    
            bitmap=Bitmap.createScaledBitmap(bitmap,bitmap.getWidth(),bitmap.getHeight(),true);
            paint.setColor(Color.BLUE);
            canvas.drawBitmap(bitmap,0,0,null);
    
            pdfDocument.finishPage(page);
    
            //save the bitmap image
            File root = new File(Environment.getExternalStorageDirectory(),"PDF folder 12");
            if (!root.exists()){
                root.mkdir();
            }
            File file = new File(root,"picture.pdf");
            try {
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                pdfDocument.writeTo(fileOutputStream);
            }catch (Exception e){
                e.getStackTrace();
            }
            pdfDocument.close();
        }
    }
    

    不要忘记权限,请用户授予权限

    如果要自动打开pdf文件,请在给出正确的文件夹路径和pdf文件名后使用此方法

     String path ="/sdcard/PDF folder 12/picture.pdf";
    public void openPDF (){
        File pdfFile = new File(path);//File path
        if (pdfFile.exists()) //Checking if the file exists or not
        {
            Uri path = Uri.fromFile(pdfFile);
            Intent objIntent = new Intent(Intent.ACTION_VIEW);
            objIntent.setDataAndType(path, "application/pdf");
            objIntent.setFlags(Intent. FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(objIntent);//Starting the pdf viewer
        } else {
    
            Toast.makeText(GenerateQRActivity.this, "The file not exists! ", Toast.LENGTH_SHORT).show();
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 2020-06-28
      • 2014-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-07
      相关资源
      最近更新 更多