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);
}
}
}
Related
I'm trying to send multiple PNG:s to an adroid-phone.
(Every image is sent in a separate JSON-object together with multiple other objects that is associated with the image.)
I'm sending the images as byte-arrays and my phone is receiving them.
The problem starts when I try to decode with BitmapFactory.decodeByteArray which returns null.
How should I encode on the server-side and decode on the android-side?
First attempt on server-side:
File imgPath = new File(path);
BufferedImage bufferedImage = ImageIO.read(imgPath);
WritableRaster raster = bufferedImage.getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
byte[] bytes = data.getData();
Second attempt on server-side:
byte[] bytes = null;
File file = new File(path);
bytes = Files.readAllBytes(file.toPath());
Android-side:
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
mImageView.setImageBitmap(bitmap);
Sending JSON from server:
public class Response {
List<Person> mPeople;
..other objects...
}
public class Person {
String name;
String image; //base68string
}
public ServerThread {
Response resp = create objects to send;
String str = new Gson().toJson(resp);
OutputStreamWriter.write(str);
}
Receiving JSON on Android-side:
Response resp = gson.fromJson(str, Response.class);
List<Person> = resp.getPersons();
//Person-class on the android side is Parcable
So I tried this approach but it still doesn't work:
// Server-side
import java.util.Base64;
import java.util.Base64.Encoder;
File file = new File(path);
byte[] bytes = Files.readAllBytes(file.toPath());
Encoder e = Base64.getEncoder();
String base64String = e.encodeToString(bytes);
//Android-side
byte[] bytes = Base64.decode(base64String, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
mImageView.setImageBitmap(bitmap);
I suggest you to try Picasso or Glide to load image into imageview directly from the URL. You don't have to manage this all stuff manually.
I was doing that stuff but after using one of this library it removes lots of work.
Just try this.
I am having trouble interpreting this question.
I receive a img in JSON formated in Base64, for web developers its only do:
"".
How I can make it in Java?
You can use apache commons-codec for converting byte array. to base64 and from base64 to byte array.
Actually, you can use guava. This artifact has base64 libraries and json.
Just add com.google.guava in your maven's project.
For creating image, you can use:
InputStream in = new ByteArrayInputStream(yourbytearray);
BufferedImage bImageFromConvert = ImageIO.read(in);
ImageIO.write(bImageFromConvert, "jpg", new File("c:/yourimage.jpg"));
//JSON funtion
String cmd_getPhoto = so.cmd_getPhoto();
//for remove ":"data:image\/png;base64,"
String imageDataBytes = cmd_getPhoto.substring(cmd_getPhoto.indexOf(",") + 1);
//for decode
Base64 b = new Base64();
byte[] decode = b.decode(imageDataBytes.getBytes());
//create the stream
InputStream stream = new ByteArrayInputStream(decode);
try {
//set the stream for a bufferedImage and do what your will with it
BufferedImage bitmap = ImageIO.read(stream);
jLabel6.setIcon(new ImageIcon(bitmap));
} catch (IOException ex) { }
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()
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'm using a jQuery plugin called wPaint to allow users to draw their own image. I send the resulting image as a string to the server as a string which begins with
data:image/png;base64,
I tried the two approaches below but with both the approaches i'm not able to store the image.
Approach 1
String imageData = parameterParser.getStringParameter("image", "");
byte[] imgByteArray = Base64.decodeBase64(imageData.getBytes());
FileOutputStream fileOutputStream = new FileOutputStream("/home/arvind/Desktop/test.png");
fileOutputStream.write(imgByteArray);
fileOutputStream.close();
In this case the file is written but doesn't show the image. However, when i remove the file extension i get the string that was sent to the server (i.e. whatever is in imageData).
Approach 2
String imageData = parameterParser.getStringParameter("image", "");
byte[] imgByteArray = Base64.decodeBase64(imageData.getBytes());
InputStream in = new ByteArrayInputStream(imgByteArray);
BufferedImage bImageFromConvert = ImageIO.read(in);
ImageIO.write(bImageFromConvert, "png", new File("/home/arvind/Desktop/test.png"));
The BufferedImage bImageFromConvert is null so I get an exception (IllegalArgumentException) when the file is created.
The Base64 class is from the apache commons codec library and is version 1.2.
Is there something I'm doing wrong?
Initially I had sent the data to the server using the following code.
$.ajax({
url : '/campaign/holiImageUpload.action',
type : 'POST',
data : "image=" + $("#wPaint2").wPaint("image")
success :function(data){
}
});
Now i'm sending the data to the server using the following code
var imgData = $("#wPaint2").wPaint("image");
$.ajax({
url : '/campaign/holiImageUpload.action',
type : 'POST',
data : {image : imgData},
success :function(data){
}
});
In the server side this is the final code :
String imageData = parameterParser.getStringParameter("image", "");
try {
imageData = imageData.substring(22);
byte[] imgByteArray = Base64.decodeBase64(imageData.getBytes());
InputStream in = new ByteArrayInputStream(imgByteArray);
BufferedImage bufferedImage = ImageIO.read(in);
ImageIO.write(bufferedImage, "png", new File("/home/arvind/Desktop/test.png"));
catch(Exception ex){
ex.printStrackTrace();
}
It appears that you are trying to decode data:image/png'base64 along with your Base64 encoded data? You will want to remove that from the input string before you decode the Base64 data into image bytes.
Also, you don't want to decode the string as bytes... just as a string.