Quality of Image After Resize Very Low - Java

Quality of Image after resize very low -- Java

The issue you are seeing is actually related to the resampling filter used for downscaling. Obviously, the one used by your library is a bad one for the situation. Nearest neighbor, bilinear and bicubic are typical bad examples to be used when downscaling. I don't know the exact resampling filter Photoshop uses, but I used 3-lobed lanczos and got the following result:

Sample Image

So, to solve your problem, you need to use a smarter resampling filter.

Image size after resizing is greater than original image

See the documentation for Bitmap.Compress(), especially the second parameter (quality):

quality Hint to the compressor, 0-100. 0 meaning compress for small size, 100 meaning compress for max quality. Some formats, like PNG which is lossless, will ignore the quality setting

Just use a lower quality setting to get a smaller file. It is quite possible for a resized image of a lower resolution to end up with a larger filesize than the original if the quality setting passed to Bitmap.compress() is large, and the original file was saved with a low quality setting.

So just try using a lower quality value e.g:

bitmap.compress(Bitmap.CompressFormat.JPEG, 75 /*quality setting*/, outputStream);

Experiment with different quality settings until you find a good trade off between quality and file size.

Image resize quality (Java)

I've tried it all - including the tricks here, and all I can say is that you're better of using ImageMagick with whatever interface. Javas imaging libraries are just not up to snuff when it comes to this. You need to support so many formats and algorithms to get it right.

Re-sizing an image without losing quality

The best article I have ever read on this topic is The Perils of Image.getScaledInstance() (web archive).

In short: You need to use several resizing steps in order to get a good image. Helper method from the article:

public BufferedImage getScaledInstance(BufferedImage img,
int targetWidth,
int targetHeight,
Object hint,
boolean higherQuality)
{
int type = (img.getTransparency() == Transparency.OPAQUE) ?
BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = (BufferedImage)img;
int w, h;
if (higherQuality) {
// Use multi-step technique: start with original size, then
// scale down in multiple passes with drawImage()
// until the target size is reached
w = img.getWidth();
h = img.getHeight();
} else {
// Use one-step technique: scale directly from original
// size to target size with a single drawImage() call
w = targetWidth;
h = targetHeight;
}

do {
if (higherQuality && w > targetWidth) {
w /= 2;
if (w < targetWidth) {
w = targetWidth;
}
}

if (higherQuality && h > targetHeight) {
h /= 2;
if (h < targetHeight) {
h = targetHeight;
}
}

BufferedImage tmp = new BufferedImage(w, h, type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();

ret = tmp;
} while (w != targetWidth || h != targetHeight);

return ret;
}

Image quality issues using Java library imgsclr to RESIZE

I don't think the core issue is with imgsclr, but with the choice of jpg. Remember, jpg uses a loss-based algorithm, dumping parts of the image to reduce it's size.

For comparison, the two images below were produced using the same methods, but the left was output using jpg and the right using png (using the ImageIO API)

Compare

So the top image is the same master image.

The second row is imgsclr using ULTRA_QUALITY, AUTOMATIC, BALANCED and QUALITY methods. The last image on the second row is using SPEED

The last row is a serious of "other" scaling methods. The first two use a divide and conquer approach, dividing the image by 2 until it reaches it's desired size, demonstrated here. The first is a "to fill" and the other is "to fit" (one will overfill the available space, one will fit within). The third image is using Image#getScaledInstance and I seem to have introduced a alpha channel somewhere, hence the reason the jpg version is red, but I was comparing quality ;)

The reason for the size increase may come down to imgsclr attempting to maintain the aspect ratio of the image

And finally...

Sample Image

This compares BufferedImageOp, using OP_BRIGHTER, OP_ANTIALIAS and OP_BRIGHTER, OP_ANTIALIAS, none from right to left...

These are output as PNGs

Image Resize UpScale lost Quality

The fact is that when you scale an image up, it has to create data where there was none. (Roughly speaking). To do this, you have to interpolate between the existing pixels to fill in the new ones. You may be able to get better results by trying different kinds of interpolation - but the best method will be different for different kinds of images.

Since your sample image is just squares, nearest-neighbour interpolation will likely give you the best results. If you are scaling up an image of scenery or maybe a portrait you'll need a more clever algorithm.

The result will rarely look perfect, and it's best to start with a larger image if possible!

Take a look here to get an understanding of the problem. http://en.wikipedia.org/wiki/Image_scaling#Scaling_methods

decrease image resolution in java

This is the working code

public class ImageCompressor {
public void compress() throws IOException {
File infile = new File("Y:\\img\\star.jpg");
File outfile = new File("Y:\\img\\star_compressed.jpg");

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
infile));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(outfile));

SeekableStream s = SeekableStream.wrapInputStream(bis, true);

RenderedOp image = JAI.create("stream", s);
((OpImage) image.getRendering()).setTileCache(null);

RenderingHints qualityHints = new RenderingHints(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);

RenderedOp resizedImage = JAI.create("SubsampleAverage", image, 0.9,
0.9, qualityHints);

JAI.create("encode", resizedImage, bos, "JPEG", null);

}

public static void main(String[] args) throws IOException {

new ImageCompressor().compress();
}
}

This code is Working Great for me. if you need to resize the image then you can
change the x and y scale here JAI.create("SubsampleAverage", image, xscale,yscale, qualityHints);



Related Topics



Leave a reply



Submit