Saving two BufferedImages within a LayeredPane - java

I am working with a LayeredPane that contains two images, one on each layer. I have been working on a method that obtains the image positions (based on the label positions the images are in) and then save the bottom image (lower one from within the layeredPane) and also the top one if it is at all covering the bottom image (may only be a part of the image), however I have been having some trouble with this and I'm a bit unsure on how to get it working properly.
I have been stuck working on this for quite a while now so any help with my existing code or thoughts on how I should approach this another way would be a big help for me.
Thanks in advance.
public void saveImageLayering(BufferedImage topImg,BufferedImage bottomImg, JLabel topLabel, JLabel bottomLabel) {
int width = bottomImg.getWidth();
int height = bottomImg.getHeight();
Point bottomPoint = new Point();
Point topPoint = new Point();
bottomPoint = bottomLabel.getLocation();
topPoint = topLabel.getLocation();
System.out.println("image x coordinate " + bottomPoint.x);
System.out.println("image y coordinate " + bottomPoint.y);
//arrays to store the bottom image
int bottomRedImgArray[][] = new int[width][height];
int bottomGreenImgArray[][] = new int[width][height];
int bottomBlueImgArray[][] = new int[width][height];
//arrays to store the top image
int topRedImgArray[][] = new int[width][height];
int topGreenImgArray[][] = new int[width][height];
int topBlueImgArray[][] = new int[width][height];
//loop through the bottom image and get all pixels rgb values
for(int i = bottomPoint.x; i < width; i++){
for(int j = bottomPoint.y; j < height; j++){
//set pixel equal to the RGB value of the pixel being looked at
pixel = new Color(bottomImg.getRGB(i, j));
//contain the RGB values in the respective RGB arrays
bottomRedImgArray[i][j] = pixel.getRed();
bottomGreenImgArray[i][j] = pixel.getGreen();
bottomBlueImgArray[i][j] = pixel.getBlue();
}
}
//create new image the same size as old
BufferedImage newBottomImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//set values within the 2d array to the new image
for (int x1 = 0; x1 < width; x1++){
for (int y1 = 0; y1 < height; y1++){
//putting values back into buffered image
int newPixel = (int) bottomRedImgArray[x1][y1];
newPixel = (newPixel << 8) + (int) bottomGreenImgArray[x1][y1];
newPixel = (newPixel << 8) + (int) bottomBlueImgArray[x1][y1];
newBottomImage.setRGB(x1, y1, newPixel);
}
}
//create rectangle around bottom image to check if coordinates of top in inside and save only the ones that are
Rectangle rec = new Rectangle(bottomPoint.x, bottomPoint.y, bottomImg.getWidth(), bottomImg.getHeight());
//loop through the top image and get all pixels rgb values
for(int i = bottomPoint.x; i < bottomImg.getWidth(); i++){
for(int j = bottomPoint.y; j < bottomImg.getHeight(); j++){
//if top image is inside lower image then getRGB values
if (rec.contains(topPoint)) { //___________________________________________________________doesnt contain any..
if (firstPointFound == true) {
//set pixel equal to the RGB value of the pixel being looked at
pixel = new Color(topImg.getRGB(i, j));
//contain the RGB values in the respective RGB arrays
topRedImgArray[i][j] = pixel.getRed();
topGreenImgArray[i][j] = pixel.getGreen();
topBlueImgArray[i][j] = pixel.getBlue();
} else {
firstPoint = new Point(i, j);
firstPointFound = true;
}
}
}
}
//create new image the same size as old
BufferedImage newTopImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//set values within the 2d array to the new image
for (int x1 = 0; x1 < topImg.getWidth(); x1++){
for (int y1 = 0; y1 < topImg.getHeight(); y1++){
//putting values back into buffered image
int newPixel = (int) topRedImgArray[x1][y1];
newPixel = (newPixel << 8) + (int) topGreenImgArray[x1][y1];
newPixel = (newPixel << 8) + (int) topBlueImgArray[x1][y1];
newTopImage.setRGB(x1, y1, newPixel);
}
}
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//uses the Graphics.drawImage() to place them on top of each other
Graphics g = newImage.getGraphics();
g.drawImage(newBottomImage, bottomPoint.x, bottomPoint.y, null);
g.drawImage(newTopImage, firstPoint.x, firstPoint.y, null);
try {
//then save as image once all in correct order
File outputfile = new File("saved_Layered_Image.png");
ImageIO.write(newImage, "png", outputfile);
JOptionPane.showMessageDialog(null, "New image saved successfully");
} catch (IOException e) {
e.printStackTrace();
}
}

I'm not really sure why you're messing around with the pixels, however, the idea is relatively simple
Basically, you want to create a third "merged" image which is the same size as the bottomImage. From there, you simply want to paint the bottomImage onto the merged image at 0x0.
Then you need to calculate the distance that the topImage is away from bottomImage's location and paint it at that point.
BufferedImage merged = new BufferedImage(bottomImg.getWidth(), bottomImg.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = master.createGraphics();
g2d.drawImage(bottomImg, 0, 0, this);
int x = topPoint .x - bottomPoint .x;
int y = topPoint .y - bottomPoint .y;
g2d.drawImage(topImg, x, y, this);
g2d.dispose();
Using this basic idea, I was able to produce these...

Related

How can I create identicons using Java or Android?

I've seen many questions about this, but all of them are C#. None of them are Java, and I couldn't find a proper library for this.
What library can do this for me programmatically by giving it a string/hash? This algorithm is actually implemented on StackExchange.
You can look at this link. There is a code that you could use to generate your identicons http://www.davidhampgonsalves.com/Identicons
The code for Java is the following one:
public static BufferedImage generateIdenticons(String text, int image_width, int image_height){
int width = 5, height = 5;
byte[] hash = text.getBytes();
BufferedImage identicon = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
WritableRaster raster = identicon.getRaster();
int [] background = new int [] {255,255,255, 0};
int [] foreground = new int [] {hash[0] & 255, hash[1] & 255, hash[2] & 255, 255};
for(int x=0 ; x < width ; x++) {
//Enforce horizontal symmetry
int i = x < 3 ? x : 4 - x;
for(int y=0 ; y < height; y++) {
int [] pixelColor;
//toggle pixels based on bit being on/off
if((hash[i] >> y & 1) == 1)
pixelColor = foreground;
else
pixelColor = background;
raster.setPixel(x, y, pixelColor);
}
}
BufferedImage finalImage = new BufferedImage(image_width, image_height, BufferedImage.TYPE_INT_ARGB);
//Scale image to the size you want
AffineTransform at = new AffineTransform();
at.scale(image_width / width, image_height / height);
AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
finalImage = op.filter(identicon, finalImage);
return finalImage;
}
I solved the problem.
I used Gravatar. I first got the link of the image and stored it as a String like this:
String identiconURL = "http://www.gravatar.com/avatar/" + userID + "?s=55&d=identicon&r=PG";
Then, I used Glide:
Glide.with(ProfilePictureChooserActivity.this)
.load(identiconURL)
.centerCrop()
.into(imageView);

Getting the color of a pixel [duplicate]

Given an image file, say of PNG format, how to I get an array of int [r,g,b,a] representing the pixel located at row i, column j?
So far I am starting here:
private static int[][][] getPixels(BufferedImage image) {
final byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
int[][][] result = new int[height][width][4];
// SOLUTION GOES HERE....
}
Thanks in advance!
You need to get the packed pixel value as an int, you can then use Color(int, boolean) to build a color object from which you can extract the RGBA values, for example...
private static int[][][] getPixels(BufferedImage image) {
int[][][] result = new int[height][width][4];
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
Color c = new Color(image.getRGB(i, j), true);
result[y][x][0] = c.getRed();
result[y][x][1] = c.getGreen();
result[y][x][2] = c.getBlue();
result[y][x][3] = c.getAlpha();
}
}
}
It's not the most efficient method, but it is one of the simplest
BufferedImages have a method called getRGB(int x, int y) which returns an int where each byte is the components of the pixel (alpha, red, green and blue). If you dont want to do the bitwise operators yourself you can use Colors.getRed/Green/Blue methods by creating a new instance of Java.awt.Color with the int from getRGB.
You can do this in a loop to fill the three-dimensional array.
This is my code for this problem:
File f = new File(filePath);//image path with image name like "lena.jpg"
img = ImageIO.read(f);
if (img==null) //if img null return
return;
//3d array [x][y][a,r,g,b]
int [][][]pixel3DArray= new int[img.getWidth()][img.getHeight()][4];
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
int px = img.getRGB(x,y); //get pixel on x,y location
//get alpha;
pixel3DArray[x][y][0] =(px >> 24)& 0xff; //shift number and mask
//get red
pixel3DArray[x][y][1] =(px >> 16)& 0xff;
//get green
pixel3DArray[x][y][2] =(px >> 8)& 0xff;
//get blue
pixel3DArray[x][y][3] =(px >> 0)& 0xff;
}
}

Converting Colors

I'm trying to write a method for my game that will take an image, the hex value for the old color, and the hex value for the new color and then convert all pixels of the old color to the new color. Right now, the method paints the entire image the new color, as if the if statement is not working at all. This the method:
private void convertColors(BufferedImage img, int oldColor, int newColor)
{
Graphics g = img.getGraphics();
g.setColor(new Color(newColor));
Color old = new Color(oldColor);
for(int x = 0; x < img.getWidth(); x++)
{
for(int y = 0; y < img.getHeight(); y++)
{
Color tmp = new Color(img.getRGB(x, y));
if(tmp.equals(old));
{
System.out.println("Temp=" + tmp.toString() + "Old=" + old.toString() + "New=" + g.getColor().toString());
g.fillRect(x, y, 1, 1);
}
}
}
g.dispose();
}
*The hex for oldColor is 0xFFFFFF (white) and for newColor is 0xFF0000 (red).
Using the println method I get these kind of results:
Temp=java.awt.Color[r=0,g=0,b=0]Old=java.awt.Color[r=255,g=255,b=255]New=java.awt.Color[r=255,g=0,b=0]
Temp=java.awt.Color[r=255,g=255,b=255]Old=java.awt.Color[r=255,g=255,b=255]New=java.awt.Color[r=255,g=0,b=0]
The scond line looks correct, the temp color and the old are the same, but that is obviously not the case with the first. I have also tried creating a new BufferedImage and copy over the pixels but that leaves the same result... Does the equals method not work as I think it does or does this entire method just not work and there's a better way to do this? Thanks for you help in advance.
Just remove the ; after if(tmp.equals(old)).
Otherwise you compare the colors and do nothing after the comparsion and always choose the new color.
Besides that you need to reorganize your code a little bit to make it slightly more efficient:
Graphics g = img.getGraphics();
g.setColor(new Color(newColor));
for(int x = 0; x < img.getWidth(); x++) {
for(int y = 0; y < img.getHeight(); y++) {
if(img.getRGB(x, y) == oldColor) {//check if pixel color matches old color
g.fillRect(x, y, 1, 1);//fill the pixel with the right color
}
}
}
g.dispose();
Just because i was interested in the topic: relying on image filters you could do all that via:
class ColorSwapFilter extends RGBImageFilter {
int newColor, oldColor;
public ColorSwapFilter(int newColor, int oldColor) {
canFilterIndexColorModel = true;
this.newColor = newColor;
this.oldColor = oldColor;
}
#Override
public int filterRGB(int x, int y, int rgb) {
return rgb == oldColor ? newColor : oldColor;
}
}
which should be called via
BufferedImage img;//your image
ColorSwapFilter filter = new ColorSwapFilter(...,...);//your colors to be swapped.
ImageProducer producer = img.getSource();
producer = new FilteredImageSource(producer, filter);
Image im = Toolkit.getDefaultToolkit().createImage(producer);
You have a semicolon direct after your if statement if(tmp.equals(old));
This esentially tells Java that your if statement has only one command associated with it, and that command is a single semicolon, effectively meaning "do nothing". If you remove it, it will restore the condition on the block of code beneath it, which right now is just running every time regardless of the condition.
I got it to work; this is the working convertColors method:
private BufferedImage convertColors(BufferedImage img, int oldColor, int newColor)
{
int [] pixels = new int [img.getWidth() * img.getHeight()];
img.getRGB(0, 0, img.getWidth(), img.getHeight(), pixels, 0, img.getWidth());
Color old = new Color(oldColor);
Color newC = new Color(newColor);
for(int x = 0; x < img.getWidth(); x++)
{
for(int y = 0; y < img.getHeight(); y++)
{
Color tmp = new Color(pixels[x + y * img.getWidth()]);
if(tmp.equals(old))
{
pixels[x + y * img.getWidth()] = newC.getRGB();
}
}
}
img.setRGB(0, 0, img.getWidth(), img.getHeight(), pixels, 0, img.getWidth());
return newImg;
}

DCT2 of png using jTransforms

What I'm trying to do is to compute 2D DCT of an image in Java and then save the result back to file.
Read file:
coverImage = readImg(coverPath);
private BufferedImage readImg(String path) {
BufferedImage destination = null;
try {
destination = ImageIO.read(new File(path));
} catch (IOException e) {
e.printStackTrace();
}
return destination;
}
Convert to float array:
cover = convertToFloatArray(coverImage);
private float[] convertToFloatArray(BufferedImage source) {
securedImage = (WritableRaster) source.getData();
float[] floatArray = new float[source.getHeight() * source.getWidth()];
floatArray = securedImage.getPixels(0, 0, source.getWidth(), source.getHeight(), floatArray);
return floatArray;
}
Run the DCT:
runDCT(cover, coverImage.getHeight(), coverImage.getWidth());
private void runDCT(float[] floatArray, int rows, int cols) {
dct = new FloatDCT_2D(rows, cols);
dct.forward(floatArray, false);
securedImage.setPixels(0, 0, cols, rows, floatArray);
}
And then save it as image:
convertDctToImage(securedImage, coverImage.getHeight(), coverImage.getWidth());
private void convertDctToImage(WritableRaster secured, int rows, int cols) {
coverImage.setData(secured);
File file = new File(securedPath);
try {
ImageIO.write(coverImage, "png", file);
} catch (IOException ex) {
Logger.getLogger(DCT2D.class.getName()).log(Level.SEVERE, null, ex);
}
}
But what I get is: http://kyle.pl/up/2012/05/29/dct_stack.png
Can anyone tell me what I'm doing wrong? Or maybe I don't understand something here?
This is a piece of code, that works for me:
//reading image
BufferedImage image = javax.imageio.ImageIO.read(new File(filename));
//width * 2, because DoubleFFT_2D needs 2x more space - for Real and Imaginary parts of complex numbers
double[][] brightness = new double[img.getHeight()][img.getWidth() * 2];
//convert colored image to grayscale (brightness of each pixel)
for ( int y = 0; y < image.getHeight(); y++ ) {
raster.getDataElements( 0, y, image.getWidth(), 1, dataElements );
for ( int x = 0; x < image.getWidth(); x++ ) {
//notice x and y swapped - it's JTransforms format of arrays
brightness[y][x] = brightnessRGB(dataElements[x]);
}
}
//do FT (not FFT, because FFT is only* for images with width and height being 2**N)
//DoubleFFT_2D writes data to the same array - to brightness
new DoubleFFT_2D(img.getHeight(), img.getWidth()).realForwardFull(brightness);
//visualising frequency domain
BufferedImage fd = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
outRaster = fd.getRaster();
for ( int y = 0; y < img.getHeight(); y++ ) {
for ( int x = 0; x < img.getWidth(); x++ ) {
//we calculate complex number vector length (sqrt(Re**2 + Im**2)). But these lengths are to big to
//fit in 0 - 255 scale of colors. So I divide it on 223. Instead of "223", you may want to choose
//another factor, wich would make you frequency domain look best
int power = (int) (Math.sqrt(Math.pow(brightness[y][2 * x], 2) + Math.pow(brightness[y][2 * x + 1], 2)) / 223);
power = power > 255 ? 255 : power;
//draw a grayscale color on image "fd"
fd.setRGB(x, y, new Color(c, c, c).getRGB());
}
}
draw(fd);
Resulting image should look like big black space in the middle and white spots in all four corners. Usually people visualise FD so, that zero frequency appears in the center of the image. So, if you need classical FD (one, that looks like star for reallife images), you need to upgrade "fd.setRGB(x, y..." a bit:
int w2 = img.getWidth() / 2;
int h2 = img.getHeight() / 2;
int newX = x + w2 >= img.getWidth() ? x - w2 : x + w2;
int newY = y + h2 >= img.getHeight() ? y - h2 : y + h2;
fd.setRGB(newX, newY, new Color(power, power, power).getRGB());
brightnessRGB and draw methods for the lazy:
public static int brightnessRGB(int rgb) {
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
return (r+g+b)/3;
}
private static void draw(BufferedImage img) {
JLabel picLabel = new JLabel(new ImageIcon(img));
JPanel jPanelMain = new JPanel();
jPanelMain.add(picLabel);
JFrame jFrame = new JFrame();
jFrame.add(jPanelMain);
jFrame.pack();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
}
I know, I'm a bit late, but I just did all that for my program. So, let it be here for those, who'll get here from googling.

BufferedImage - Gray Scale

Given an image that is in grayscale, how would I get the pixel values of the grayscale at that location?
This outputs temp as -16777216 (black) all the time.
public void testMethod()
{
int width = imgMazeImage.getWidth();
int height = imgMazeImage.getHeight();
//Assign class variable as a new image with RGB formatting
imgMazeImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
for(int i=0; i < width; i ++){
for(int j=0; j < height; j++)
{
//Grab and set the colors one-by-one
inttemp = imgMazeImage.getRGB(j, i);
System.out.println(temp);
}
}
}
you are creating a new blank image and assigning it to your class variable:
imgMazeImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
the pixels are created with a default value and its logical that they all have the same color (black) at the stage when you are printing them since you did not manipulate the color in any pixel yet.
also, your code might fail if the width is not equal to the height. according to your for loops, i runs along width and j runs along height. therefore, you should change
int temp = imgMazeImage.getRGB(j, i);
to
int temp = imgMazeImage.getRGB(i, j);

Categories

Resources