Creating image from float array, index out of bounds - java

Why would this method throw an index out of bounds error? Trying to create an image from data I generate myself and I expected this would work.
private BufferedImage getImageFromFloatArray(float[] data, int w, int h) {
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
System.out.println("Image pixel array size: "
+ ((DataBufferInt) img.getRaster().getDataBuffer())
.getData().length);
System.out.println("Datasize: " + data.length);
WritableRaster raster = img.getRaster();
raster.setPixels(0, 0, w, h, data);
return img;
}
Stacktrace
Image pixel array size: 800000
Datasize: 800000
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 800000
at java.awt.image.SampleModel.setPixels(Unknown Source)
at java.awt.image.WritableRaster.setPixels(Unknown Source)
at image.PixelAraryToImageTest.getImageFromFloatArray(PixelAraryToImageTest.java:36)

Try using the Raster width and height variables instead of the BufferedImage width and height variable. Also use Raster.getMinX() and Raster.getMinY()
Every value in the float array isn't a pixel value. Every value is a color component value. So a 2x1 image would actually need to be of length 4, as you have ARGB color components. To make it a 2x1 image red for example, would require something like...
int numColorComponents = 4;
float[] data = new float[imgWidth*imgHeight*numColorComponents];
raster.setPixels(minX,minY, rasterWidth,rasterHeight, data);
Also, unlike other graphics frameworks, the float buffer here isn't a buffer of normalized values. Its value between [0, 255]. So, to set 2x1 image to opaque red, your buffer would be:
float alpha = 255;
float red = 255;
float[] buffer = new float[]{alpha,red,0,0,alpha,red,0,0};

Related

Error while filling color on a buffered image

I am trying to fill a buffered image rectangle with color Red
and i am getting arrayindexoutofboundexception.
could not understand why
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] pixels = {255,0,0};
bufferedImage.setRGB(0,0,width, height, pixels, 0 , width);
i'm not the expert, but it has something to do with the amount of pixels in your array and the scansize... this code below works. if you are changing the array size from 100 to 99 with a scansize of 0, you're running in the out of bounds exception. if you set the scansize to 100, then you need 10000pixels in your array with a 100x100 image.
import java.awt.image.BufferedImage;
public class Test {
public static void main(String[] args){
BufferedImage bufferedImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
int[] pixels = new int[100];
for ( int i = 0 ; i < 100; i++){
pixels[i] = 255;
}
bufferedImage.setRGB(0,0,100, 100, pixels , 0, 0);
}
}
Because inside method setRGB() one of step is to take the value of your int [] pixels.
If you try to set width=2 and height=1 than everything will work.
But if higher then your array will not have a value at this index and there will be an exception arrayindexoutofboundexception.

Create image from black and white 1D-array pixels

How can I create a black and white image using array of BLACK and WHITE pixels ?
int pixels[]= {-1, -16777216,-16777216,-16777216....}
Color w = new Color(Color.WHITE.getRGB());
int wi = w.getRGB();
Color b = new Color(Color.BLACK.getRGB());
int bi = b.getRGB();
I was trying to use this code but the result was only few black pixels.
public static BufferedImage getImageFromArray(int[] pixels, int width, int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
WritableRaster raster = (WritableRaster) image.getData();
raster.setDataElements(0, 0, width, height, pixels);
return image;
}
Not sure what exactly you are tying to create, but here are some nice examples:
http://www.lac.inpe.br/JIPCookbook/1100-create-bw.jsp

Java create BufferedImage with float precision

I created a map editor in Java. The problem is, I have steps for every byte value, so the map isn't smooth. Is it possible to change the BufferedImage raster data to float data and draw in float precision on it?
To answer your question, yes, you can create a BufferedImage with float precision. It is however a little unclear if this will help you solve your problem.
In any case, here's working example code for creating a BufferedImage with float precision:
public class FloatImage {
public static void main(String[] args) {
// Define dimensions and layout of the image
int w = 300;
int h = 200;
int bands = 4; // 4 bands for ARGB, 3 for RGB etc
int[] bandOffsets = {0, 1, 2, 3}; // length == bands, 0 == R, 1 == G, 2 == B and 3 == A
// Create a TYPE_FLOAT sample model (specifying how the pixels are stored)
SampleModel sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_FLOAT, w, h, bands, w * bands, bandOffsets);
// ...and data buffer (where the pixels are stored)
DataBuffer buffer = new DataBufferFloat(w * h * bands);
// Wrap it in a writable raster
WritableRaster raster = Raster.createWritableRaster(sampleModel, buffer, null);
// Create a color model compatible with this sample model/raster (TYPE_FLOAT)
// Note that the number of bands must equal the number of color components in the
// color space (3 for RGB) + 1 extra band if the color model contains alpha
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorModel colorModel = new ComponentColorModel(colorSpace, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_FLOAT);
// And finally create an image with this raster
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
System.out.println("image = " + image);
}
}
For map elevation data, using a single band (bands = 1; bandOffsets = {0};) and a grayscale color space (ColorSpace.CS_GRAY) and no transparency may make more sense.

Create a WritableRaster based on int array

I need to take an int array and turn it into BufferImage. I really don't have any background on this subject and I learn it all from the internet so here's what I'm trying to do:
Create an array from BufferedImage(done), turn this array into IntBuffer(done) - (Later i'll need to do some opertions on the image through the IntBuffer), put the changed values from the IntBuffer in new array(done), and turn this array into WritableRaster.
(If something isn't right in my understading of the process please tell me)
Here's the line where I deal with the WritableRaster:
WritableRaster newRaster= newRaster.setPixels(0, 0, width, height, matrix);
Eclipse marks this as a mistake and says ''Type mismatch:Cannot convert from void to WritableRaster"
Please help! I'm a bit lost.
Also sorry for bad english.
EDIT:
The matrix:
int height=img.getHeight();
int width=img.getWidth();
int[]matrix=new int[width*height];
The part of the code where I try to insert values to the Raster:
BufferedImage finalImg = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
WritableRaster newRaster= (WritableRaster)finalImg.getData();
newRaster.setPixels(0, 0, width, height, matrix);
The error message:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10769
at java.awt.image.SinglePixelPackedSampleModel.setPixels(Unknown Source)
at java.awt.image.WritableRaster.setPixels(Unknown Source)
You can create a WritableRaster and/or BufferedImage from an int array like this:
int w = 300;
int h = 200;
int[] matrix = new int[w * h];
// ...manipulate the matrix...
DataBufferInt buffer = new DataBufferInt(matrix, matrix.length);
int[] bandMasks = {0xFF0000, 0xFF00, 0xFF, 0xFF000000}; // ARGB (yes, ARGB, as the masks are R, G, B, A always) order
WritableRaster raster = Raster.createPackedRaster(buffer, w, h, w, bandMasks, null);
System.out.println("raster: " + raster);
ColorModel cm = ColorModel.getRGBdefault();
BufferedImage image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
System.err.println("image: " + image);
ColorModel cm = ColorModel.getRGBdefault();
int w = 300;
int h = 200;
WritableRaster raster = cm.createCompatibleWritableRaster(w, h);
DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer();
int[] bufferData = buffer.getData();
int[] array = new int[2400];
Random random = new Random();
for (int i = 0; i < 2400; i++) {
array[i] = random.nextInt(2);
}
System.arraycopy(array, 0, bufferData, 0, (array.length < bufferData.length ? array.length : bufferData.length));
BufferedImage image = new BufferedImage(cm, raster, false, null);
FileOutputStream fos = new FileOutputStream("D:\\abc\\OCR\\" + "LearningRaster" + ".png");
ImageIO.write(image, "PNG", fos);
fos.close();
setPixels returns void:
public static void setPixels(BufferedImage img,
int x, int y, int w, int h, int[] pixels)
so you need to create Raster and than set pixels to it:
WritableRaster newRaster= WritableRaster.createWritableRaster(…);
newRaster.setPixels(0, 0, width, height, matrix);
You need to put 4 int per pixel (it depends on color model, 4 for ARGB). So, matrix size must be
int[] matrix = new int[width * height * 4]
See more about WritableRaster here —
Oracle: WritableRaster
Code examples

Image Processing in Java

I want to extract the pixel values of the jpeg image using the JAVA language, and need to store it in array(bufferdArray) for further manipulation. So how i can extract the pixel values from jpeg image format?
Have a look at BufferedImage.getRGB().
Here is a stripped-down instructional example of how to pull apart an image to do a conditional check/modify on the pixels. Add error/exception handling as necessary.
public static BufferedImage exampleForSO(BufferedImage image) {
BufferedImage imageIn = image;
BufferedImage imageOut =
new BufferedImage(imageIn.getWidth(), imageIn.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
int width = imageIn.getWidth();
int height = imageIn.getHeight();
int[] imageInPixels = imageIn.getRGB(0, 0, width, height, null, 0, width);
int[] imageOutPixels = new int[imageInPixels.length];
for (int i = 0; i < imageInPixels.length; i++) {
int inR = (imageInPixels[i] & 0x00FF0000) >> 16;
int inG = (imageInPixels[i] & 0x0000FF00) >> 8;
int inB = (imageInPixels[i] & 0x000000FF) >> 0;
if ( conditionChecker_inRinGinB ){
// modify
} else {
// don't modify
}
}
imageOut.setRGB(0, 0, width, height, imageOutPixels, 0, width);
return imageOut;
}
The easiest way to get a JPEG into a java-readable object is the following:
BufferedImage image = ImageIO.read(new File("MyJPEG.jpg"));
BufferedImage provides methods for getting RGB values at exact pixel locations in the image (X-Y integer coordinates), so it'd be up to you to figure out how you want to store that in a single-dimensional array, but that's the gist of it.
There is a way of taking a buffered image and converting it into an integer array, where each integer in the array represents the rgb value of a pixel in the image.
int[] pixels = ((DataBufferInt)image.getRaster().grtDataBuffer()).getData();
The interesting thing is, when an element in the integer array is edited, the corresponding pixel in the image is as well.
In order to find a pixel in the array from a set of x and y coordinates, you would use this method.
public void setPixel(int x, int y ,int rgb){
pixels[y * image.getWidth() + x] = rgb;
}
Even with the multiplication and addition of coordinates, it is still faster than using the setRGB() method in the BufferedImage class.
EDIT:
Also keep in mind, the image needs type needs to be that of TYPE_INT_RGB, and isn't by default. It can be converted by creating a new image of the same dimensions, and of the type of TYPE_INT_RGB. Then using the graphics object of the new image to draw the original image to the new one.
public BufferedImage toIntRGB(BufferedImage image){
if(image.getType() == BufferedImage.TYPE_INT_RGB)
return image;
BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight, BufferedImage.TYPE_INT_RGB);
newImage.getGraphics().drawImage(image, 0, 0, null);
return newImage;
}

Categories