i have a pdf file(attached).
My objective is to convert a pdf to an image using pdfbox AS IT IS,(same as using snipping tool in windows).
The pdf has all kinds of shapes and text .
i am using the following code:
PDDocument doc = PDDocument.load("Hello World.pdf");
PDPage firstPage = (PDPage) doc.getDocumentCatalog().getAllPages().get(67);
BufferedImage bufferedImage = firstPage.convertToImage(imageType,screenResolution);
ImageIO.write(bufferedImage, "png",new File("out.png"));
when i use the code, the image file gives totally wrong outputs(out.png attached)
how do i make pdfbox take something like a direct snapshot image?
also, i noticed that the image quality of the png is not so good, is there any way to increase the resolution of the generated image?
EDIT:
here is the pdf(see page number 68)
https://drive.google.com/file/d/0B0ZiP71EQHz2NVZUcElvbFNreEU/edit?usp=sharing
EDIT 2:
it seems that all the text isvanishing.
i also tried using the PDFImageWriter class
test.writeImage(doc, "png", null, 68, 69, "final.png",TYPE_USHORT_GRAY,200 );
same result
Using PDFRenderer it is possible to convert PDF page into image formats.
Convert PDF page into image in java Using PDF Renderer. Jars Required PDFRenderer-0.9.0
package com.pdfrenderer.examples;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import javax.imageio.ImageIO;
import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFPage;
public class PdfToImage {
public static void main(String[] args) {
try {
String sourceDir = "C:/Documents/Chemistry.pdf";// PDF file must be placed in DataGet folder
String destinationDir = "C:/Documents/Converted/";//Converted PDF page saved in this folder
File sourceFile = new File(sourceDir);
File destinationFile = new File(destinationDir);
String fileName = sourceFile.getName().replace(".pdf", "_cover");
if (sourceFile.exists()) {
if (!destinationFile.exists()) {
destinationFile.mkdir();
System.out.println("Folder created in: "+ destinationFile.getCanonicalPath());
}
RandomAccessFile raf = new RandomAccessFile(sourceFile, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdf = new PDFFile(buf);
int pageNumber = 62;// which PDF page to be convert
PDFPage page = pdf.getPage(pageNumber);
System.out.println("Total pages:"+ pdf.getNumPages());
// create the image
Rectangle rect = new Rectangle(0, 0, (int) page.getBBox().getWidth(), (int) page.getBBox().getHeight());
BufferedImage bufferedImage = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_RGB);
// width & height, // clip rect, // null for the ImageObserver, // fill background with white, // block until drawing is done
Image image = page.getImage(rect.width, rect.height, rect, null, true, true );
Graphics2D bufImageGraphics = bufferedImage.createGraphics();
bufImageGraphics.drawImage(image, 0, 0, null);
File imageFile = new File( destinationDir + fileName +"_"+ pageNumber +".png" );// change file format here. Ex: .png, .jpg, .jpeg, .gif, .bmp
ImageIO.write(bufferedImage, "png", imageFile);
System.out.println(imageFile.getName() +" File created in: "+ destinationFile.getCanonicalPath());
} else {
System.err.println(sourceFile.getName() +" File not exists");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
ConvertedImage:
I get the same result as the OP using PDFBox version 1.8.4. In version 2.0.0-SNAPSHOT, though, it looks better:
Here only some arrows are thinner and some arrow parts are mis-drawn as boxes.
Thus,
how do i make pdfbox take something like a direct snapshot image?
The current release versions (up to 1.8.4) seem to have greater deficits when rendering PDFs as images. You may switch to a current development version (e.g. the current trunk, 2.0.0-SNAPSHOT) or wait until the improvements are released.
Furthermore, some minor deficits are even in 2.0.0-SNAPSHOT. You might want to present your sample document to the PDFBox people (i.e. create an according issue in their JIRA) so that they improve PDFBox even further to suit your needs.
also, i noticed that the image quality of the png is not so good, is there any way to increase the resolution of the generated image?
There are convertToImage overloads with resolution parameters. Your current code actually sets the resolution to screenResolution. Increase this resolution value.
PS: The code to render a PDF page to image has been refactored in 2.0.0-SNAPSHOT. Instead of
BufferedImage image = page.convertToImage();
you now do
BufferedImage image = RenderUtil.convertToImage(page);
I assume this has been done to remove direct AWT references from the core classes because AWT is not available on e.g. Android.
PS: The SNAPSHOT I used last year in this answer merely was a snapshot subject to changes. The 2.0.0 release is still under development, many things have changed. Especially there is no RenderUtil class anymore. Instead one currently has to use the PDFRenderer in the org.apache.pdfbox.rendering package...
it turns out that jpedal(lgpl) does the converting perfectly(just like a snapshot).
here is what I have used :
PdfDecoder decode_pdf = new PdfDecoder(true);
FontMappings.setFontReplacements();
decode_pdf.openPdfFile("Hello World.pdf");
decode_pdf.setExtractionMode(0,800,3);
try {
for(int i=0;i<40;i++)
{
BufferedImage img=decode_pdf.getPageAsImage(2+i);
ImageIO.write(img, "png",new File(String.valueOf(i)+"out.png"));
}
} catch (IOException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
decode_pdf.closePdfFile();
} catch (PdfException e) {
e.printStackTrace();
}
it works fine.
Related
I am working on a pdf editor.
I have made my changes on pdf files with OpenPDF core that is based on iText
And I am viewing the Pdf file with AndroidPdfViewer
My problems are:
Adding new annotations like text or tags or icons into an existing pdf file. ( SOLVED )
Show new changes right after annotations added into pdf file.( SOLVED )
Convert user click into Pdf file coordinates to add new annotation based on user clicked location.
Get click event on added annotations and read meta data that added into that annotation , for ex: read tag hash id that sets on icon annotation. ( SOLVED )
Remove added annotation from PDF File.
Any help appreciated
UPDATE
========================================================================
Solution 1: Adding annotations
Here is my code snippet for adding icon annotation into existing pdf file.
public static void addWatermark(Context context, String filePath) throws FileNotFoundException, IOException {
// get file and FileOutputStream
if (filePath == null || filePath.isEmpty())
throw new FileNotFoundException();
File file = new File(filePath);
if (!file.exists())
throw new FileNotFoundException();
try {
// inout stream from file
InputStream inputStream = new FileInputStream(file);
// we create a reader for a certain document
PdfReader reader = new PdfReader(inputStream);
// get page file number count
int pageNumbers = reader.getNumberOfPages();
// we create a stamper that will copy the document to a new file
PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(file));
// adding content to each page
int i = 0;
PdfContentByte under;
// get watermark icon
Image img = Image.getInstance(PublicFunction.getByteFromDrawable(context, R.drawable.ic_chat));
img.setAnnotation(new Annotation("tag", "gd871394bh2c3r", 0, 0, 0, 0));
img.setAbsolutePosition(230, 190);
img.scaleAbsolute(50, 50);
while (i < pageNumbers) {
i++;
// watermark under the existing page
under = stamp.getUnderContent(i);
under.addImage(img);
}
// closing PdfStamper will generate the new PDF file
stamp.close();
} catch (Exception de) {
de.printStackTrace();
}
}
}
Solution 2: Show new changes
Here is my code snippet for refreshing the view after adding annotation, I have added this into AndroidPdfViewer core classes.
public void refresh(int currPage) {
currentPage = currPage;
if (!hasSize) {
waitingDocumentConfigurator = this;
return;
}
PDFView.this.recycle();
PDFView.this.callbacks.setOnLoadComplete(onLoadCompleteListener);
PDFView.this.callbacks.setOnError(onErrorListener);
PDFView.this.callbacks.setOnDraw(onDrawListener);
PDFView.this.callbacks.setOnDrawAll(onDrawAllListener);
PDFView.this.callbacks.setOnPageChange(onPageChangeListener);
PDFView.this.callbacks.setOnPageScroll(onPageScrollListener);
PDFView.this.callbacks.setOnRender(onRenderListener);
PDFView.this.callbacks.setOnTap(onTapListener);
PDFView.this.callbacks.setOnLongPress(onLongPressListener);
PDFView.this.callbacks.setOnPageError(onPageErrorListener);
PDFView.this.callbacks.setLinkHandler(linkHandler);
if (pageNumbers != null) {
PDFView.this.load(documentSource, password, pageNumbers);
} else {
PDFView.this.load(documentSource, password);
}
}
Solution 4: Click on object in pdf
I have create annotations and set it to added image object, AndroidPdfViewer has an event handler, here is the example
#Override
public void handleLinkEvent(LinkTapEvent event) {
// do your stuff here
}
I will add other new solutions into my question, as update parts.
Here is my code snippet for adding text into pdf file,
Your code does not add text into an existing pdf file. It creates a new PDF, adds text to it, and appends this new PDF to the existing file presumably already containing a PDF. The result is one file containing two PDFs.
Concatenating two files of the same type only seldom results in a valid file of that type. This does works for some textual formats (plain text, csv, ...) but hardly ever for binary formats, in particular not for PDFs.
Thus, your viewer gets to show a file which is invalid as a PDF, so your viewer could simply have displayed an error and quit. But PDF viewers are notorious for trying to repair the files they are given, each viewer in its own way. Thus, depending on the viewer you could also see either only the original file, only the new file, a combination of both, an empty file, or some other repair result.
So your observation,
but this will replace with all of the Pdf file, not just inserting into it
is not surprising but may well differ from viewer to viewer.
To actually change an existing file with OpenPDF (or any iText version before 6 or other library forked from such a version) you should read the existing PDF using a PdfReader, manipulate that reader in a PdfStamper, and close that stamper.
For example:
PdfReader reader = new PdfReader("original.pdf");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("original-stamped.pdf"));
PdfContentByte cb = stamper.getOverContent(1);
cb.beginText();
cb.setTextMatrix(100, 400);
cb.showText("Text at position 100,400.");
cb.endText();
stamper.close();
reader.close();
In particular take care to use different file names here. After closing the stamper and the reader you can delete the original PDF and replace it with the stamped version.
If it is not desired to have a second file, you can alternatively initialize the PdfStamper with a ByteArrayOutputStream and after closing the stamper and the reader replace the contents of the original file with those of the ByteArrayOutputStream.
It's a cross-platform project in VS 19, but for now, I'm starting with Android.
I have found tons of repos. of apps that open the native camera software of your device and then analyze it, and throw the result. But I want to take that picture, from a custom camera.
I found one in GitHub that could be useful as a base for it, and want to take the image taken by it and pass it through the TF lite model (locally).
The code is pretty straight forward, this is the part were it take photo action is (Android):
async void TakePhotoButtonTapped(object sender, EventArgs e)
{
camera.StopPreview();
var image = textureView.Bitmap;
try
{
var absolutePath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim).AbsolutePath;
var folderPath = absolutePath + "/Camera";
var filePath = System.IO.Path.Combine(folderPath, string.Format("photo_{0}.jpg", Guid.NewGuid()));
var fileStream = new FileStream(filePath, FileMode.Create);
await image.CompressAsync(Bitmap.CompressFormat.Jpeg, 50, fileStream);
fileStream.Close();
image.Recycle();
var intent = new Android.Content.Intent(Android.Content.Intent.ActionMediaScannerScanFile);
var file = new Java.IO.File(filePath);
var uri = Android.Net.Uri.FromFile(file);
intent.SetData(uri);
MainActivity.Instance.SendBroadcast(intent);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(#" ", ex.Message);
}
camera.StartPreview();
}
So, from then, it would open a new activity showing the photo that was taken and the given prediction.
Any idea of how to fetch the image given (taken the path, as passing the bitmap I suppose would be really slow) and (most importantly) make a prediction out of it in the new activity?
I'm basing myself with this TFLite project (although, as I said, it opens the native camera) as to code the model.
I have looked through several codes and imported many libraries, i tried using PdfRender which is quite easy to use but it doesn't work below api version 21 and android-pdfviewer library code it makes the apk size lot bigger when i imported and used it in my project. Can anyone suggest some library or code to convert pdf every pages into bitmaps and saving it in arraylist which should not make apk size bigger and should support every versions of android.
Below i have attched my code PdfRender
ParcelFileDescriptor pdfFile = ParcelFileDescriptor.open(pdf,
ParcelFileDescriptor.MODE_READ_ONLY);
PdfRenderer pdfRenderer = new PdfRenderer(pdfFile);
if (pdfRenderer != null) {
for (int i = 0; i < pdfRenderer .getPageCount(); i++) {
// Open page with specified index
try {
if (pdfPage != null) {
pdfPage .close();
}
} catch (Exception e) {
e.printStackTrace();
}
pdfPage = pdfRenderer.openPage(i);
Bitmap bitmap = Bitmap.createBitmap(olamPage.getWidth(),
pdfPage .getHeight(), Bitmap.Config.ARGB_8888);
//Pdf page is rendered on Bitmap
pdfPage .render(bitmap, null, null,
PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// ArrayList Adding Bitmaps
pdfBitmaps.add(bitmap);
}
I want to make a feature like default camera feature did. There are a left thumbnail image which show last taken image. When click to the photo, it show the photo and I can slide to view next photo.
My photos is put on "Abc/Pictures" folder.
To get the latest modified file in folder for specific extension
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.comparator.LastModifiedFileComparator;
import org.apache.commons.io.filefilter.WildcardFileFilter;
...
/* Get the newest file for a specific extension */
public File getTheNewestFile(String filePath, String ext) {
File theNewestFile = null;
File dir = new File(filePath);
FileFilter fileFilter = new WildcardFileFilter("*." + ext);
File[] files = dir.listFiles(fileFilter);
if (files.length > 0) {
/** The newest file comes first **/
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
theNewestFile = files[0];
}
return theNewestFile;
}
Addition
To get all files or only png and jpeg use
new WildcardFileFilter("*.*");
new WildcardFileFilter(new String[]{"*.png", "*.jpg"});
Use below code find latest images from folder and I hope you are saving images with there time stamp which is standard appraoch.
File path = new File(Environment.getExternalStorageDirectory()
.getPath() + "/Abc/Pictures");
int imagesCount= path .listFiles().length; // get the list of images from folder
Bitmap bmp = BitmapFactory.decodeFile(sdcardPath.listFiles()[imagesCount - 1].getAbsolutePath());
eachImageView.setImageBitmap(bmp); // set bitmap in imageview
I'm working on a school android project.
I need to have a download button which downloads a picture(when we have class)
And after display it in another activity(even in offline mode, and after quiting)
I've tried picasso, but I can't get it to save and use it in offline mode.
For you to support offline mode, You need to Save the image on your disk because when your cache is cleared, The image is cleared as well.
You can easily use Glide to Solve this, also storing on device and retrieving
You can Learn more about Glide here http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
/** Download the image using Glide **/
Bitmap theBitmap = null;
theBitmap = Glide.
with(YourActivity.this).
load("Url of your image").
asBitmap().
into(-1, -1).
get();
saveToInternalStorage(theBitmap, getApplicationContext(), "your preferred image name");
/** Save it on your device **/
public String saveToInternalStorage(Bitmap bitmapImage, Context context, String name){
ContextWrapper cw = new ContextWrapper(context);
// path to /data/data/yourapp/app_data/imageDir
String name_="foldername"; //Folder name in device android/data/
File directory = cw.getDir(name_, Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,name);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
Log.e("absolutepath ", directory.getAbsolutePath());
return directory.getAbsolutePath();
}
/** Method to retrieve image from your device **/
public Bitmap loadImageFromStorage(String path, String name)
{
Bitmap b;
String name_="foldername";
try {
File f=new File(path, name_);
b = BitmapFactory.decodeStream(new FileInputStream(f));
return b;
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
return null;
}
/** Retrieve your image from device and set to imageview **/
//Provide your image path and name of the image your previously used.
Bitmap b= loadImageFromStorage(String path, String name)
ImageView img=(ImageView)findViewById(R.id.your_image_id);
img.setImageBitmap(b);
Thanks to #Droidman :
How to download and save an image in Android
Of course you can perform downloading and managing images by yourself,
but if your project is quite complex already, there are a lot of
libraries around and you do not need to reinvent the wheel. I won't
post code this time since there are a lot of examples, but I'm going
to tell you about 2 most useful libraries (IMO) related to image
downloading.
1) Android Volley. A powerful networking library created by Google and
covered by official documentation. POST'ing or GET'ing data, images,
JSON - volley will manage it for you. Using volley just for image
downloading is a bit of an overkill in my opinion.
2) Picasso
Image downloading and caching, perfect for
ListView/GridView/RecyclerView. Apache 2.0 license.
3) Fresco
Quite a new image loading library created by Facebook. Progressive
JPEG streaming, gifs and more. Apache 2.0
You could use Android Library called Universal Image Loader:
https://github.com/nostra13/Android-Universal-Image-Loader