How to convert an image to buffered image using java default libraries - java

I am working on a project that involves pattern detection. I have to scale the input images to a specific size and test for pixel colour.
I tried to take in a java.awt.Image so I could resize it, then convert it to BufferedImage to test for the RGB value for each independent pixel.
However, casting BufferedImage to Image does not work.
Since java.awt.Image cannot access the color value of each individual pixel, I have to use the .getRBG functions of a BufferedImage. However, I have to take in a java.awt.Image because BufferedImage cannot be resized. I did some research about resizing the BufferedImage but all the result I found is about resizing it on screen, but not the actual image. I am NOT trying to display the BufferedImage on screen, I am trying to access the colour value of each pixel on an image.
These are the ways that could fix my issue:
Please suggest a way to...
Scale a BufferedImage (that doesn't involve drawing on the screen, just resizing the BufferedImage itself)
or
Access the colour value of a pixel in java.awt.Image
Image img = ImageIO.read(inputFile).getScaledInstance(400, 400, 0);
BufferedImage scaledImage = (BufferedImage)img;
The following code does not compile because BufferedImage cannot be cast to java.awt.Image

String imagePath = "path/to/your/image.jpg";
BufferedImage myPicture = ImageIO.read(new File(imagePath));
You can use ImageIO, check this documentation: Converting Image to BufferedImage
Or this amazing tutorial: https://www.baeldung.com/java-images
Or even this same question in 2012: Converting Image to BufferedImage
If I answer wrong your question, let me know.
For resize your image, you can try use something like that:
public static BufferedImage resize(BufferedImage img, int newW, int newH) {
Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = dimg.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
return dimg;
}
this answer come from: Bufferedimage resize

Related

How to remove black background after resizing BufferedImages java

I wrote a method to resize BufferedImages for me but after doing so .png images end up losing their transparency and instead they get a black background.
public BufferedImage getSizedImg(BufferedImage otherImage,int width,int height){
BufferedImage outputImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = outputImg.createGraphics();
g.drawImage(otherImage, 0, 0, width, height, null);
g.dispose();
return outputImg;
}
How can I fix the method so that the images keep their transparency?
Simple. When you create your new re-sized BufferedImage here:
BufferedImage outputImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
don't use BufferedImage.TYPE_INT_RGB but rather BufferedImage.TYPE_INT_ARGB. The "A" stands for "alpha" and this gives you the transparency. For more on this, please see the BufferedImage API.

Retrieving pixel data from Java Image

Recently I have been attempting to scale pixel arrays (int[]) in Java. I used .setRGB() to add all my pixel data into the BufferedImage. BufferedImage then offers a function called .getScaledInstance(). This should work great for my purposes, but I ran into a problem. .getScaledInstance() returns a Image, not a BufferedImage. With an Image object, I cannot use .getRGB() to add all the pixel data (in int[] form) from the scaled Image back into an array. Is there a way to get raw pixel data from an Image file? Am I missing something? I looked at other questions and did a bit of googling, and they only seemed to be wanting to get picture data in a different form of array (int[][]) or in bytes. Any help would be appreciated, thanks. Also, Sprite is a class I made that is being used. Here is my code:
public Sprite scaleSprite(Sprite s, int newWidth, int newHeight){
BufferedImage image = new BufferedImage(s.getWidth(), s.getHeight(), BufferedImage.TYPE_INT_RGB);
for(int y = 0; y < s.getHeight(); y++){
for(int x = 0; x < s.getWidth(); x++){
image.setRGB(x, y, s.getPixel(x, y));
}
}
Image newImage = image.getScaledInstance(newWidth, newHeight, Image.SCALE_AREA_AVERAGING);
Sprite newS = new Sprite(newWidth, newHeight);
int[] pixels = new int[newWidth * newHeight];
newImage.getRGB(0, 0, newWidth, newHeight, pixels, 0, newWidth); //This is where I am running into problems. newImage is an Image and I cannot retrieve the raw pixel data from it.
newS.setPixels(pixels);
return newS;
}
You can draw the resulting Image onto a BufferedImage like this:
Image newImage = image.getScaledInstance(newWidth, newHeight, Image.SCALE_AREA_AVERAGING);
BufferedImage buffImg = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2 = (Graphics2D) buffImg.getGraphics();
g2.drawImage(newImage, 0, 0, 10, 10, null);
g2.dispose();
Or you can scale the image directly by drawing it on another BufferedImage:
BufferedImage scaled = new BufferedImage(newWidth, newWidth, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2 = (Graphics2D) scaled.getGraphics();
g2.drawImage(originalImage, 0, 0, newWidth, newWidth, 0, 0, originalImage.getWidth(), originalImage.getHeight(), null);
g2.dispose();
The second approach will work correctly if the two BufferedImages have the same aspect ratio.
To be clear, getScaledInstance() is a method of Image, not BufferedImage. You don't generally want to revert to working directly with the Image superclass once you're working with BufferedImage; Image is really not easy to work with.
Please see if this will help: How to scale a BufferedImage
Or from Scaling a BufferedImage, where they yield the following example:
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
public class Main {
public static void main(String[] argv) throws Exception {
BufferedImage bufferedImage = new BufferedImage(200, 200,
BufferedImage.TYPE_BYTE_INDEXED);
AffineTransform tx = new AffineTransform();
tx.scale(1, 2);
AffineTransformOp op = new AffineTransformOp(tx,
AffineTransformOp.TYPE_BILINEAR);
bufferedImage = op.filter(bufferedImage, null);
}
This will give you the ability to scale entirely at the level of BufferedImage. From there you can apply whatever sprite specific or array data algorithm you wish.

How to resize image to maximize their dimensions into a panel without changing aspect ratio

I want to draw some images into a panel, I need that the images conserves their aspect ratio with the biggest dimensions to be drawn over a panel. So given the panel dimensions I must create a Java code to maximize that dimensions. The only ideas that I had needed to solve some linear programming, and I don't know how to do it in Java.
Which should be the easiest way to do what I need?
Here is the method to get a re-sized BufferedImage.
private BufferedImage resizeImage(BufferedImage originalImage, int width, int height)
throws IOException {
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
You can use Darryl's Stretch Icon. It will dynamically resize the Icon to fill the space available to the label.

Performing setRGB on BufferedImage changes pixel to black instead of color

** Important update, see below! **
I am creating a program that changes the pixels of a BufferedImage to a certain color when that pixel fulfills a set of conditions in Java. However, when I write the image to disk, the pixels that should be colored are instead black.
First I define the color, using RGB codes:
Color purple = new Color(82, 0, 99);
int PURPLE = purple.getRGB();
Then I read the image I want to alter from a File into a BufferedImage called "blank":
BufferedImage blank = ImageIO.read(new File("some path"));
Now, loop through the pixels, and when a pixel at location (x, y) matches a criteria, change its color to purple:
blank.setRGB(x, y, PURPLE);
Now, write "blank" to the disk.
File output = new File("some other path");
ImageIO.write(blankIn, "png", output); // try-catch blocks intentionally left out
The resulting file should be "blank" with some purple pixels, but the pixels in question are instead black. I know for a fact that the issue is with setRGB and NOT any import or export functions, because "blank" itself is a color image, and gets written to file as such. I read around and saw a lot of posts recommending that I use Graphics2D and to avoid setRGB, but with no discussion of pixel-by-pixel color changing.
I also tried direct bit manipulation, like this:
blank.setRGB(x, y, ((82 << 16) + (0 << 8) + 99));
I'm probably doing that wrong, but if I put it in correctly it wouldn't matter, because the pixels are getting set to transparent when I do this (regardless of what the numbers say, which is very strange, to say the least).
** When I try this:
blank.setRGB(x, y, Color.RED.getRGB());
My output file is grayscale, so that means setRGB is, in fact, modifying my picture in grayscale. I think this is actually a rather simple issue, but the solution eludes me.
Based on the insights in https://stackoverflow.com/a/21981173 that you found yourself ... (a few minutes after posting the question) ... it seems that it should be sufficient to simply convert the image into ARGB directly after it was loaded:
public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
The original image that was imported into Java was actually grayscale, so when Java read it into the BufferedImage, it simply imported it as a grayscale BufferedImage. By adding a very small but imperceptible colored dot in the corner of my image, I was able to get Java to output a correctly colored image.
Unfortunately, this is only a half solution, because I do not know how to fix this programmatically.
SOLUTION:
Convert the BufferedImage from grayscale to ARGB with this snippet:
BufferedImage blank2 = blank;
// Create temporary copy of blank
blank = new BufferedImage(blank.getWidth(), blank.getHeight(), BufferedImage.TYPE_INT_ARGB);
// Recreate blank as an ARGB BufferedImage
ColorConvertOp convert = new ColorConvertOp(null);
// Now create a ColorConvertOp object
convert.filter(blank2, blank);
// Convert blank2 to the blank color scheme and hold it in blank
You want to add this right after blank = ImageIO.read(new File("some path")).

Creating and rendering an image dynamically with transparent background for use with drawImage

Could someone provide an example of how to dynamically create an image in Java, draw lines et cetera on it, and then draw the image so that areas not painted will remain transparent in the drawing process?
One could use a BufferedImage with an image type that supports transparency such as BufferedImage.TYPE_INT_ARGB:
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
One can draw on the BufferedImage by calling BufferedImage.createGraphics to obtain a Graphics2D object, then perform some drawing:
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = img.createGraphics();
g.drawLine(0, 0, 10, 10); // draw a line.
g.dispose();
Then, since BufferedImage is a subclass of Image that can be used to draw onto another Image using one of the Graphics.drawImage that accepts an Image.

Categories