Convert 2D array in Java to Image - java

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.

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

Converting Grayscale values from .csv to BufferedImage

I'm attempting to convert a .csv file containing grayscale values to an image using BufferedImage.
The csv is read into pixArray[] initially, in which all values are doubles.
I am attempting to use BufferedImage to create a 100x100px output image with the code
BufferedImage image = new BufferedImage(width,height,BufferedImage.
TYPE_BYTE_GRAY);
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
image.setRGB(x, y, (int)Math.round(pixArray[y]));
}
}
File file_out = new File("output.png");
try {
ImageIO.write(image, "png", file_out);
} catch (IOException e) {
e.printStackTrace();
}
but all I have as output is a 100x100 black square.
I've tried alternatives to TYPE_BYTE_GRAY with no success, as well as the png format for outout, and can't find what is producing this error.
It should be
int g = (int)Math.round(pixArray[y]);
image.setRGB(x,y,new Color(g,g,g).getRGB());
What your current code is doing is setting the alpha to the pixel value but leaving the color components all zero.
Posting an alternative solution. While Jim's answer is correct and works, it is also one of the slowest* ways to put sample values into a gray scale BufferedImage.
A BufferedImage with TYPE_BYTE_GRAY don't need all the conversion to and from RGB colors. To put the gray values directly into the image, do it through the image's raster:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
WritableRaster raster = image.getRaster();
for (int y = 0; y < height; y++) {
int value = (int) Math.round(pixArray[y])
for (int x = 0; x < width; x++) {
raster.setSample(x, y, 0, value);
}
}
*) Slow because of creating excessive throw-away Color instances, but mostly due to color space conversion to/from sRGB color space. Probably not very noticeable in a 100x100 image, but if you try 1000x1000 or larger, you will notice.
PS: I also re-arranged the loops to loop over x in the inner loop. This is normally faster, especially when reading values, due to data locality and caching in modern CPUs. In your case, it matters mostly because you only need to compute (round, cast) the value for each row.

Parsing Image in Java with different actions for different pixel colours

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

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.

grayscale bitmap into 2d array

Hi everyone i have problems in converting GrayScale bmp images into integer 2D-array (with values 0-255) in Java.
I have a pmb image that could be seen as an integer(0-255) 2D-array and i want to see that 2D-array in a Java data structure
i tried this way:
Image image = ImageIO.read(new File("my_img.bmp"));
BufferedImage img = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_BYTE_GRAY);
Graphics g = img.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
Then with my BufferedImage i create int[][] this way:
int w = img.getWidth();
int h = img.getHeight();
int[][] array = new int[w][h];
for (int j = 0; j < w; j++) {
for (int k = 0; k < h; k++) {
array[j][k] = img.getRGB(j, k);
}
}
But now all the 2D-array is full of number like "-9211021" or similar.
i think that the problem is in getRGB(j,k) but i don't know if it's possible to solve it.
edit:
i know RGB is not grayscale, so how can i get the grayscale value of a single pixel from a grayscale BufferedImage?
In a grayscale image, BufferedImage.getPixel(x,y) wont give values within the [0-255] range. Instead, it returns the corresponding value of a gray level(intensity) in the RGB colorspace. That's why you are getting values like "-9211021".
The following snippet should solve your problem :
Raster raster = image.getData();
for (int j = 0; j < w; j++) {
for (int k = 0; k < h; k++) {
array[j][k] = raster.getSample(j, k, 0);
}
}
where image is the created BufferedImage. The 0 in the getSample indicates that we are accessing the first byte/band(setting it to a greater value will throw a ArrayOutOfBoundException in grayscale images).
You can use Catalano Framework. Contains several filters for image processing.
http://code.google.com/p/catalano-framework/
Detail: That's it faster than using WritableRaster.
FastBitmap fb = new FastBitmap(bufferedImage);
int[][] image = new int[fb.getHeight()][fb.getWidth];
fb.toArrayGray(image);
//Do manipulations with image
//...
//Place the image into fastBitmap
fb.arrayToImage(image);
//Retrieve in bufferedImage if you desire.
bufferedImage = fb.toBufferedImage();

Categories