Reputation: 488
I am developing an application where I need to convert an Image to PDF. I tried something, but the issue is, Image size in that PDF is very very small. I need solution to fix this. Also I am looking for converting multiple Images into single PDF document. I will post the code which I tried.
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();
}
}
When I convert Bitmap to Byte array, I am compressing the image and I guess, that's the reason. Without compressing the image, I am unable to convert Bitmap to Byte Array.
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG,100,stream);
byte[] byteArray=stream.toByteArray();
convertPDF(byteArray);
Is there any solution for this?
UPDATED
Here I have implemented the answer which suggested by @Burak Cakir in the answer. But now I am getting larger image in PDF. For better understanding, Please find the images below.
Upvotes: 22
Views: 59676
Reputation: 564
this is how I convert image into pdf very easy , you need to declare the user permission first in the manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
then in your main activity, you must check for permission is granted or not if you don't know how to do it just search on youtube you will find a lot of videos about that topic, after that, I use this method to pic image that i want to convert into pdf from the gallery.
public void pickImage() {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent,120);
}
After that I override the onActivityResult() method to retrieve the selected image .
@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();
}
}
don't forget the permission and ask the user to grant the permission
If you want to open pdf file automatically use this method after given the right path to the folder and pdf file name
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();
}
}
Upvotes: 0
Reputation: 883
Just pass context and list of file It will create a PDF file in cache dir Add your own logic to share/open PDF Works fast and reliable method
- No library needed (Uses android internal android.graphics.pdf.PdfDocument classes)
- Works in background, Doesn''t freeze UI
- No need to declare and grant storage permission :)
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();
}
Upvotes: 6
Reputation: 761
Add library in gradle
implementation 'com.itextpdf:itextg:5.5.10'
Create folder path - it will create pdf from all images of folder
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();
AsyncTask
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();
}
}
Upvotes: 1
Reputation: 928
I would suggest you to use iText
pdf library. Here is the gradle
dependency:
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();
Upvotes: 25
Reputation: 771
You can convert a JPG to a PDF by targeting a minimum SDK of 19 (KitKat 4.4) and using Google's PdfDocument API ( https://developer.android.com/reference/android/graphics/pdf/PdfDocument ), as shown below in 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()
Upvotes: 17
Reputation: 2094
Download source code from here (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();
}
}
}
}
Thanks!
Upvotes: 19