Problem converting PNG to JPG using Java (ImageIO.write()) [duplicate] - java

This question already has answers here:
Issue using ImageIO.write jpg file: pink background [closed]
(6 answers)
Closed 9 years ago.
I am using ImageIO.write() to convert PNG files to JPG. For some reason, my result image has a pink layer over it. I have searched far and wide for a solution but haven't found any. The code works for all other types of images except PNG.

I'm not sure how the other code snippet works given buffer is not used after it's created. I've found this pink problem to be jvm version specific.
The easiest solution I've found is to do this.
BufferedImage image = null;
BufferedImage imageRGB = null;
// imageBytes is some png file you read
image = ImageIO.read(new ByteArrayInputStream(imageBytes));
// Attempt at PNG read fix
imageRGB = new BufferedImage(image.getWidth(),
image.getHeight(), BufferedImage.TYPE_INT_RGB);
// write data into an RGB buffered image, no transparency
imageRGB.setData(image.getData());
// return the RGB buffered image, or do ImageIO.write( ... );
return imageRGB; // fixed for jpeg

Quick reading of other SO answers tagged ImageIO led to this.
The root cause can be a buggy reader. The proposed workaround is using different reader package.
Edit Above link is broken, but this appears to be it.
Edit The above links are broken, here it is on archive.org.

I too had the same problem, but if i write it in png format then it gets solved.
Something like this,
ImageIO.write(resizedImageBuffer, "png", baos);

I found this link which has some code that might be of use. I tried your code with a few of my images but I couldn't reproduce the issue. I tried the last answer by devyn_a and it didn't break anything. Here's your code modified with devyn_a's solution.
String url = "file:///d:/teststuff/IMG_0393.JPG";
String to = "d:/teststuff/out.jpg";
BufferedImage oldImage = ImageIO.read(new URL(url));
BufferedImage buffer = new BufferedImage (oldImage.getWidth(),
oldImage.getHeight(), BufferedImage.TYPE_INT_RGB);
ImageIO.write(ImageIO.read(new URL(url)), "jpg", new File(to));
It would be interesting to know if this resolves the issue.

Related

Java - reading a compressed bitmap

I'm looking to read in the RGB values of a bitmap (or the hex colour codes, either work).
I have tried both this code :
File image = serverConfig.get(map.bmp);
BufferedImage buffer = ImageIO.read(image);
dimX = buffer.getWidth();
dimY = buffer.getHeight();
byte[] pixlesB = (byte[]) buffer.getRaster().getDataElements(0, 0, buffer.getWidth(), buffer.getHeight(), null);
and this code :
File image = serverConfig.get(map.bmp);
BufferedImage buffer = ImageIO.read(image);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(buffer, "bmp", baos );
baos.flush();
byte[] pixlesB = baos.toByteArray();
baos.close();
The both work fine for a small bitmap, but when I load a large bitmap, the data gets compressed and the array returns a bunch of semi random numbers.
for example:
A green pixel will read 2,2,2 instead of 0,255,0
A red pixel will read 5,5,5 instead of 255,0,0
A yellow pixel will read 8,8,8 instead of 255,255,0
The bitmaps I'm using only include the colours red, yellow and green.
My problem is I have no way of knowing what colour 2,2,2 relates to without checking it manually (which I cannot do since it changes with each bitmap)
I know that there is some metadata in the bitmap that specifies 2 is green, but I don't know how to access it or use it to turn 2 back into 0,255,0
And this is not a duplicate of Java - get pixel array from image since that doesn't mention compressed files.
And while I did ask this question a while back, it was just redirected to the above site.
Thanks in advance!
EDIT: Just thought this might make the question a bit clearer. I believe the file is being read correctly, it is just compressed. How do I decompress it?
If you want to read an image as a bitmap or as rgb values, you need to transform the image's format first.
Jpeg is a compressed image format, you need to use a tool or library in order to read as rgb.
check this answer:
How to get the rgb values of a jpeg image in TYPE_3BYTE_BGR?
Hope this helps

How to rotate a jpeg lossless (90, 180, 270, 360) [duplicate]

This question already has answers here:
Lossless JPEG Rotate (90/180/270 degrees) in Java?
(5 answers)
Closed 8 years ago.
I want to rotate an jpeg image lossless.
My code works with success but is with loss:
ByteArrayInputStream inputstream = new ByteArrayInputStream(imgByteArraySource);
BufferedImage oldBufferedImage = ImageIO.read(inputstream);
BufferedImage newBufferedImage = rotate(oldBufferedImage, degrees);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(newBufferedImage, "jpg", baos);
baos.flush();
byte[] imageInByte = baos.toByteArray();
I found an old post on this site:
Lossless JPEG Rotate (90/180/270 degrees) in Java?
Maybe there is a better solution.
I'm not very confident about the media-util library (it is old, and it is packaged in a .exe file).
Has someone an idea?
Is there a new and better way to do this?
Thanks in advance.
Bobby
It is only possible to rotate losslessly in 90 degree increments.
To do it in 90 increments, you need to either compress using the same quantization tables used in the original (which still may introduce loss, depending upon the encoder) or use a special program that rearranges the MCUs in the JPEG stream.
Any time you decompress a JPEG using different quantization tables you will get loss.

How to prevent loss of image quality while using ImageIO.write() method?

I am dealing with Images in java where I do read and write Images in my local disk. My Problem is while writing Images I am losing the quality of the actual Image I read. It reduces the quality by image file size from 6.19MB(actual image size) file to 1.22MB(written using ImageIO.write() which is drastic loss. How can I prevent this loss when i do use
ImageIO.write(image, "jpg", os);
for writing Image.
Remember, I dont need any compression over here. Just I want to read the Image and write the same image with same quality and same file Size. I also tried,
writer.write(null, new IIOImage(image, null, null), param);
but it takes my execution time more and does a compression process.
Please help me out in this. Is there any chance to write lossless image quality using
ImageIO.write(image, "jpg", os);
or any other way?
Thanks in advance...!
You seem to be a little confused about JPEG "compression" and "quality" (and I partly blame the ImageIO API for that, as they named the setting "compressionQuality").
JPEG is always going to compress. That's the point of the format. If you don't want compression, JPEG is not the format you want to use. Try uncompressed TIFF or BMP. As the commenters have already said, normal JPEG is always going to be lossy (JPEG-LS and JPEG Lossless are really different algorithms btw).
If you still want to go with JPEG, here's some help. Unfortunately, there's no way to control the "compressionQuality" setting using:
ImageIO.write(image, "jpg", os);
You need to use the more verbose form:
ImageReader reader = ...;
reader.setInput(...);
IIOImage image = reader.readAll(0, null); // Important, also read metadata
RenderedImage renderedImage = image.getRenderedImage();
// Modify renderedImage as you like
ImageWriter writer = ImageIO.getImageWriter(reader);
ImageWriteParam param = writer.getDefaultWriteParam();
paran.setCompressionMode(MODE_COPY_FROM_METADATA); // This modes ensures closest to original compression
writer.setOutput(...);
writer.write(null, image, param); // Write image along with original meta data
Note: try/finally blocks and stream close()and reader/writer dispose() omitted for clarity. You'll want them in real code. :-)
And this shouldn't really make your execution time noticeably longer, as ImageIO.write(...) uses similar code internally.

Resizing images in PDF using iText: incompatible color conversion

I'm trying to reduce the filesize of a few PDF's in Java. I've found a few techniques to do this. But resizing images seems most effective.
I followed this piece of code which uses iText.
It works great on a few PDF's (reduction from 4.5MB to 800KB!) but some stayed unaffected.
I altered the code a bit as follows, so it would accept more Stream objects (and hopefully compress more):
PdfReader reader = new PdfReader(original.getPath());
int size = reader.getXrefSize();
for(int i=0;i<size;i++){
PdfObject object = reader.getPdfObject(i);
if (object == null || !object.isStream())
continue;
PRStream stream = (PRStream)object;
PdfImageObject image = new PdfImageObject(stream);
try{
BufferedImage bi = image.getBufferedImage();
//more stuff here
And it did! Some PDF's actually got compressed a lot more. However, I got a strange exception at some that didn't change at all:
javax.imageio.IIOException: Incompatible color conversion
at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkColorConversion(JPEGImageReader.java:927)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1028)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:984)
at javax.imageio.ImageIO.read(ImageIO.java:1438)
at javax.imageio.ImageIO.read(ImageIO.java:1342)
at com.itextpdf.text.pdf.parser.PdfImageObject.getBufferedImage(PdfImageObject.java:302)
at com.example.compression.App.main(App.java:56)
(App.java:56 being the line that says image.getBufferedImage();)
Some research discovered, the Stream it was trying to open was a CMYK JPG.
I'm wondering why these wouldn't open, and how I can resize these images anyway.
Thanks
BufferedImage doesn't deal with CMYK nativally (and I'm not sure if Java does in other native components, anyway).
In the fields listed in Java 6 docs, there's no cmyk color model....
You can take a look at this site, someone tells you how to deal with BufferedImage and CMYK colorspace.
Good luck!

java pgm 2 jpeg/png

I have an int array containing gray scale values from 0-254, i also have the x and y size of the image. It is an easy thing to create an pgm image, but i want to display it in a jsp, so i need somehow to convert it to a jpeg or png image.
If you suggest jai, than please tell me at which classes to look, or how to actually do it in jai.
Thanks a lot, in advance.
Maybe skip the PGM entirely?
int[] myImage = getGreyscaleIntArray();
BufferedImage im = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
WritableRaster raster = im.getRaster();
for(int h=0;h<height;h++)
{
for(int w=0;w<width;w++)
{
raster.setSample(w,h,0, myImage[h * width + w]);
}
}
ByteArrayOutputStream myJpg = new ByteArrayOutputStream();
javax.imageio.ImageIO.write(im, "jpg", myJpg);
uses the JAI ImageIO api, specifically the ImageIO utility class
WriteableRaster sample from the Java Image Processing cookbook
ImageMagick works well for converting images and Jmagick provides an interface to call directly from java programs.

Categories