Create image from 2D Color Array - java

I have an array called image[][] and i want to create a BufferedImage out of this so I can have the player store it in a file.

// Initialize Color[][] however you were already doing so.
Color[][] image;
// Initialize BufferedImage, assuming Color[][] is already properly populated.
BufferedImage bufferedImage = new BufferedImage(image.length, image[0].length,
BufferedImage.TYPE_INT_RGB);
// Set each pixel of the BufferedImage to the color from the Color[][].
for (int x = 0; x < image.length; x++) {
for (int y = 0; y < image[x].length; y++) {
bufferedImage.setRGB(x, y, image[x][y].getRGB());
}
}
This is a straightforward way of creating (and potentially storing) an image, if that's what you're trying to get at. However, this is not efficient by any means. Try it with a larger image and you'll see a noticeable speed difference.

Related

How can I add a border to an image in Java?

The border needs to be made out of the closest pixel of the given image, I saw some code online and came up with the following. What am I doing wrong? I'm new to java, and I am not allowed to use any methods.
/**
* TODO Method to be done. It contains some code that has to be changed
*
* #param enlargeFactorPercentage the border in percentage
* #param dimAvg the radius in pixels to get the average colour
* of each pixel for the border
*
* #return a new image extended with borders
*/
public static BufferedImage addBorders(BufferedImage image, int enlargeFactorPercentage, int dimAvg) {
// TODO method to be done
int height = image.getHeight();
int width = image.getWidth();
System.out.println("Image height = " + height);
System.out.println("Image width = " + width);
// create new image
BufferedImage bi = new BufferedImage(width, height, image.getType());
// copy image
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixelRGB = image.getRGB(x, y);
bi.setRGB(x, y, pixelRGB);
}
}
// draw top and bottom borders
// draw left and right borders
// draw corners
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixelRGB = image.getRGB(x, y);
for (enlargeFactorPercentage = 0; enlargeFactorPercentage < 10; enlargeFactorPercentage++){
bi.setRGB(width, enlargeFactorPercentage, pixelRGB * dimAvg);
bi.setRGB(enlargeFactorPercentage, height, pixelRGB * dimAvg);
}
}
}
return bi;
I am not allowed to use any methods.
What does that mean? How can you write code if you can't use methods from the API?
int enlargeFactorPercentage
What is that for? To me, enlarge means to make bigger. So if you have a factor of 10 and your image is (100, 100), then the new image would be (110, 110), which means the border would be 5 pixels?
Your code is creating the BufferedImage the same size as the original image. So does that mean you make the border 5 pixels and chop off 5 pixels from the original image?
Without proper requirements we can't help.
#return a new image extended with borders
Since you also have a comment that says "extended", I'm going to assume your requirement is to return the larger image.
So the solution I would use is to:
create the BufferedImage at the increased size
get the Graphics2D object from the BufferImage
fill the entire BufferedImage with the color you want for the border using the Graphics2D.fillRect(….) method
paint the original image onto the enlarged BufferedImage using the Graphics2D.drawImage(…) method.
Hello and welcome to stackoverflow!
Not sure what you mean with "not allowed using methods". Without methods you can not even run a program because the "thing" with public static void main(String[] args) is a method (the main method) and you need it, because it is the program starting point...
But to answer your question:
You have to load your image. A possibility would be to use ImageIO. Then you create a 2D graphics object and then you can to drawRectangle() to create a border rectangle:
BufferedImage bi = //load image
Graphics2D g = bi.getGraphics();
g.drawRectangle(0, 0, bi.getHeight(), bi.getWidth());
This short code is just a hint. Try it out and read the documentation from Bufferedimage see here and from Graphics2D
Edit: Please notice that this is not quite correct. With the code above you overdraw the outer pixel-line from the image. If you don't want to cut any pixel of, then you have to scale it up and draw with bi.getHeight()+2 and bi.getWidth()+2. +2 because you need one pixel more at each side of the image.

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.

Converting a double scripted array of grayscale int values to a BufferedImage

So after hours of searching I am ready to pull my hair out on this one.
I am doing some research in Computer Vision and am working with grayscale images. I need to end up with an "image" (a double scripted double array) of Sobel filtered double values. My Sobel converter is set up to take in a double scripted int array (int[][]) and go from there.
I am reading in a buffered image and I gather the grayscale int values via a method that I am 99% sure works perfectly (I can present it if need be).
Next I am attempting to convert this matrix of int values to a BufferedImage by the below method:
private BufferedImage getBIFromIntArr(int[][] matrix){
BufferedImage img = new BufferedImage(matrix.length * 4, matrix[0].length, BufferedImage.TYPE_INT_ARGB);
- Gather the pixels in the form of [alpha, r, g, b]
- multiply the size of the array by 4 for the model
int[] pixels = new int[(matrix.length * 4 * matrix[0].length)];
int index = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
int pixel = matrix[i][j];
pixels[index] = pixel;
index++;
for (int k = 0; k < 3; k++) {
pixels[index] = 0;
index++;
}
}
}
-get the raster
WritableRaster raster = img.getRaster();
-output the amount of pixels and a sample of the array
System.out.println(pixels.length);
for (int i = 0; i < pixels.length; i++) {
System.out.print(pixels[i] + " ");
}
- set the pixels of the raster
raster.setPixels(0, 0, matrix.length, matrix[0].length, pixels);
- paint the image via an external routing to check works (does not)
p.panel.setNewImage(img);
return img;
}
Here is my understanding. The ARGB Type consists of 4 values Alpha, Red, Green, and Blue. I am guessing that setting the alpha values in the new BufferedImage to the greyscale image int values (the matrix values passed in) then this will reproduce the image. Please correct me if I am wrong. So as you can see I create an array of pixels that stores the int values like this: [intValue, 0, 0, 0] repeatedly to try to stay with the 4 value model.
Then I create a writable raster and set the gathered pixels in it using the gathered pixels. The only thing is that I get nothing in the BufferedImage. No error with the code below and Im sure my indeces are correct.
What am I doing wrong? Im sure it is obvious but any help is appreciated because I cant see it. Perhaps my assumption about the model is wrong?
Thanks,
Chronic

Avoiding loops while accessing pixel information of an image

I'm trying to copy the RGB values of an image to a 2D array. At the moment I'm using two nested for loops. My question is, is it possible to use arraycopy or any other method to make the operation faster?
The below code works fine, I just would like to optimize it.
private LSHColor[][] pixels = new LSHColor[w][h];
public LSHImage(BufferedImage img) {
pixels = new LSHColor[img.getWidth()][img.getHeight()];
for (int y = 0; y < img.getHeight(); y++)
for (int x = 0; x < img.getWidth(); x++)
pixels[x][y] = LSHColor.fromRGB(img.getRGB(x, y));
}
arraycopy is not going to help for two reasons. First reason is that you are not making a copy: you are creating an array based on the content of another array. On top of that, your pixels[][] is in column-major order, meaning that pixels of the same column are next to each other in memory, while images are stored in row-major order.
One thing that you can optimize is getting your pixels from the image. Rather than reading them one at a time, you can get them all at once, and then use your loops for processing, like this:
public LSHImage(BufferedImage img) {
int w = img.getWidth();
int h = img.getHeight();
pixels = new LSHColor[w][h];
int[] raw = img.getRGB(0, 0, w, h, null, 0, w);
for (int y = 0; y < img.getHeight(); y++)
for (int x = 0; x < img.getWidth(); x++)
pixels[x][y] = LSHColor.fromRGB(raw[w*y+x]);
}
This makes a single call to getRGB instead of making Width*Height calls. Tradeoff here is that you use some temporary memory for the image, which may be prohibitive for larger images.

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