Java combine images one on top of the other - java

I want to create one image from 2 images so the first one will be above the second one:
----------------
image1
----------------
----------------
image2
----------------
So the output image will have have the height and width of image 1 + image 2:
Here is my code:
private void combainImages(List<String> imageList, String combainedImages)
throws IOException {
//paths for the images
String aPath = imageList.get(0);
String bPath = imageList.get(1);
//as image
BufferedImage a = ImageIO.read(new File(aPath));
BufferedImage b = ImageIO.read(new File(bPath));
int aw = a.getWidth(); //551
int ah = a.getHeight(); //600
int bw = b.getWidth(); //551
int bh = b.getHeight(); //600
BufferedImage c = new BufferedImage(a.getHeight() + b.getHeight(),
a.getWidth() + b.getWidth(), BufferedImage.TYPE_INT_ARGB);
// 1200 1102
Graphics g = c.getGraphics();
g.drawImage(a, 0, 0, null);
g.drawImage(b, 0, a.getWidth(), null);
ImageIO.write(c, "PNG", new File(combainedImages));
}
The output for this is a big space between the 2 image.
Thanks for any help.

You're choosing the Y position based on the width rather than the height.
g.drawImage(b, 0, a.getWidth(), null);
should be
g.drawImage(b, 0, a.getHeight(), null);

Related

concat image file not able to create

I try to join two images. But not able to create it.
I am not able to understand what is the problem in the below code.
It is not able to create the concat.jpg file.
BufferedImage image = ImageIO.read(mainFile);
BufferedImage image1 = ImageIO.read(fileToMerge);
int width = Math.max(image.getWidth() , image1.getWidth());
int height = Math.max(image.getHeight() , image1.getHeight());
log.info("width {}", width);
log.info("height {}", height);
BufferedImage concatImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = concatImage.createGraphics();
graphics2D.drawImage(image, 0, image.getHeight(), null);
graphics2D.drawImage(image1, 0 , image1.getHeight(), null);
ImageIO.write(concatImage, "jpg", new File(Constants.LOCAL_FOLDER + "/concat.jpg"));
You want the height of concatImage to be the combined height of image and image1.
You want to draw image at coordinates (0,0) and you want to draw image1 at x = 0 and y = height of image
Try the following.
BufferedImage image = ImageIO.read(mainFile);
BufferedImage image1 = ImageIO.read(fileToMerge);
int width = Math.max(image.getWidth() , image1.getWidth());
int height = image.getHeight() + image1.getHeight();
log.info("width {}", width);
log.info("height {}", height);
BufferedImage concatImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = concatImage.createGraphics();
graphics2D.drawImage(image, 0, 0, null);
graphics2D.drawImage(image1, 0, image.getHeight(), null);
ImageIO.write(concatImage, "jpg", new File(Constants.LOCAL_FOLDER + "/concat.jpg"));
Note that you should call graphics2D.dispose() when you no longer need to use it.

Drawing new image over old image java

I need to draw a new image over old image. I first opened both images in BufferedImage and changed their white background to transparent. Then I got a Graphics2D object from the bufferedImage of old image and called drawImage method of Graphics2D class. I then saved the old image to disk. When I open the saved image I find only the old image with white background changed to transparent. Can anyone suggest me what is error with my code or how can I get to fix my error ?
BufferedImage newImage = ImageIO.read(new File("new.png"));
BufferedImage oldImage = ImageIO.read(new File("old.png"));
newImage = makeWhiteTransparent(newImage);
oldImage = makeWhiteTransparent(oldImage);
Graphics2D graphics = (Graphics2D) oldImage.getGraphics();
graphics.drawImage(newImage,null, 0,0);
File outputImage = new File("merged.png");
ImageIO.write(oldImage, "png", outputImage);
My makeWhiteTransparent method goes like this:
public static BufferedImage makeWhiteTransparent(BufferedImage img){
BufferedImage dst = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
dst.getGraphics().drawImage(img, 0, 0, null);
int markerRGB = Color.WHITE.getRGB() | 0xFF000000;
int width = dst.getWidth();
int height = dst.getHeight();
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
int rgb = dst.getRGB(x, y);
if ( ( rgb | 0xFF000000 ) == markerRGB ) {
int value = 0x00FFFFFF & rgb;
dst.setRGB(x, y, value);
}
}
}
return dst;
}
I tried changing graphics.drawImage(newImage, null,0,0) to graphics.drawImage(newImage, 0,0, null) and also changing TYPE_4BYTE_ABGR to TYPE_INT_ARGB as suggested but it did nothing. The error still exists.
This needs to be changed:
graphics.drawImage(newImage,null, 0,0);
to
graphics.drawImage(newImage, 0,0, null);
you are using the wrong version of drawImage - check http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html
--
Change also the type TYPE_4BYTE_ABGR to TYPE_INT_ARGB
--
Here's how it works for me:
public BufferedImage makeWhiteTransparent(BufferedImage img){
BufferedImage dst = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
dst.getGraphics().drawImage(img, 0, 0, null);
int markerRGB = 0x00ffffff; // Color.WHITE.getRGB() | 0xFF000000;
int width = dst.getWidth();
int height = dst.getHeight();
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
int rgb = dst.getRGB(x, y)&0x00ffffff;
if ( rgb == markerRGB ) {
int value = 0x00FFFFFF & rgb;
dst.setRGB(x, y, value);
}
}
}
return dst;
}
bim = makeWhiteTransparent(bim);
bim2 = makeWhiteTransparent(bim2);
Graphics2D graphics = (Graphics2D) bim.getGraphics();
graphics.drawImage(bim2,0,0, null);
g2.drawImage(bim, w/2-wc/2, h/2-hc/2, null);
I got the answer to my question finally. All I had to do was create a new BufferedImage and draw two images over it. Below is the code that works as expected:
BufferedImage newImage = ImageIO.read(new File("new.png"));
BufferedImage oldImage = ImageIO.read(new File("old.png"));
oldImage = makeWhiteTransparent(oldImage);
newImage = makeWhiteTransparent(newImage);
int width = Math.max(newImage.getWidth(), oldImage.getWidth());
int height = Math.max(newImage.getHeight(), oldImage.getHeight());
BufferedImage combined = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics graphics = combined.getGraphics();
graphics.drawImage(oldImage, 0, 0, null);
graphics.drawImage(newImage, 0, 0, null);
File outputImage = new File("merged.png");
ImageIO.write(combined, "PNG", outputImage);

Text to bitmap wrong color

We are building a native extension for air, to generate bitmap data from text.
The code below generates the bitmap of a smiley ant "test" those should bee yellow but the color is blue.
http://i.stack.imgur.com/wC1ZH.png
After a lot of searching and trying different example code we are stuck.
public static Bitmap drawText(String text, int textWidth, int textSize, String color) {
try {
text = URLDecoder.decode("%F0%9F%98%8D test", "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Get text dimensions
TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
textPaint.setColor(Color.parseColor("#ffe400"));
textPaint.setTextSize(textSize);
textPaint.setAntiAlias(true);
StaticLayout mTextLayout = new StaticLayout(text, textPaint, textWidth, Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
// Create bitmap and canvas to draw to
Bitmap b = Bitmap.createBitmap(textWidth, mTextLayout.getHeight(), Config.ARGB_8888);
Canvas c = new Canvas(b);
// Draw text
c.save();
c.translate(0, 0);
mTextLayout.draw(c);
c.restore();
Extension.log("Color " + Integer.toString(b.getPixel(15,10), 16));
return b;
}
When logging the returned pixels its already blue so we assume it goes wrong in this function.
It seems that the red and blue color channel are switched.
Fixed it by reversing the blue and red color chanel:
private static Bitmap reversColors(Bitmap b){
int width = b.getWidth();
int height = b.getHeight();
int[] pixels = new int[width * height];
b.getPixels(pixels, 0, width, 0, 0, width, height);
int[] finalArray = new int[width * height];
for(int i = 0; i < finalArray.length; i++) {
int red = Color.red(pixels[i]);
int green = Color.green(pixels[i]);
int blue = Color.blue(pixels[i]);
int alpha = Color.alpha(pixels[i]);
finalArray[i] = Color.argb(alpha, blue, green, red);
}
return Bitmap.createBitmap(finalArray, width, height, Bitmap.Config.ARGB_8888);
}
It is not the best way, but i can't find a better solution

Reshape a bufferedImage and store the double values in txt

I want to load an image to resize it to 100x100 to reshape it in 1x100000 and save it in an txt file. So I read it in bufferedImage, I resize it to 100x100. The next steps for reshaping it and save the double values of it is what I am looking for:
File img = new File(train_path + fileNames.get(i) + "/" + imageNames.get(i).get(j));
BufferedImage in = ImageIO.read(img);
BufferedImage newImage = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g = newImage.createGraphics();
g.drawImage(in, 0, 0, null);
g.dispose();
BufferedImage newImg = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
Graphics gr = newImg.createGraphics();
gr.drawImage(newImage, 0, 0, 100, 100, null);
gr.dispose();
System.out.println(newImage.getHeight()+ " "+ newImage.getWidth());
System.out.println(newImg.getHeight()+ " "+ newImg.getWidth());
You can get an array of int from the initial image:
int[] pixels = newImage.getRGB(0, 0, 100, 100, null, 0, 100);
which means get RGB values from (0,0) to (100,100) in a new array, starting from index 0, offsetting index for each line of 100.
Then for each int in pixels, the grayscale value is given by:
int gray = pixels[i] & 0xFF;

How do I flip an image horizontally flip with glReadPixels() Bufferedimage and out put with ImageIO?

How do I flip an Screenshot image? I can't find my problem anywhere else.Example code:
/*
*#param fileLoc //Location of fileoutput destination
*#param format //"png"
*#param WIDTH //Display.width();
*#param HEIGHT //Display.height();
*/
private void getScreenImage(){
int[] pixels = new int[WIDTH * HEIGHT];
int bindex;
// allocate space for RBG pixels
ByteBuffer fb = ByteBuffer.allocateDirect(WIDTH * HEIGHT * 3);//.order(ByteOrder.nativeOrder());
// grab a copy of the current frame contents as RGB
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, fb);
BufferedImage image = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
// convert RGB data in ByteBuffer to integer array
for (int i=0; i < pixels.length; i++) {
bindex = i * 3;
pixels[i] =
((fb.get(bindex) << 16)) +
((fb.get(bindex+1) << 8)) +
((fb.get(bindex+2) << 0));
}
try {
//Create a BufferedImage with the RGB pixels then save as PNG
image.setRGB(0, 0, WIDTH, HEIGHT, pixels, 0 , WIDTH);
ImageIO.write(image, format , fileLoc);
}
catch (Exception e) {
System.out.println("ScreenShot() exception: " +e);
}
}
Basically the code works for capturing the screen and storing at as "png" format.
But it output's the image horizontally flipped, because glReadPixels();,
read from bottom-left to top-right.
So how do I flip the image horizontally before I ImageIO.write();?
Thanks in-front,
Rose.
E.G. of flipping an image horizontally using an AffineTransform.
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Test001 {
public static BufferedImage getFlippedImage(BufferedImage bi) {
BufferedImage flipped = new BufferedImage(
bi.getWidth(),
bi.getHeight(),
bi.getType());
AffineTransform tran = AffineTransform.getTranslateInstance(bi.getWidth(), 0);
AffineTransform flip = AffineTransform.getScaleInstance(-1d, 1d);
tran.concatenate(flip);
Graphics2D g = flipped.createGraphics();
g.setTransform(tran);
g.drawImage(bi, 0, 0, null);
g.dispose();
return flipped;
}
Test001(BufferedImage bi) {
JPanel gui = new JPanel(new GridLayout(1,2,2,2));
gui.add(new JLabel(new ImageIcon(bi)));
gui.add(new JLabel(new ImageIcon(getFlippedImage(bi))));
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) throws AWTException {
final Robot robot = new Robot();
Runnable r = new Runnable() {
#Override
public void run() {
final BufferedImage bi = robot.createScreenCapture(
new Rectangle(0, 360, 200, 100));
new Test001(bi);
}
};
SwingUtilities.invokeLater(r);
}
}
It's worth noting that it might be faster to simply read the pixels out of the buffer in the order you want them, rather than read them backwards and do a costly transform operation. Additionally, since you know for sure that the BufferedImage is TYPE_INT_RGB it should be safe to write directly into its raster.
ByteBuffer fb = BufferUtils.createByteBuffer(WIDTH * HEIGHT * 3);
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, fb);
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
for (int i = pixels.length - 1; i >= 0; i--) {
int x = i % WIDTH, y = i / WIDTH * WIDTH;
pixels[y + WIDTH - 1 - x] = (fb.get() & 0xff) << 16 | (fb.get() & 0xff) << 8 | fb.get() & 0xff;
}

Categories