BufferedImage turns all black after scaling via canvas - java

I have a method which purpose is to receive an image and return it scaled down.
The reason I'm using canvas is that I believe that it will scale the image automatically for me.
After the conversion the outputimage is completely black. Anyone have any clue on how to fix this?
try {
InputStream in = new ByteArrayInputStream(f.getBytes());
BufferedImage image = ImageIO.read(in);
File beforescale = new File("beforescale.jpg");
ImageIO.write(image, "jpg", beforescale); //works
Canvas canvas = new Canvas();
canvas.setSize(100, 100);
canvas.paint(image.getGraphics());
image = canvasToImage(canvas);
File outputfile = new File("testing.jpg");
ImageIO.write(image, "jpg", outputfile); //all black
response.getWriter().print(canvas);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private BufferedImage canvasToImage(Canvas cnvs) {
int w = cnvs.getWidth();
int h = cnvs.getHeight();
int type = BufferedImage.TYPE_INT_RGB;
BufferedImage image = new BufferedImage(w,h,type);
Graphics2D g2 = image.createGraphics();
cnvs.paint(g2);
g2.dispose();
return image;
}

The problem is, here you use canvas#paint(Graphics) to paint the image on the canvas:
canvas.paint(image.getGraphics());
And here you canvas#paint(Graphics) again to paint the canvas on the image:
cnvs.paint(g2);
Obviously one of these two fails. You can only use this method to paint the canvas on the image.
The solution is to use getScaledInstance() on image.
BufferedImage image = ImageIO.read(in);
Image smallerImg = image.getScaledInstance(100,100,Image.SCALE_SMOOTH);
ImageIO.write(smallerImg, "jpg", outputfile);

Related

Convert an ImageIcon to a Base64 String and back to an ImageIcon without saving to disk?

I'm trying to store an imageIcon bas a Base64 String.
This is what I have so far:
public ImageIcon getImageIcon() {
if(imageIcon == null || imageIcon.isEmpty()){
return null;
} else {
try {
byte[] btDataFile = Base64.decodeBase64(imageIcon);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(btDataFile));
return new ImageIcon(image);
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
return null;
}
}
}
public void setImageIcon(ImageIcon imageIconIn) {
imageIcon = Base64.encodeBase64String(imageToByteArray(imageIconIn));
}
public static byte[] imageToByteArray(ImageIcon imageIn) {
try {
BufferedImage image = new BufferedImage(imageIn.getIconWidth(), imageIn.getIconHeight(),BufferedImage.TYPE_INT_RGB);
ByteArrayOutputStream b = new ByteArrayOutputStream();
// FIX
Graphics g;
g = image.createGraphics();
imageIn.paintIcon(null, g, 0,0);
// END FIX
ImageIO.write(image, "jpg", b );
g.dispose();
return b.toByteArray();
} catch (IOException ex) {
System.out.println(ex.getLocalizedMessage());
return null;
}
}
I get a black rectangle instead of the image.
I'm using Java 1.8 on Ubuntu 16.04.
What am I doing wrong?
Thanks for your help.
******************************** . FIXED . ******************************
I found a working solution and updated the above code.
******************************** EDIT *********************************
Added g.dispose() after painting icon.
This code creates a brand new BufferedImage, with width & height same as the given image.
BufferedImage image = new BufferedImage(
imageIn.getIconWidth(),
imageIn.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Note that the image is empty. No content has been written to it. The bytes will all be zero, and RGB 0x000000 is black.
Then, you are writing the bytes of this black image to your ByteArrayOutputStream.
ByteArrayOutputStream b = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", b );
return b.toByteArray();
Of course, when you convert that byte buffer back to an image, it will be black.
You will want to draw/copy imageIn into your new image before you write out the bytes.
But if you don't mind using whatever the current image's format is, you could just write out that image instead of converting it to TYPE_INT_RGB...
Image image = imageIn.getImage();
// write image to ByteArrayOutputStream

How to convert Image into BufferedImage

Right now I have an image and I want to convert it into a BufferedImage...
This is my code -
private BufferedImage toBufferedImage(Image img, int width, int height){
// Create a buffered image with transparency
BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// Draw the image on to the buffered image
Graphics bGr = bimage.getGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
// Return the buffered image
return bimage;
}
But it doesn't work. Can someone explain what's wrong?
Try the new JRE that includes JavaFX.
You could use SwingFXUtils. There is a method which does what you ask for:
BufferedImage image = SwingFXUtils.fromFXImage(fxImage, null);
or
BufferedImage image = ImageIO.read(new File(filename));
BufferedImage extends Image, so you can cast it:
BufferedImage buffered = (BufferedImage) image;
But you must check the type of your image object in runtime, because it can contain other kind of Image.
UPDATE
To convert an Image to a BufferedImage you should check this class and try it:
http://www.dzone.com/snippets/converting-images

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);

Java: Merging 2 images is not working

I'm trying to read 2 image files, then merge image2 on top of image1, but the code below does not seem to work. After saving, I only see image1 as original.
Both images are PNG.
String url= uploadPath + filename;
BufferedImage im = ImageIO.read(url);
String url2= "image2.png";
BufferedImage im2 = ImageIO.read(url);
Graphics2D g = im.createGraphics();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
g.drawImage(im2, im.getWidth()/2, im.getHeight()/2, null);
g.dispose();
ImageIO.write(im, "png", new File( url ));
What did I miss here?
Thanks
I had no issues getting it to work.
I did find this line...
g.drawImage(im2, im.getWidth()/2, im.getHeight()/2, null);
Of a little concern. It MIGHT be possible to render the image outside of the background image, if the image sizes are just right. You should be using coordinates that are relative to the master image...
public class MergeImages {
public static void main(String[] args) {
File inner = new File("Inner.png");
File outter = new File("Outter.png");
try {
BufferedImage biInner = ImageIO.read(inner);
BufferedImage biOutter = ImageIO.read(outter);
System.out.println(biInner);
System.out.println(biOutter);
Graphics2D g = biOutter.createGraphics();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
int x = (biOutter.getWidth() - biInner.getWidth()) / 2;
int y = (biOutter.getHeight() - biInner.getHeight()) / 2;
System.out.println(x + "x" + y);
g.drawImage(biInner, x, y, null);
g.dispose();
ImageIO.write(biOutter, "PNG", new File("Outter.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
I'd also double check shuangwhywhy suggestion of making sure you not reading in the same file twice ... I did that some thing when testing the code :P
Your problem is im2 is exactly the same as im:
BufferedImage im = ImageIO.read(url);
BufferedImage im2 = ImageIO.read(url);
I guess it is a typo: it should be url2 rather than url to be read as im2, Am I right?
BufferedImage im2 = ImageIO.read(url2);
You can also try SRC_ATOP with the transparency 0.5.

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