I'm using this depo git application that allows you to capture or choose images and save them in a pdf document. It's working great except the image saved does not fit the whole screen.
So I tried changing theses numbers Document document = new Document(PageSize.A4, 38, 38, 50, 38); or image.setBorderWidth(15);
(documentRect.getWidth() - image.getScaledWidth()) / 2,
(documentRect.getHeight() - image.getScaledHeight()) / 2);
but no luck...
Furthermore the author didn't not use any imageview on layout so I have to edit problematically. Any ideas ?
Update : apparently changing image.scaleAbsolute(bmp.getWidth(), bmp.getHeight()); to
image.scaleAbsolute(500f, 500f); or image.scalePercent(500f); does the trick (I have to play with the numbers to fit the page).
Downside the quality image is horrible...
PdfUtils
public static final String LOG_ACTIVITY = "PdfUtils";
public static String ImgPdf(Activity activity, ArrayList<String> listPathImg,String folder, String pdfName) {
String result ="";
Image image;
String path = FileUtils.createFolderApp(folder);
path = path + pdfName + ".pdf";
Document document = new Document(PageSize.A4, 38, 38, 50, 38);
Log.v(LOG_ACTIVITY, "Document Created");
Rectangle documentRect = document.getPageSize();
try {
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(path));
document.open();
for (int i = 0; i < listPathImg.size(); i++) {
Bitmap bmp = MediaStore
.Images
.Media
.getBitmap(
activity.getContentResolver(),
Uri.fromFile(new File(listPathImg.get(i))));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 70, stream);
image = Image.getInstance(listPathImg.get(i));
if (bmp.getWidth() > documentRect.getWidth() || bmp.getHeight() > documentRect.getHeight()) {
//bitmap is larger than page,so set bitmap's size similar to the whole page
image.scaleAbsolute(documentRect.getWidth(), documentRect.getHeight());
} else {
//bitmap is smaller than page, so add bitmap simply.
//[note: if you want to fill page by stretching image,
// you may set size similar to page as above]
image.scaleAbsolute(bmp.getWidth(), bmp.getHeight());
}
image.setAbsolutePosition(
(documentRect.getWidth() - image.getScaledWidth()) / 2,
(documentRect.getHeight() - image.getScaledHeight()) / 2);
image.setBorder(Image.BOX);
image.setBorderWidth(15);
document.add(image);
document.newPage();
}
result=path;
} catch (Exception err) {
err.printStackTrace();
result="";
} finally {
document.close();
}
return result;
}
Instead of image.scaleAbsolute(width,height) try image.scaleToFit(width,height)
I think what you want to do is change the size of
Rectangle documentRect = document.getPageSize();
Rectangle has 4 parameters that you can set on construction (x , y, width, height).
Changing those might solve your problem.
I use PDF24 Creator if I understand the question correctly.
Solution from this answer.
I changed image.scaleAbsolute(bmp.getWidth(), bmp.getHeight()); to
image.scalePercent(scaler); ofc you have to include
float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
- document.rightMargin() - indentation) / image.getWidth()) * 100;
Now it fit. Though the image quality is not perfect.
Related
My app is using user-selected images and creating a PDF out of it using itextpdf.
It is successfully creating PDF but there is no space between images
Ex.
My Code
public void createPdf(String dest) throws IOException, DocumentException {
Image img = Image.getInstance(allSelectedImages.get(0).getPath());
Document document = new Document(img);
PdfWriter.getInstance(document, new FileOutputStream(dest));
document.open();
for (Uri image : allSelectedImages) {
img = Image.getInstance(image.getPath());
document.newPage();
document.setMargins(100, 100, 100, 100);
img.setAbsolutePosition(0, 0);
document.add(img);
}
document.close();
}
You are adding one image per page, so the space between images is equivalent to the space between pages which is determined by your PDF viewer.
What you can do it adding some margins around your images - this is what you are trying to do already but there are some things that need to be fixed.
Here is an example on how your code can be adapted to add 100pt margin for all sides of the page (note that I am calculating page sizes dynamically so that the page size adapts to the image size in case images are of different size):
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("path/to.pdf"));
document.open();
for (File image : allSelectedImages) {
Image img = Image.getInstance(image.getPath());
float leftMargin = 100;
float rightMargin = 100;
float topMargin = 100;
float bottomMargin = 100;
document.setPageSize(new Rectangle(img.getWidth() + leftMargin + rightMargin, img.getHeight() + topMargin + bottomMargin));
document.newPage();
document.setMargins(leftMargin, rightMargin, topMargin, bottomMargin);
img.setAbsolutePosition(leftMargin, bottomMargin);
document.add(img);
}
Following this tutorial from openCV, and it should be straight forward. However, it crashes with an assertion fail on the net.forward, that I cannot resolve/find anywhere else.
Thought this problem seemed similar and tried to go through the fix/problem finding. However, restarting the discussion and trials showed it is likely not the same. I used initially 3.4.3, which did not support the same Mat type somehow. Updated to 3.4.7 now, and can confirm the blob size is okay (generated from image). Tried also various other prototxt and caffemodels, but doubt by now that the problem lies there (works if the files are okay, otherwise the net loading fails). The key code should be this:
// Load a network.
public void onCameraViewStarted(int width, int height) {
String proto = getPath("deploy.prototxt", this);
String weights = getPath("MobileNetSSD_deploy.caffemodel", this);
net = Dnn.readNetFromCaffe(proto, weights);
Log.i(TAG, "Network loaded successfully");
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
// Get a new frame
Mat frame = inputFrame.rgba();
Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2RGB);
// Forward image through network.
Mat blob = Dnn.blobFromImage(frame, 0.007843,
new Size(300, 300),
new Scalar(127.5, 127.5, 127.5));
net.setInput(blob);
Mat detections = net.forward(); //***215 ASSERTION FAILED occurs***
int cols = frame.cols();
int rows = frame.rows();
detections = detections.reshape(1, (int)detections.total() / 7);
for (int i = 0; i < detections.rows(); ++i) {
double confidence = detections.get(i, 2)[0];
if (confidence > 0.2) {
int classId = (int)detections.get(i, 1)[0];
int left = (int)(detections.get(i, 3)[0] * cols);
int top = (int)(detections.get(i, 4)[0] * rows);
int right = (int)(detections.get(i, 5)[0] * cols);
int bottom = (int)(detections.get(i, 6)[0] * rows);
// Draw rectangle around detected object.
Imgproc.rectangle(frame, new Point(left, top), new Point(right, bottom),
new Scalar(0, 255, 0));
String label = classNames[classId] + ": " + confidence;
int[] baseLine = new int[1];
Size labelSize = Imgproc.getTextSize(label, Core.FONT_HERSHEY_SIMPLEX, 0.5, 1, baseLine);
// Draw background for label.
Imgproc.rectangle(frame, new Point(left, top - labelSize.height),
new Point(left + labelSize.width, top + baseLine[0]),
new Scalar(255, 255, 255), Core.FILLED);
// Write class name and confidence.
Imgproc.putText(frame, label, new Point(left, top),
Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(0, 0, 0));
}
}
return frame;
}
public void onCameraViewStopped() {}
// Upload file to storage and return a path.
private static String getPath(String file, Context context) {
AssetManager assetManager = context.getAssets();
BufferedInputStream inputStream = null;
try {
// Read data from assets.
inputStream = new BufferedInputStream(assetManager.open(file));
byte[] data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
// Create copy file in storage.
File outFile = new File(context.getFilesDir(), file);
FileOutputStream os = new FileOutputStream(outFile);
os.write(data);
os.close();
// Return a path to file which may be read in common way.
return outFile.getAbsolutePath();
} catch (IOException ex) {
Log.i(TAG, "Failed to upload a file");
}
return "";
}
The full error message is
cv::Exception: OpenCV(3.4.7) /build/3_4_pack-android/opencv/modules/dnn/src/layers/batch_norm_layer.cpp:39: error: (-215:Assertion failed) blobs.size() >= 2 in function 'cv::dnn::BatchNormLayerImpl::BatchNormLayerImpl(const cv::dnn::experimental_dnn_34_v13::LayerParams&)'
I expect it to not crash. The frame should be okay (image loaded), the net is not empty, and the layers in the net seem fine too (checked since there are some differences using caffe in java). Any help is appreciated!
After some days of research in different directions, I found the problem: the frame format should be BGR, not RGB! That means
Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2BGR);
I'm trying to save an image in bmp format, but it doesn't create any file.
If I use "png" instead, everything works fine.
Any ideas?
//This works fine:
ImageIO.write(bi, "png", new File("D:\\MyImage.png"));
//This does not work:
ImageIO.write(bi, "bmp", new File("D:\\MyImage.bmp"));
ImageIO.getWriterFormatNames() gives me "jpg", "bmp", "jpeg" and some others..
Thanks in advance.
Jakob
I just finished debugging a similar problem and I thought I will present my reasoning here, although Jakob has gone ahead with the PNG format.
First, always check the return value of ImageIO.write(...). It will return false if no appropriate writer can be found and that's what should have happened when Jakob tried writing it as a bitmap. This happens when the actual image format of the file does not match what is given in the 'format name' argument. No exception is thrown in this case. Check out the docs at http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#write(java.awt.image.RenderedImage, java.lang.String, java.io.File)
Second, check the image type of the BufferedImage object by using the BufferedImage#getType() method. Check out the possible return values at http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html#getType(). For example, If you get the type as TYPE_INT_ARGB from your BufferedImage object (which represents a PNG with a alpha component) you wont have success using ImageIO.write(bi, "BMP", new File("D:\\test.bmp")) and the method would return false, even though you can see BMP/bmp in the list of entries obtained using ImageIO.getWriterFormatNames(). You might have to work on the encoding and transform your image to the desired format.
Third, when facing such problems which can be a pain sometimes, it always helps to use an image editor such as GIMP to check out your image properties in detail.
#Green arrow, a minor note... you can use either "bmp" or "BMP" as the image format value. The same applies for other formats as well. It does not matter.
As #bincob says, if write returns false, you can redraw the source image like this
BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(),
bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null);
And then you can write again.
Using BufferedImage.TYPE_INT_RGB encoding works for "gif","png","tif" as well as "jpg" and "bmp":
static void saveBufferedImageToFileTest(){
String[] types = new String[] {"gif","png","tif","jpg","bmp"};
//JPEG and BMP needs BufferedImage.TYPE_INT_RGB. See https://mkyong.com/java/convert-png-to-jpeg-image-file-in-java/
//BufferedImage.TYPE_INT_RGB for all `types`
int biType = BufferedImage.TYPE_INT_RGB; // BufferedImage.TYPE_INT_ARGB does not work for "bmp" and "jpeg"
BufferedImage bi = new BufferedImage(200 ,200, biType);
Graphics g = bi.getGraphics();
g.fillRect(50, 50, 100, 100);
g.dispose();
try {
for(String type : types){
boolean success = ImageIO.write(bi,type,new File("test_image."+type));
System.out.println(type + (success ? " file created" : " file NOT created") );
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
didn't try but I think the format should be "BMP" and not "bmp" actually.
Please try with
ImageIO.write(bi, "BMP", new File("D:\\MyImage.bmp"));
and see what happens.
We can't see how your bi is build.
BufferedImage bufferedImage = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
Is the encodingType is set properly ?
I think your bi is corrupted, that's work perfectly for me.
BufferedImage bi = new BufferedImage(50,50,BufferedImage.TYPE_INT_RGB);
Graphics gd = bi.getGraphics();
gd.drawRect(0, 0, 10, 10);
try {
ImageIO.write(bi, "BMP", new File("C:\\test.bmp"));
ImageIO.write(bi, "PNG", new File("C:\\test.png"));
} catch (IOException e) {
System.out.println("error "+e.getMessage());
}
An oldie, but BMPs are still useful occasionally and the answers above all skirt the best solution: do it yourself. That way it works for any type of bitmap.
static void writeBMP(BufferedImage image, File f) throws IOException {
OutputStream out = new BufferedOutputStream(new FileOutputStream(f));
int width = image.getWidth();
int height = image.getHeight();
int row = (width * 3 + 3) / 4 * 4;
out.write('B');
out.write('M');
writeInt(out, 14 + 40 + row * height); // file size
writeInt(out, 0);
writeInt(out, 14 + 40); // bitmap offset
writeInt(out, 40); // size
writeInt(out, width); // width
writeInt(out, height); // weight
writeInt(out, (24<<16) | 1); // planes, bpp
writeInt(out, 0); // compression
writeInt(out, row * height); // bitmap size
writeInt(out, 0); // resx
writeInt(out, 0); // resy
writeInt(out, 0); // used colors
writeInt(out, 0); // important colors
for (int y=height-1;y>=0;y--) {
for (int x=0;x<width;x++) {
int rgba = image.getRGB(x, y);
out.write(rgba & 0xFF); // b
out.write(rgba >> 8); // g
out.write(rgba >> 16); // r
}
for (int x=width*3;x%4!=0;x++) { // pad to 4 bytes
out.write(0);
}
}
out.close();
}
private static void writeInt(OutputStream out, int v) throws IOException {
out.write(v);
out.write(v >> 8);
out.write(v >> 16);
out.write(v >> 24);
}
I'm trying to save an image in bmp format, but it doesn't create any file.
If I use "png" instead, everything works fine.
Any ideas?
//This works fine:
ImageIO.write(bi, "png", new File("D:\\MyImage.png"));
//This does not work:
ImageIO.write(bi, "bmp", new File("D:\\MyImage.bmp"));
ImageIO.getWriterFormatNames() gives me "jpg", "bmp", "jpeg" and some others..
Thanks in advance.
Jakob
I just finished debugging a similar problem and I thought I will present my reasoning here, although Jakob has gone ahead with the PNG format.
First, always check the return value of ImageIO.write(...). It will return false if no appropriate writer can be found and that's what should have happened when Jakob tried writing it as a bitmap. This happens when the actual image format of the file does not match what is given in the 'format name' argument. No exception is thrown in this case. Check out the docs at http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#write(java.awt.image.RenderedImage, java.lang.String, java.io.File)
Second, check the image type of the BufferedImage object by using the BufferedImage#getType() method. Check out the possible return values at http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html#getType(). For example, If you get the type as TYPE_INT_ARGB from your BufferedImage object (which represents a PNG with a alpha component) you wont have success using ImageIO.write(bi, "BMP", new File("D:\\test.bmp")) and the method would return false, even though you can see BMP/bmp in the list of entries obtained using ImageIO.getWriterFormatNames(). You might have to work on the encoding and transform your image to the desired format.
Third, when facing such problems which can be a pain sometimes, it always helps to use an image editor such as GIMP to check out your image properties in detail.
#Green arrow, a minor note... you can use either "bmp" or "BMP" as the image format value. The same applies for other formats as well. It does not matter.
As #bincob says, if write returns false, you can redraw the source image like this
BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(),
bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newBufferedImage.createGraphics().drawImage(bufferedImage, 0, 0, Color.WHITE, null);
And then you can write again.
Using BufferedImage.TYPE_INT_RGB encoding works for "gif","png","tif" as well as "jpg" and "bmp":
static void saveBufferedImageToFileTest(){
String[] types = new String[] {"gif","png","tif","jpg","bmp"};
//JPEG and BMP needs BufferedImage.TYPE_INT_RGB. See https://mkyong.com/java/convert-png-to-jpeg-image-file-in-java/
//BufferedImage.TYPE_INT_RGB for all `types`
int biType = BufferedImage.TYPE_INT_RGB; // BufferedImage.TYPE_INT_ARGB does not work for "bmp" and "jpeg"
BufferedImage bi = new BufferedImage(200 ,200, biType);
Graphics g = bi.getGraphics();
g.fillRect(50, 50, 100, 100);
g.dispose();
try {
for(String type : types){
boolean success = ImageIO.write(bi,type,new File("test_image."+type));
System.out.println(type + (success ? " file created" : " file NOT created") );
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
didn't try but I think the format should be "BMP" and not "bmp" actually.
Please try with
ImageIO.write(bi, "BMP", new File("D:\\MyImage.bmp"));
and see what happens.
We can't see how your bi is build.
BufferedImage bufferedImage = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
Is the encodingType is set properly ?
I think your bi is corrupted, that's work perfectly for me.
BufferedImage bi = new BufferedImage(50,50,BufferedImage.TYPE_INT_RGB);
Graphics gd = bi.getGraphics();
gd.drawRect(0, 0, 10, 10);
try {
ImageIO.write(bi, "BMP", new File("C:\\test.bmp"));
ImageIO.write(bi, "PNG", new File("C:\\test.png"));
} catch (IOException e) {
System.out.println("error "+e.getMessage());
}
An oldie, but BMPs are still useful occasionally and the answers above all skirt the best solution: do it yourself. That way it works for any type of bitmap.
static void writeBMP(BufferedImage image, File f) throws IOException {
OutputStream out = new BufferedOutputStream(new FileOutputStream(f));
int width = image.getWidth();
int height = image.getHeight();
int row = (width * 3 + 3) / 4 * 4;
out.write('B');
out.write('M');
writeInt(out, 14 + 40 + row * height); // file size
writeInt(out, 0);
writeInt(out, 14 + 40); // bitmap offset
writeInt(out, 40); // size
writeInt(out, width); // width
writeInt(out, height); // weight
writeInt(out, (24<<16) | 1); // planes, bpp
writeInt(out, 0); // compression
writeInt(out, row * height); // bitmap size
writeInt(out, 0); // resx
writeInt(out, 0); // resy
writeInt(out, 0); // used colors
writeInt(out, 0); // important colors
for (int y=height-1;y>=0;y--) {
for (int x=0;x<width;x++) {
int rgba = image.getRGB(x, y);
out.write(rgba & 0xFF); // b
out.write(rgba >> 8); // g
out.write(rgba >> 16); // r
}
for (int x=width*3;x%4!=0;x++) { // pad to 4 bytes
out.write(0);
}
}
out.close();
}
private static void writeInt(OutputStream out, int v) throws IOException {
out.write(v);
out.write(v >> 8);
out.write(v >> 16);
out.write(v >> 24);
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert pdf file to jpg asp.net
public class Pdf2Image {
private Image image;
int length;
public int convertPdf2Image(String pdfname) {
File file = new File(pdfname);
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new PDFFile(buf);
// draw the first page to an image
int num = pdffile.getNumPages();
length=num;
for (int i = 0; i <= num; i++) {
PDFPage page = pdffile.getPage(i);
//get the width and height for the doc at the default zoom
int width = (int) page.getBBox().getWidth();
int height = (int) page.getBBox().getHeight();
Rectangle rect = new Rectangle(0, 0, width, height);
int rotation = page.getRotation();
Rectangle rect1 = rect;
if (rotation == 90 || rotation == 270) {
rect1 = new Rectangle(0, 0, rect.height, rect.width);
}
//generate the image
BufferedImage img = (BufferedImage) page.getImage(
rect.width, rect.height, //width & height
rect1, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
ImageIO.write(img, "png", new File("src\\downloadedFiles\\aa" + i + ".png"));
}
} catch (FileNotFoundException e1) {
System.err.println(e1.getLocalizedMessage());
} catch (IOException e) {
System.err.println(e.getLocalizedMessage());
}
return length;
}
public static void main(String[] args) {
Pdf2Image p = new Pdf2Image();
p.convertPdf2Image("src\\downloadedFiles\\todaypdf.pdf");
}
}
I am using this code to convert PDF file to image. It is working fine for most of the PDF's but showing exception for a PDF file. Exception is:
Expected 'xref' at start of table.
Could any one tell me why it is giving such an exception?
There are many malformed PDF files out in the wild and this is most likely one of them.
It is not possible to give a definite answer until seeing the problem PDF file. What I am guessing is that the 'startxref' specifies an absolute position into the PDF where the xref table should be located. The java library is jumping to this position on the file expecting to find the word 'xref' but cannot find it.
http://blog.amyuni.com/?p=1627
One way to fix this would be to load the file into the full version of Acrobat and then save the file. Acrobat will fix the xref offset as mentioned in the link.
There are quite large companies out there generating malformed PDF's that should know better. Adobe lets these files exist because it makes it hard for their PDF competitors to keep up and compete.