Parsing Image in Java with different actions for different pixel colours - java

I want to colour every black pixel in my image with the color the previous pixel had. And if there are 2 or more consecutive black pixels, the colour of the last non-black pixel is taken. I figured out how to iterate through pixels but the pixels won't change their colour. I think I miss the "save changes" line.
Here the code:
public static void iteratePixels() throws IOException {
File file = new File("C:\\blackDots.png");
BufferedImage image = ImageIO.read(file);
int lastNotBlack = -1;
int actualColour = 0;
for (int x = 0; x < image.getHeight(); x++) {
for (int y = 0; y < image.getWidth(); y++) {
int black = -16777216;
try {
actualColour = image.getRGB(x, y);
} catch (Exception e) {
continue;
}
if(image.getRGB(x, y)==black){
image.setRGB(x, y, lastNotBlack);
System.out.println("black pixel at: " +x +" "+y);
}
if (actualColour != black){
lastNotBlack= actualColour;
}
}
}
}
So how do I appy the changes ? Or is there another mistake?

You're changing the pixels only in the in-memory image, but you need to write those pixels back to a file:
ImageIO.write(image, "png", new File("C:\\blackDots_modified.png"));
(to be called after all pixels have been modified)
See also: https://docs.oracle.com/javase/tutorial/2d/images/saveimage.html

Related

Create image from double Array with color intensity

I've got a two dimensional double Array with color intensity values of an image, looking similar to this (my arrays size is 256x256 filled up with values as below):
790.0 739.0 690.0 601.0 582.0 630.0 730.0 773.0
982.0 879.0 754.0 695.0 687.0 631.0 630.0 666.0
1046.0 1080.0 1070.0 990.0 872.0 730.0 647.0 657.0
1008.0 998.0 962.0 959.0 944.0 930.0 921.0 932.0
Is it possible to create an Image Object out of this file?
My current code:
Double imageLayer[][] = vtkLayers.get(layer);
int xLenght = imageLayer.length;
int yLength = imageLayer[0].length;
System.out.println(xLenght);
System.out.println(yLength);
BufferedImage b = new BufferedImage(xLenght, yLength, 3);
for(int x = 0; x < xLenght; x++) {
for(int y = 0; y < yLength; y++) {
int rgb = (imageLayer[x][y]).intValue() << 16 | (imageLayer[x][y]).intValue() << 8 | (imageLayer[x][y]).intValue();
b.setRGB(x, y, rgb);
}
}
try {
File outputfile = new File("C:\\temp\\image.png");
ImageIO.write(b, "png", outputfile);
}
catch (IOException e){
System.out.println("Could not create picture");
}
To test it I tried to create a png file. But this code currently only produces a blank png File.
As I'm new to Java I've used this post as guide.
It would be the best, if I can create an Image object directly, without creating a png first.
I could solve the problem by myself:
Double imageLayer[][] = vtkLayers.get(layer);
// Initialize BufferedImage, assuming Color[][] is already properly populated.
BufferedImage bufferedImage = new BufferedImage(imageLayer.length, imageLayer[0].length,
BufferedImage.TYPE_INT_RGB);
// Set each pixel of the BufferedImage to the color from the Color[][].
for (int x = 0; x < imageLayer.length; x++) {
for (int y = 0; y < imageLayer[x].length; y++) {
Color test = doubleToColor(imageLayer[x][y], 4080);
bufferedImage.setRGB(x, y, test.getRGB());
}
}
try {
File imageFile = new File(path);
ImageIO.write(bufferedImage, "png", imageFile);
}
catch (Exception e){
System.out.println("Failed to create image");
}
The function doubleToColor converts my doubles to an RGB code:
public static Color doubleToColor(double x,double maxx){
float cR=(float)(0.5 + (x / (2 * maxx)));
float cG=(float)(0.5 + (x / (2 * maxx)));
float cB=(float)(0.5 - (x / (2 * maxx)));
Color c = new Color(cR,cG,cB);
return c;
}

What order does PixelGrabber put pixels into the array in java?

What order does PixelGrabber put pixels into the array in java? Does it take the pixels along the width of the image first? Or along the height of the image first?
public static int[] convertImgToPixels(Image img, int width, int height) {
int[] pixel = new int[width * height];
PixelGrabber pixels = new PixelGrabber(img, 0, 0, width, height, pixel, 0, width);
try {
pixels.grabPixels();
} catch (InterruptedException e) {
throw new IllegalStateException("Interrupted Waiting for Pixels");
}
if ((pixels.getStatus() & ImageObserver.ABORT) != 0) {
throw new IllegalStateException("Image Fetch Aborted");
}
return pixel;
}
In the code example provided by the documentation
It has the following for loops:
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
handlesinglepixel(x+i, y+j, pixels[j * w + i]);
}
}
The access pixels[j * w + i] shows that it goes first along the row, then by along the columns. It grabs the pixels along the width first.
I'm pretty sure it uses row major order, but the easiest way is to actually grab the pixels, set a sequence of them to a particular color (for easy identification) and then save them out to an image. If the pixel strip appears vertical than the order is column major, otherwise it is row major. You can use code like: here
public static Image getImageFromArray(int[] pixels, int width, int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
WritableRaster raster = (WritableRaster) image.getData();
raster.setPixels(0,0,width,height,pixels);
return image;
}
To convert an the int[] to an image.
Also, I use ((DataBufferInt)img.grtRaster().getDataBuffer()).getData() to quickly grab the pixels of the image. Any modifications to that int[] will reflect in the image and vice versa. And that is row major for sure.

java buffered image color op with different values for RGB

I have a buffered image that is drawn in grayscale, and I would like to convert it to color, where the colors map to some ranges in the gray. For example, all grays between 0-100 map to red, 100-255 map to green. It looks like the buffered image lookup ops are the way to do this, but I'm not entirely sure how to do this. For example, if the RGB of the grayscale image is (50,50,50), I want to convert that pixel to (255,0,0), not (255,255,255). Is the lookup op the right way to go with this?
if the RGB of the grayscale image is (50,50,50), I want to convert that pixel to (255,0,0)
Try this one
try {
BufferedImage image = ImageIO.read(new File("resources/Tulips.jpg"));
BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
int newColorRGB = new Color(255, 0, 0).getRGB();
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
Color color = new Color(image.getRGB(x, y));
int red = color.getRed();
int blue = color.getBlue();
int green = color.getGreen();
if (red == 50 && blue == 50 && green == 50) {
newImage.setRGB(x, y, newColorRGB);
} else {
newImage.setRGB(x, y, color.getRGB());
}
}
}
ImageIO.write(newImage, "png", new File("resources/Tulips1.png"));
} catch (IOException e) {
e.printStackTrace();
System.out.println("Sorry, I cannot find that file.");
}
Note: change the image type as per your requirement.

Convert 2D array in Java to Image

I need to convert a 2D array of pixel intensity data of a grayscale image back to an image. I tried this:
BufferedImage img = new BufferedImage(
regen.length, regen[0].length, BufferedImage.TYPE_BYTE_GRAY);
for(int x = 0; x < regen.length; x++){
for(int y = 0; y<regen[x].length; y++){
img.setRGB(x, y, (int)Math.round(regen[x][y]));
}
}
File imageFile = new File("D:\\img\\conv.bmp");
ImageIO.write(img, "bmp", imageFile);
where "regen" is a 2D double array. I am getting an output which is similar but not exact. There are few pixels that are totally opposite to what it must be (I get black color for a pixel which has a value of 255). Few gray shades are also taken as white. Can you tell me what is the mistake that I am doing?
Try some code like this:
public void writeImage(int Name) {
String path = "res/world/PNGLevel_" + Name + ".png";
BufferedImage image = new BufferedImage(color.length, color[0].length, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < 200; x++) {
for (int y = 0; y < 200; y++) {
image.setRGB(x, y, color[x][y]);
}
}
File ImageFile = new File(path);
try {
ImageIO.write(image, "png", ImageFile);
} catch (IOException e) {
e.printStackTrace();
}
}
BufferedImage.TYPE_BYTE_GRAY is unsigned and non-indexed. Moreover,
When data with non-opaque alpha is stored in an image of this type, the color data must be adjusted to a non-premultiplied form and the alpha discarded, as described in the AlphaComposite documentation.
At a minimum you need to preclude sign extension and mask off all but the lowest eight bits of the third parameter to setRGB(). Sample data that reproduces the problem would be dispositive.

Taking a picture as input, Make grey scale and & then outputting

I'm attempting to take a picture as input, then manipulate said picture (I specifically want to make it greyscale) and then output the new image. This is a snippet of the code that I'm editing in order to do so but I'm getting stuck. Any ideas of what I can change/do next. Greatly appreciated!
public boolean recieveFrame (Image frame) {
int width = frame.width();
int height = frame.height();
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
Color c1 = frame.get(i, j);
double greyScale = (double) ((Color.red *.3) + (Color.green *.59) + (Color.blue * .11));
Color newGrey = Color.greyScale(greyScale);
frame.set(i, j, newGrey);
}
}
boolean shouldStop = displayImage(frame);
return shouldStop;
}
I'm going to try to stick as close as possible to what you already have. So, I'll assume that you are looking for how to do pixel-level processing on an Image, rather than just looking for a technique that happens to work for converting to greyscale.
The first step is that you need the image to be a BufferedImage. This is what you get by default from ImageIO, but if you have some other type of image, you can create a BufferedImage and paint the other image into it first:
BufferedImage buffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffer.createGraphics();
g.drawImage(image, 0, 0);
g.dispose()
Then, you can operate on the pixels like this:
public void makeGrey(BufferedImage image) {
for(int x = 0; x < image.getWidth(); ++x) {
for(int y = 0; y < image.getHeight(); ++y) {
Color c1 = new Color(image.getRGB(x, y));
int grey = (int)(c1.getRed() * 0.3
+ c1.getGreen() * 0.59
+ c1.getBlue() * .11
+ .5);
Color newGrey = new Color(grey, grey, grey);
image.setRGB(x, y, newGrey.getRGB());
}
}
}
Note that this code is horribly slow. A much faster option is to extract all the pixels from the BufferedImage into an int[], operate on that, and then set it back into the image. This uses the other versions of the setRGB()/getRGB() methods that you'll find in the javadoc.

Categories