I am using PDFBox to extract the images from my pdf (which contains only jpg's).
Since I will save those images inside my database, I would like to directly convert each image to an inputstream object first without placing the file temporary on my file sysem. I am facing difficulties with this however. I think it has to do because of the use of image.getPDFStream().createInputStream() as I did in the following example:
while (imageIter.hasNext()) {
String key = (String) imageIter.next();
PDXObjectImage image = (PDXObjectImage) images.get(key);
FileOutputStream output = new FileOutputStream(new File(
"C:\\Users\\Anton\\Documents\\lol\\test.jpg"));
InputStream is = image.getPDStream().createInputStream(); //this gives me a corrupt file
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
output.write(buffer);
}
}
However this works:
while (iter.hasNext()) {
PDPage page = (PDPage) iter.next();
PDResources resources = page.getResources();
Map<String, PDXObject> images = resources.getXObjects();
if (images != null) {
Iterator<?> imageIter = images.keySet().iterator();
while (imageIter.hasNext()) {
String key = (String) imageIter.next();
PDXObjectImage image = (PDXObjectImage) images.get(key);
image.write2file(new File("C:\\Users\\Anton\\Documents\\lol\\test.jpg")); //this works however
}
}
}
Any idea how I can convert each PDXObjectImage (or any other object I can get) to an inputstream?
In PDFBox 1.8, the easiest way is to use write2OutputStream(), so your first code block would now look like this:
while (imageIter.hasNext()) {
String key = (String) imageIter.next();
PDXObjectImage image = (PDXObjectImage) images.get(key);
FileOutputStream output = new FileOutputStream(new File(
"C:\\Users\\Anton\\Documents\\lol\\test.jpg"));
image.write2OutputStream(output);
}
advanced solution, as long as you're really sure you have only JPEGs that display properly, i.e. have no unusual colorspace:
while (imageIter.hasNext()) {
String key = (String) imageIter.next();
PDXObjectImage image = (PDXObjectImage) images.get(key);
FileOutputStream output = new FileOutputStream(new File(
"C:\\Users\\Anton\\Documents\\lol\\test.jpg"));
InputStream is = image.getPDStream().getPartiallyFilteredStream(DCT_FILTERS);
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
output.write(buffer);
}
}
The second solution removes all filters except the DCT (= JPEG) filter. Some older PDFs have several filters, e.g. ascii85 and DCT.
Now even if you created the image with JPEGs, you don't know what your PDF creation software did. One way to find out what type of image it is, is to check what class it is (use instanceof):
- PDPixelMap => PNG
- PDJpeg => JPEG
- PDCcitt => TIF
Another way is to use image.getSuffix().
PDXObjectImage has method write2OutputStream(OutputStream out) from which you can then get either byte array out of output stream.
Check How to convert OutputStream to InputStream? for converting OutputStream to InputStream.
If you are using PDFBox 2.0.0 or above
PDDocument document = PDDocument.load(new File("filePath")); //filePath is the path to your .pdf
PDFRenderer pdfRenderer = new PDFRenderer(document);
for(int i=0; i<document.getPages().getCount(); i++){
BufferedImage bim = pdfRenderer.renderImage(i, 1.0f, ImageType.RGB); //Get bufferedImage for page "i" with scale 1
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bim, "jpg", os);
InputStream is = new ByteArrayInputStream(os.toByteArray());
//Do whatever you need with the inputstream
}
document.close()
Related
I'm trying to save tiff images uploaded via browser using Spring and JAI ImageIO. I can save the image using the code below but the problem is that the saved image doesn't have the layers(the ones that tiff images consist of) which it has before uploading.
Are there any other parameters to ensure that the saved image also has the layers?
private void saveTiffImage(byte[] bytes, String uuid) throws Exception {
SeekableStream stream = new ByteArraySeekableStream(bytes);
String[] names = ImageCodec.getDecoderNames(stream);
ImageDecoder dec =
ImageCodec.createImageDecoder(names[0], stream, null);
RenderedImage im = dec.decodeAsRenderedImage();
String fileName = uuid + ".tif";
com.sun.media.jai.codec.TIFFEncodeParam params = new com.sun.media.jai.codec.TIFFEncodeParam();
params.setCompression(com.sun.media.jai.codec.TIFFEncodeParam.COMPRESSION_PACKBITS);
FileOutputStream os = new FileOutputStream(IMG_LOCATION + fileName);
javax.media.jai.JAI.create("filestore", im, IMG_LOCATION + fileName, "TIFF", params);
os.flush();
os.close();
}
I've found the solution using the answer here : How to combine two or many tiff image files in to one multipage tiff image in JAVA.
private Object[] saveTiffImage(byte[] bytes, String uuid) throws Exception {
SeekableStream stream = new ByteArraySeekableStream(bytes);
String[] names = ImageCodec.getDecoderNames(stream);
ImageDecoder dec =
ImageCodec.createImageDecoder(names[0], stream, null);
// Here we get the other pages.
Vector vector = new Vector();
int pageCount = dec.getNumPages();
for (int i = 1; i < pageCount; i++) {
RenderedImage im = dec.decodeAsRenderedImage(i);
vector.add(im);
}
String fileName = uuid + ".tif";
com.sun.media.jai.codec.TIFFEncodeParam params = new com.sun.media.jai.codec.TIFFEncodeParam();
params.setCompression(com.sun.media.jai.codec.TIFFEncodeParam.COMPRESSION_PACKBITS);
// Then set here
params.setExtraImages(vector.iterator());
// This is the first page
RenderedImage im = dec.decodeAsRenderedImage(0);
FileOutputStream os = new FileOutputStream(IMG_LOCATION + fileName);
javax.media.jai.JAI.create("filestore", im, IMG_LOCATION + fileName, "TIFF", params);
os.flush();
os.close();
}
I have a class named Person. Each Person has an avatar image stored as javafx.scene.image.Image field. I am trying to write those images from a collection of Persons to an xml file.
This is how i write the image:
Image image = p.getImage();
BufferedImage img = SwingFXUtils.fromFXImage(image, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "png", baos);
// baos.flush();
String encodedImage = Base64.getEncoder().encodeToString(baos.toByteArray());
baos.close();
xmlEventWriter.add(xmlEventFactory.createCharacters(encodedImage));
And this is how i am trying to read it:
byte[] bytes = Base64.getDecoder().decode(event.asCharacters().getData());
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
BufferedImage image = ImageIO.read(byteArrayInputStream);
personImage = SwingFXUtils.toFXImage(image, null);
Problem begins when reading encoded image from xml file. I am not receiving the whole set of characters. Value of event.asCharacters().getData() is only a part of what can be found in the xml file.
That is why i receive a javax.imageio.IIOException: Error reading PNG image data # (PersonXMLTool.java:77) which is BufferedImage image = ImageIO.read(byteArrayInputStream); and a Caused by: java.io.EOFException: Unexpected end of ZLIB input stream.
At first i was using apache commons Base64 but it does not make any difference. On my test project i was doing the same and it worked. The difference was i did not write the encoded image to any xml file but used the String it generated for me.
Any help appreciated.
It looks like you are assuming the character data is all transmitted in a single XMLEvent. This won't be the case (unless the image is tiny): typically you will receive the character data in multiple events.
So you need to parse the xml file using something like this:
XMLInputFactory inputFactory = XMLInputFactory.newFactory() ;
XMLEventReader eventReader = inputFactory.createXMLEventReader(Files.newBufferedReader(xmlFile.toPath()));
StringBuilder encodedImageBuffer = new StringBuilder();
boolean readingImage = false ;
while (eventReader.hasNext() && encodedImage == null) {
XMLEvent event = eventReader.nextEvent();
if (event.isStartElement()) {
StartElement el = event.asStartElement();
if ("image".equals(el.getName().getLocalPart())) {
readingImage = true ;
}
}
if (event.isCharacters() && readingImage) {
Characters characters = event.asCharacters();
encodedImageBuffer.append(characters.getData());
}
if (event.isEndElement()) {
EndElement el = event.asEndElement();
if ("image".equals(el.getName().getLocalPart())) {
String encodedImage = encodedImageBuffer.toString();
byte[] imageData = Base64.getDecoder().decode(encodedImage);
ByteArrayInputStream dataInputStream = new ByteArrayInputStream(imageData);
BufferedImage buffImage = ImageIO.read(dataInputStream);
Image image = SwingFXUtils.toFXImage(buffImage, null);
}
}
}
from server side an image is being sent to me.
The image i receive it as string, what server side is sending me is the entire file.
How can I read it in android side?
File tempFile = File.createTempFile("image", ".jpg", null);
// tempFile.wr
byte[] bytes = output.toString().getBytes();
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(bytes);
output is the result i receive, its string which is the entire file send from server side.
Bitmap myBitmap = BitmapFactory.decodeFile(tempFile.getAbsolutePath());
m2.setImageBitmap(myBitmap);
I am getting SkImageDecoder::Factory returned null
this code running produces this log cat
File tempFile = File.createTempFile("image", ".jpg", null);
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(output.toString().getBytes());
fos.close();
System.out.println(""+tempFile.getAbsolutePath());
BitmapFactory.Options myOptions = new BitmapFactory.Options();
myOptions.inDither = true;
myOptions.inScaled = false;
myOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// important
myOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(tempFile.getAbsolutePath());
m2.setImageBitmap(bitmap);
http://www.speedyshare.com/8BdVs/log.txt
Here is the code to convert into stream from base64 decoded string of image. This will only work if it has properly encoded in Base64 and stored it in your server
Bitmap img = null;
InputStream stream = new ByteArrayInputStream(Base64.decode(imageDataBytes.getBytes(), Base64.DEFAULT));
img = BitmapFactory.decodeStream(stream);
I need to create a barcode image in java using jasperreports, currently I'm doing this saving the image file on disk, but I need to do it without saving the image on disk. I need to create the barcode image in memory an then send it to iReport as a parameter.
This is what I have done:
Map<String, Object> parameters = new HashMap<String, Object>();
String imagePath = "\\\\netw\\barCode.jpg";
parameters.put("rutaCodigoBarrasVal", imagePath);
Barcode barCode = BarcodeFactory.createPDF417("1234567890");
barCode.setDrawingText(false);
barCode.setBarHeight(33);
barCode.setBarWidth(207);
FileOutputStream fOS = new FileOutputStream(imagePath);
BarcodeImageHandler.writeJPEG(barCode, fOS);
fOS.close();
What can I do?
You should first try to write the Barcode into a byte array or InputStream, looking at your library documentation.
JasperReports supports passing an image as a InputStream parameter, and draw that in the report.
InputStream imageStream = ...;
parametros.put("image", imageStream );
From JasperReports, receive that parameter as java.io.InputStream, then draw it with an image widget and the following properties:
Image Expression: $P{image}
Expression Class: java.io.InputStream
I hope it helps.
Finally this is what I did using barcode4j library:
ByteArrayOutputStream os = new ByteArrayOutputStream();
PDF417Bean barCode = new PDF417Bean();
boolean antiAlias = false;
int orientation = 0;
int dpi = 300;
BitmapCanvasProvider canvas = new BitmapCanvasProvider(dpi, BufferedImage.TYPE_BYTE_BINARY, antiAlias, orientation);
BarcodeDimension dim = new BarcodeDimension(207, 42);
canvas.establishDimensions(dim);
barCode.setColumns(7);
barCode.generateBarcode(canvas, codeToConvert);
canvas.finish();
String mime = MimeTypes.MIME_JPEG;
os = new ByteArrayOutputStream();
final BitmapEncoder encoder = BitmapEncoderRegistry.getInstance(mime);
encoder.encode(canvas.getBufferedImage(), os, mime, dpi);
fis = new ByteArrayInputStream(os.toByteArray());
From a DB2 table I've got blob which I'm converting to a byte array so I can work with it. I need to take the byte array and create a PDF out of it.
This is what I have:
static void byteArrayToFile(byte[] bArray) {
try {
// Create file
FileWriter fstream = new FileWriter("out.pdf");
BufferedWriter out = new BufferedWriter(fstream);
for (Byte b: bArray) {
out.write(b);
}
out.close();
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
But the PDF it creates is not right, it has a bunch of black lines running from top to bottom on it.
I was actually able to create the correct PDF by writing a web application using essentially the same process. The primary difference between the web application and the code about was this line:
response.setContentType("application/pdf");
So I know the byte array is a PDF and it can be done, but my code in byteArrayToFile won't create a clean PDF.
Any ideas on how I can make it work?
Sending your output through a FileWriter is corrupting it because the data is bytes, and FileWriters are for writing characters. All you need is:
OutputStream out = new FileOutputStream("out.pdf");
out.write(bArray);
out.close();
One can utilize the autoclosable interface that was introduced in java 7.
try (OutputStream out = new FileOutputStream("out.pdf")) {
out.write(bArray);
}
Read from file or string to bytearray.
byte[] filedata = null;
String content = new String(bytearray);
content = content.replace("\r", "").replace("\uf8ff", "").replace("'", "").replace("\"", "").replace("`", "");
String[] arrOfStr = content.split("\n");
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
try (PDPageContentStream cs = new PDPageContentStream(document, page)) {
// setting font family and font size
cs.beginText();
cs.setFont(PDType1Font.HELVETICA, 14);
cs.setNonStrokingColor(Color.BLACK);
cs.newLineAtOffset(20, 750);
for (String str: arrOfStr) {
cs.newLineAtOffset(0, -15);
cs.showText(str);
}
cs.newLine();
cs.endText();
}
document.save(znaFile);
document.close();
public static String getPDF() throws IOException {
File file = new File("give complete path of file which must be read");
FileInputStream stream = new FileInputStream(file);
byte[] buffer = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bytesRead;enter code here
while ((bytesRead = stream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
System.out.println("it came back"+baos);
byte[] buffer1= baos.toByteArray();
String fileName = "give your filename with location";
//stream.close();
FileOutputStream outputStream =
new FileOutputStream(fileName);
outputStream.write(buffer1);
return fileName;
}