After transform image using AffineTransform, photo get low quality - java

I'm trying to fixing photo direction using EXIF information, the photo rotated correctly but after rotate they becomes very low quality...My guess is parameter passed during write new image is wrong. Any help appreciated.
//code get Exif information
Metadata metadata = ImageMetadataReader.readMetadata(outputFile);
Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
if(directory == null) {
logger.warn("no EXIF info.");
outputFile.delete();
return;
}
JpegDirectory jpegDirectory = metadata.getFirstDirectoryOfType(JpegDirectory.class);
int orientation;
try {
orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
if(orientation != 1) {
//rotate image
int w = jpegDirectory.getImageWidth();
int h = jpegDirectory.getImageHeight();
ImageInformation imageInformation = new ImageInformation(orientation, w, h);
AffineTransform affineTransform = getExifTransformation(imageInformation);
InputStream pictureStream = new FileInputStream(outputFile);
BufferedImage pictureBuffer = ImageIO.read(pictureStream);
pictureStream.close();
if (pictureBuffer == null) {
logger.warn("The picture buffer parsed is null.");
}
pictureBuffer = transformImage(pictureBuffer, affineTransform);
//code do image transfer
public static BufferedImage transformImage(BufferedImage image, AffineTransform transform) throws Exception {
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);
BufferedImage destinationImage = op.createCompatibleDestImage(image, null );
Graphics2D g = destinationImage.createGraphics();
g.setBackground(Color.WHITE);
g.clearRect(0, 0, destinationImage.getWidth(), destinationImage.getHeight());
destinationImage = op.filter(image, destinationImage);
return destinationImage;
}

Thanks all the helps:-)
After change transform function to this, problem solved, not sure why it's the case, gpasch may be right
public static BufferedImage transformImage(BufferedImage image, AffineTransform transform) throws Exception {
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);
BufferedImage destinationImage = new BufferedImage(image.getWidth(),image.getHeight(), image.getType());
destinationImage = op.filter(image, destinationImage);
return destinationImage;
}

This may solve your problem. According to AffineTransformOp
"If destCM is null, an appropriate ColorModel is used; this ColorModel may
have an alpha channel even if the source ColorModel is opaque."
Therefore I suggest the following:
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);
BufferedImage destinationImage = op.createCompatibleDestImage(image, null );
destinationImage = op.filter(image, null);
return destinationImage;
or even forgo the compatible image:
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);
BufferedImage destinationImage = op.filter(image, null);
return destinationImage;
Also I'm not sure Bicubic is all that important but may not be the problem.
Because the compatible image returns an image with alpha i.e. transparent
this
Graphics2D g = destinationImage.createGraphics();
g.setBackground(Color.WHITE);
g.clearRect(0, 0, destinationImage.getWidth(), destinationImage.getHeight());
will put a layer of transparency on the image; the image painted afterward with be fused with the white color.

Keep it simple and you should use the dimensions expected from the operation:
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
BufferedImage destinationImage = op.filter(bImage, op.createCompatibleDestImage(bImage, null));

Related

change image size in java [duplicate]

I have a PNG image and I want to resize it. How can I do that? Though I have gone through this I can't understand the snippet.
If you have an java.awt.Image, resizing it doesn't require any additional libraries. Just do:
Image newImage = yourImage.getScaledInstance(newWidth, newHeight, Image.SCALE_DEFAULT);
Obviously, replace newWidth and newHeight with the dimensions of the specified image.
Notice the last parameter: it tells the runtime the algorithm you want to use for resizing.
There are algorithms that produce a very precise result, however these take a large time to complete.
You can use any of the following algorithms:
Image.SCALE_DEFAULT: Use the default image-scaling algorithm.
Image.SCALE_FAST: Choose an image-scaling algorithm that gives higher priority to scaling speed than smoothness of the scaled image.
Image.SCALE_SMOOTH: Choose an image-scaling algorithm that gives higher priority to image smoothness than scaling speed.
Image.SCALE_AREA_AVERAGING: Use the Area Averaging image scaling algorithm.
Image.SCALE_REPLICATE: Use the image scaling algorithm embodied in the ReplicateScaleFilter class.
See the Javadoc for more info.
We're doing this to create thumbnails of images:
BufferedImage tThumbImage = new BufferedImage( tThumbWidth, tThumbHeight, BufferedImage.TYPE_INT_RGB );
Graphics2D tGraphics2D = tThumbImage.createGraphics(); //create a graphics object to paint to
tGraphics2D.setBackground( Color.WHITE );
tGraphics2D.setPaint( Color.WHITE );
tGraphics2D.fillRect( 0, 0, tThumbWidth, tThumbHeight );
tGraphics2D.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR );
tGraphics2D.drawImage( tOriginalImage, 0, 0, tThumbWidth, tThumbHeight, null ); //draw the image scaled
ImageIO.write( tThumbImage, "JPG", tThumbnailTarget ); //write the image to a file
Try this:
ImageIcon icon = new ImageIcon(UrlToPngFile);
Image scaleImage = icon.getImage().getScaledInstance(28, 28,Image.SCALE_DEFAULT);
Resize image with high quality:
private static InputStream resizeImage(InputStream uploadedInputStream, String fileName, int width, int height) {
try {
BufferedImage image = ImageIO.read(uploadedInputStream);
Image originalImage= image.getScaledInstance(width, height, Image.SCALE_DEFAULT);
int type = ((image.getType() == 0) ? BufferedImage.TYPE_INT_ARGB : image.getType());
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g2d = resizedImage.createGraphics();
g2d.drawImage(originalImage, 0, 0, width, height, null);
g2d.dispose();
g2d.setComposite(AlphaComposite.Src);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(resizedImage, fileName.split("\\.")[1], byteArrayOutputStream);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
} catch (IOException e) {
// Something is going wrong while resizing image
return uploadedInputStream;
}
}
int newHeight = 150;
int newWidth = 150;
holder.iv_arrow.requestLayout();
holder.iv_arrow.getLayoutParams().height = newHeight;
holder.iv_arrow.getLayoutParams().width = newWidth;
holder.iv_arrow.setScaleType(ImageView.ScaleType.FIT_XY);
holder.iv_arrow.setImageResource(R.drawable.video_menu);
Simple way in Java
public void resize(String inputImagePath,
String outputImagePath, int scaledWidth, int scaledHeight)
throws IOException {
// reads input image
File inputFile = new File(inputImagePath);
BufferedImage inputImage = ImageIO.read(inputFile);
// creates output image
BufferedImage outputImage = new BufferedImage(scaledWidth,
scaledHeight, inputImage.getType());
// scales the input image to the output image
Graphics2D g2d = outputImage.createGraphics();
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose();
// extracts extension of output file
String formatName = outputImagePath.substring(outputImagePath
.lastIndexOf(".") + 1);
// writes to output file
ImageIO.write(outputImage, formatName, new File(outputImagePath));
}
Design jLabel first:
JLabel label1 = new JLabel("");
label1.setHorizontalAlignment(SwingConstants.CENTER);
label1.setBounds(628, 28, 169, 125);
frame1.getContentPane().add(label1); //frame1 = "Jframe name"
Then you can code below code:
ImageIcon imageIcon1 = new ImageIcon(new ImageIcon("add location url").getImage().getScaledInstance(100, 100, Image.SCALE_DEFAULT)); //100, 100 add your own size
label1.setIcon(imageIcon1);

How can i auto-size image when frame is maximised? [duplicate]

I have a PNG image and I want to resize it. How can I do that? Though I have gone through this I can't understand the snippet.
If you have an java.awt.Image, resizing it doesn't require any additional libraries. Just do:
Image newImage = yourImage.getScaledInstance(newWidth, newHeight, Image.SCALE_DEFAULT);
Obviously, replace newWidth and newHeight with the dimensions of the specified image.
Notice the last parameter: it tells the runtime the algorithm you want to use for resizing.
There are algorithms that produce a very precise result, however these take a large time to complete.
You can use any of the following algorithms:
Image.SCALE_DEFAULT: Use the default image-scaling algorithm.
Image.SCALE_FAST: Choose an image-scaling algorithm that gives higher priority to scaling speed than smoothness of the scaled image.
Image.SCALE_SMOOTH: Choose an image-scaling algorithm that gives higher priority to image smoothness than scaling speed.
Image.SCALE_AREA_AVERAGING: Use the Area Averaging image scaling algorithm.
Image.SCALE_REPLICATE: Use the image scaling algorithm embodied in the ReplicateScaleFilter class.
See the Javadoc for more info.
We're doing this to create thumbnails of images:
BufferedImage tThumbImage = new BufferedImage( tThumbWidth, tThumbHeight, BufferedImage.TYPE_INT_RGB );
Graphics2D tGraphics2D = tThumbImage.createGraphics(); //create a graphics object to paint to
tGraphics2D.setBackground( Color.WHITE );
tGraphics2D.setPaint( Color.WHITE );
tGraphics2D.fillRect( 0, 0, tThumbWidth, tThumbHeight );
tGraphics2D.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR );
tGraphics2D.drawImage( tOriginalImage, 0, 0, tThumbWidth, tThumbHeight, null ); //draw the image scaled
ImageIO.write( tThumbImage, "JPG", tThumbnailTarget ); //write the image to a file
Try this:
ImageIcon icon = new ImageIcon(UrlToPngFile);
Image scaleImage = icon.getImage().getScaledInstance(28, 28,Image.SCALE_DEFAULT);
Resize image with high quality:
private static InputStream resizeImage(InputStream uploadedInputStream, String fileName, int width, int height) {
try {
BufferedImage image = ImageIO.read(uploadedInputStream);
Image originalImage= image.getScaledInstance(width, height, Image.SCALE_DEFAULT);
int type = ((image.getType() == 0) ? BufferedImage.TYPE_INT_ARGB : image.getType());
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g2d = resizedImage.createGraphics();
g2d.drawImage(originalImage, 0, 0, width, height, null);
g2d.dispose();
g2d.setComposite(AlphaComposite.Src);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(resizedImage, fileName.split("\\.")[1], byteArrayOutputStream);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
} catch (IOException e) {
// Something is going wrong while resizing image
return uploadedInputStream;
}
}
int newHeight = 150;
int newWidth = 150;
holder.iv_arrow.requestLayout();
holder.iv_arrow.getLayoutParams().height = newHeight;
holder.iv_arrow.getLayoutParams().width = newWidth;
holder.iv_arrow.setScaleType(ImageView.ScaleType.FIT_XY);
holder.iv_arrow.setImageResource(R.drawable.video_menu);
Simple way in Java
public void resize(String inputImagePath,
String outputImagePath, int scaledWidth, int scaledHeight)
throws IOException {
// reads input image
File inputFile = new File(inputImagePath);
BufferedImage inputImage = ImageIO.read(inputFile);
// creates output image
BufferedImage outputImage = new BufferedImage(scaledWidth,
scaledHeight, inputImage.getType());
// scales the input image to the output image
Graphics2D g2d = outputImage.createGraphics();
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose();
// extracts extension of output file
String formatName = outputImagePath.substring(outputImagePath
.lastIndexOf(".") + 1);
// writes to output file
ImageIO.write(outputImage, formatName, new File(outputImagePath));
}
Design jLabel first:
JLabel label1 = new JLabel("");
label1.setHorizontalAlignment(SwingConstants.CENTER);
label1.setBounds(628, 28, 169, 125);
frame1.getContentPane().add(label1); //frame1 = "Jframe name"
Then you can code below code:
ImageIcon imageIcon1 = new ImageIcon(new ImageIcon("add location url").getImage().getScaledInstance(100, 100, Image.SCALE_DEFAULT)); //100, 100 add your own size
label1.setIcon(imageIcon1);

Error: sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage

please help me cant do this thing to work to me sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage
if (shape.hasImage())
{
// If this shape is an image, extract image to file
String extension = ImageTypeToExtension(shape.getImageData().getImageType());
String imageFileName = MessageFormat.format("Image.ExportImages.{0} Out.{1}", imageIndex, extension);
String strBarCodeImageExtracted = "" + imageFileName;
shape.getImageData().save(strBarCodeImageExtracted);
// Recognize barcode from this image
BarCodeReader reader = new BarCodeReader ((BufferedImage) Toolkit.getDefaultToolkit().getImage(strBarCodeImageExtracted),BarCodeReadType.Code39Standard);
while (reader.read())
{
System.out.println("codetext: " + reader.getCodeText());
}
imageIndex++;
}
EDIT: This answer was accepted after the comment was written, so one has to assume that the comment was the actual solution. The comment was
... to replace Toolkit.getDefaultToolkit().getImage(...) with ImageIO.read(...) ...
Original answer:
You may either try to read the image direcly with ImageIO, or consider painting the image into a newly allocated BufferedImage, e.g. with a method like
public static BufferedImage convertToBufferedImage(Image image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(null), image.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
And then in your case:
Image image = Toolkit.getDefaultToolkit().getImage(strBarCodeImageExtracted);
BufferedImage bufferedImage = convertToBufferedImage(image);
BarCodeReader reader = new BarCodeReader(bufferedImage,BarCodeReadType.Code39Standard);

Generate thumbnail and fill empty space with color

Is it possible to implement the first example with Scalr?
My code is the following:
BufferedImage thumbnail = Scalr.resize(ImageIO.read(sourceFile), Scalr.Method.ULTRA_QUALITY, Scalr.Mode.FIT_TO_WIDTH,
width, height, Scalr.OP_ANTIALIAS);
ImageIO.write(thumbnail, destinationfile.getExtension(), destinationfile);
What I want is to receive the image like this:
where the blue bars are the space I want to fill with the color.
Thank you
Update: maybe it is possible to implement with Thumbnailator?
Just done! Perhaps it can help you!
public static BufferedImage resizeAndCrop(BufferedImage bufferedImage) throws IOException {
int himg = bufferedImage.getHeight();
int wimg = bufferedImage.getWidth();
double rateh = himg/dim;
double ratew = wimg/dim;
double rate = ratew;
if(rateh>ratew)
rate = rateh;
int dimhimg = (int) (himg/rate);
int dimwimg = (int) (wimg/rate);
double startw = dim/2 - dimwimg/2;
double starth = dim/2 - dimhimg/2;
BufferedImage tThumbImage = new BufferedImage( dim, dim, BufferedImage.TYPE_INT_RGB );
Graphics2D tGraphics2D = tThumbImage.createGraphics(); //create a graphics object to paint to
tGraphics2D.setBackground( Color.WHITE );
tGraphics2D.setPaint( Color.WHITE );
tGraphics2D.fillRect( 0, 0, dim, dim );
tGraphics2D.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
tGraphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
tGraphics2D.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
tGraphics2D.drawImage( bufferedImage, (int)startw, (int)starth, dimwimg, dimhimg, null ); //draw the image scaled
File ff = new File(path + "jdata/tmp/prova.jpg");
ImageIO.write( tThumbImage, "JPG", ff); //write the image to a file
BufferedImage croppedContainMethod = ImageIO.read(ff);
return croppedContainMethod;
}
Nobody has idea so I will publish my solution...
I decided to continue to use Scalr (I didn't checked the Thumbnailator's last version but the previous ones failed on big pictures).
So first of all I call resize method, and then, if sizes of the new thumbnail are bigger then given ones I call crop method that crops a thumbnail by the center.. The code is the following:
BufferedImage thumbnail = Scalr.resize(sourceFile, Scalr.Method.ULTRA_QUALITY, Scalr.Mode.AUTOMATIC, destinationSize.width, destinationSize.height);
if (thumbnail.getWidth() > destinationSize.width)
thumbnail = Scalr.crop(thumbnail, (thumbnail.getWidth() - destinationSize.width) / 2, 0, destinationSize.width, destinationSize.height);
else if (thumbnail.getHeight() > destinationSize.height)
thumbnail = Scalr.crop(thumbnail, 0, (thumbnail.getHeight() - destinationSize.height) / 2, destinationSize.width, destinationSize.height);
It is not ideal, but at least it handles 'wide' images after generation of thumbnails

Background is black when rotating an image

I'm trying to rotate an image using this code:
File imgPath = new File("c:\\tmp\\7.jpg");
BufferedImage src = ImageIO.read(imgPath);
AffineTransform tx = new AffineTransform();
int width = src.getWidth();
int height = src.getHeight();
tx.rotate(radiant ,width, height);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
BufferedImage out = op.filter(src, null);
File outFile = new File("c:\\tmp\\out.jpg");
ImageIO.write(out, "jpg", outFile);
For some reason the background after the rotation is black.
How can make the background white or transparent?
When you are using AffineTransformOp.filter(src, null) for creating new images, the new image uses the same ColorModel as the source image.
Your input image is a jpeg, which means it is not transparent, so the destination image is an RGB image, without the alpha (transparency) level.
When rotated with such a small angle, the image no longer occupies exactly the same bounds, so the background is visible in its edges and because there is no alpha level, it is normal that the background is black.
However, if you save it to a format that supports transparency like gif or png, your image will not display the black background anymore.
ImageIO.write(out, "gif", outFile);
The full code:
try {
File imgPath = new File("d:\\downloads\\about.jpg");
BufferedImage src = ImageIO.read(imgPath);
AffineTransform tx = new AffineTransform();
int width = src.getWidth();
int height = src.getHeight();
tx.rotate(0.02050493823247637, width, height);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
BufferedImage out = op.filter(src, null);
File outFile = new File("d:\\downloads\\about0.gif");
ImageIO.write(out, "gif", outFile);
} catch (Exception e) {
e.printStackTrace();
}
Take a look at this for even more information and tricks.
Here is my image after rotation to gif:

Categories

Resources