Java: Merging 2 images is not working - java

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.

Related

How to place two images in one canvas through java (not jframe)

I just want to place two different images on one canvas and make it a .jpg file in Java. I just want to make a resulting file, not a GUI.
I want to make a result file like below with both images above:
You can use BufferedImage to combine the two images. The following code shows a simple implementation:
public static void combineImages(String imagePath1, String imagePath2, String outputPath) throws IOException {
int intervalWidth = 20; // The interval between two images
BufferedImage image1 = ImageIO.read(new File(imagePath1));
BufferedImage image2 = ImageIO.read(new File(imagePath2));
int combinedWidth = image1.getWidth() + image2.getWidth() + intervalWidth;
int combinedHeight = Math.max(image1.getHeight(), image2.getHeight());
BufferedImage combined = new BufferedImage(combinedWidth, combinedHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = combined.createGraphics();
g.setColor(Color.WHITE);
// Fill the background with white
g.fillRect(0, 0, combinedWidth, combinedHeight);
// Draw the two images on the combined image
g.drawImage(image1, 0, 0, null);
g.drawImage(image2, image1.getWidth() + intervalWidth, 0, null);
ImageIO.write(combined, "jpg", new File(outputPath));
}

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

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

BufferedImage turns all black after scaling via canvas

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

My batch jpg resizer works with color images, but grayscale ones become washed out

I've been having a problem with my Java program. It's for resizing images. You drop it into a folder and run it, and it creates a new folder with the resized images. It works great on color, but it has a problem with grayscale. The images are converted, but they become lighter and more washed out, as if someone has messed with the curves or levels. All the input files and output files are sRGB color space jpegs, saved in RGB color mode. I have thousands of 50 megapixel film scans I'm trying to convert down to 15 megapixels or less. Any help or ideas anyone could offer would be most appreciated. The programs full code is below, it's about 130 lines. I have a feeling the problem may be in the toBufferedImage function but I'm lost as to what it could be.
package jpegresize;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;
import javax.imageio.*;
import javax.imageio.stream.*;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
System.out.println("JPEGResize running . . .");
int max_side = 4096;
float quality = 0.9f;
if(args.length == 0) System.out.println("No maximum side resolution or compression quality arguments given, using default values.\nUsage: java -jar JPEGResize.jar <maximum side resolution in pixels> <quality 0 to 100 percent>");
if(args.length >= 1) max_side = Integer.parseInt(args[0]);
if(args.length >= 2) quality = Float.parseFloat(args[1]) / 100.0f;
System.out.println("Maximum side resolution: " + max_side);
System.out.println("Compression quality: " + (quality * 100) + "%");
File folder = new File(".");
File[] listOfFiles = folder.listFiles(new JPEGFilter());
for(int i = 0; i < listOfFiles.length; i++) {
System.out.println("Processing " + listOfFiles[i].getName() + " . . .");
resizeFile(listOfFiles[i].getName(), max_side, quality);
System.out.println("Saved /resized/" + listOfFiles[i].getName());
}
System.out.println("Operations complete.");
}
public static void resizeFile(String filename, int max_side, float quality) {
try
{
BufferedImage input_img = ImageIO.read(new File(filename));
double aspect_ratio = ((double)input_img.getWidth()) / ((double)input_img.getHeight());
int width, height;
if(input_img.getWidth() >= input_img.getHeight()) {
width = max_side;
height = (int)(((double)max_side) / aspect_ratio);
}
else {
width = (int)(((double)max_side) * aspect_ratio);
height = max_side;
}
Image scaled_img = input_img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage output_img = toBufferedImage(scaled_img);
Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = (ImageWriter)iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(quality);
File doesDirExist = new File("resized/");
if(!doesDirExist.exists())
new File("resized").mkdir();
File file = new File("resized/" + filename);
FileImageOutputStream output = new FileImageOutputStream(file);
writer.setOutput(output);
IIOImage image = new IIOImage(output_img, null, null);
writer.write(null, image, iwp);
writer.dispose();
}
catch (IOException e)
{
e.printStackTrace();
}
}
// This method returns a buffered image with the contents of an image
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage)image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
// Create a buffered image with a format that's compatible with the screen
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try {
// Determine the type of transparency of the new buffered image
int transparency = Transparency.OPAQUE;
// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(
image.getWidth(null), image.getHeight(null), transparency);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
}
class JPEGFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
return (name.toLowerCase().endsWith(".jpg")) || (name.toLowerCase().endsWith(".jpeg"));
}
}
If jdk's classes and methods are buggy, report the bug to oracle (oh! I wish I could go on saying to SUN..).
And, while the next release will correct the bug ;), try some work arounds, scaling image by yourself like proposed here.
Regards,
Stéphane
In your code, you assume jpeg are encoded in RGB, but that's not always the case. It's also possible to encode 8 bit gray scaled jpeg. So I suggest that you try this when building your BufferedImage, replace :
BufferedImage.TYPE_INT_RGB;
by
BufferedImage.TYPE_BYTE_GRAY;
and see if it works for those images.
If so, then you still have to find out a way to determine the encoding type to automatically change the type of BufferedImage color encoding to use, but you will be one stop closer.
Regards,
Stéphane

Categories

Resources