How can I convert a string containing a jpeg or png to an array (preferably one dimensional) of pixels? Ideally using classes built into java?
It turns out you need commons-fileupload. Look at the user guide for how to obtain the image InputStream. From there you can simply call:
BufferedImage image = ImageIO.read(item.getInputStream());
From here on there are many ways:
loop over the image dimensions and for each x and y call int rgb = image.getRGB(x, y);
same as above, but call getRed(x, y), getGreen(x, y), getBlue(x, y)
get the ColorModel and call the above methods there
call getRGB(startX, startY, w, h, rgbArray, offset, scansize)
call getData(), which returns a Raster, and call getPixes(..) there
Use PixelGraber. It returns one-dimensional array of RGB data.
Related
I'm writing an application that needs to work with 16-bit "5-5-5" RGB colors (that is, 5 bits for each color and one bit of padding). In order to handle these images, I am using the BufferedImage class provided by AWT. The BufferedImage class specifically allows for the usage of non-RGB color spaces by taking either a ColorModel object or a predefined image type constant - one of which is the 5-5-5 pixel format that I need.
My problem is this: the BufferedImage "setRGB()" method states in its description that color values provided are "assumed to be in the default RGB color model, TYPE_INT_ARGB, and default sRGB color space" (per the BufferedImage documentation page). No other method seems to accept values designed for different color spaces, either.
Is there a way to use my non-standard color space directly with BufferedImage, or would I have to rely on the class's internal color conversion mechanisms to handle all of my colors? (Or am I just misreading/misunderstanding something about how the class works?)
BufferedImage.TYPE_USHORT_555_RGB still uses a completely standard RGB color space (in fact, it uses sRGB), so I don't think a different color space is what you are looking for.
If you want to perform painting or other operations in Java, just use the normal methods like setRGB/getRGB() and createGraphics()/Grapics2D. Everything will be properly converted to and from the packed USHORT_555_RGB format for you.
For example:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Do some custom painting
Graphics2D g = image.createGraphics();
g.drawImage(otherImage, 0, 0, null); // image type here does not matter
g.setColor(Color.ORANGE); // Color in sRGB, but does not matter
g.fillOval(0, 0, w, h);
g.dispose();
image.setRGB(0, h/2, w, 1, new int[w]); // Silly way to create a horizontal black line at the center of the image... Don't do this, use fillRect(0, h/2, 1, w)! ;-)
// image will still be USHORT_555_RGB *internally*
However, if you have pixel data in the USHORT_555_RGB format (ie. from an external library/api/service), it may be faster and more accurate to set these values directly to the raster/databuffer. Or if you need to pass the pixel values back to the same library/api/service.
For example, using the Raster:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Some fictional API. It's assumed that data.length == w * h
short[] apiPixels = api.getPixelsUSHORT_555_RGB(w, h);
WritableRaster raster = image.getRaster();
// Set short values to image
raster.setDataElements(0, 0, w, h, apiPixels);
// Get short values from image
short[] pixels = (short[]) raster.getDataElements(0, 0, w, h, null); // TYPE_USHORT_555_RGB -> always short[]
api.setPixels(pixels, w, h); // Another fictional API
Or, alternatively, use the DataBuffer:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Some fictional API. It's assumed that data.length == w * h
short[] apiPixels = api.getPixelsUSHORT_555_RGB(w, h);
DataBufferUShort buffer = (DataBufferUShort) image.getRaster().getDataBuffer(); // TYPE_USHORT_555_RGB -> always DataBufferUShort
// Set short values to image
System.arraycopy(apiPixels, 0, buffer.getData(), 0, apiPixels.length);
// Get short values from image
api.setPixels(buffer.getData(), w, h);
In most cases it does not matter which method you use, but the first approach (using Raster only) may keep the image managed, which will make images display faster on screen from your Java process.
PS: If a different color space is really what you need (ie. the pixel array from the external library/api/service uses a different color space, and you need to view the pixels in this color space), you can create a BufferedImage in USHORT_555_RGB style with a custom color space like this:
// Either use one of the built-in color spaces, or load one from disk
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
ColorSpace colorSpaceToo = new ICC_ColorSpace(ICC_Profile.getInstance(Files.newInputStream(new File("/path/to/custom_rgb_profile.icc").toPath())));
// Create a color model using your color space, TYPE_USHORT and 5/5/5 mask, no transparency
ColorModel colorModel = new DirectColorModel(colorSpace, 15, 0x7C00, 0x03E0, 0x001F, 0, false, DataBuffer.TYPE_USHORT);
// And finally, create an image from the color model and a compatible raster
BufferedImage imageToo = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(w, h), colorModel.isAlphaPremultiplied(), null);
Just remember that as the Java2D graphics operations and setRGB/getRGB are still using sRGB, now all operations on your image will be converted back and forth between your color space and sRGB. Performance will not be as good.
for an assignment I have to display an image using imagej in java. So I used the following code:
FloatProcessor abc=new FloatProcessor(imageSizeX,imageSizeY);
for (int i=0;i<imageSizeX;i++){
for(int j=0;j<imageSizeY;j++){
abc.putPixel(i, j, 100);
}
}
ImagePlus im=new ImagePlus("test",abc);
im.show();
but the Image I get is always completely black. Can you tell me what the mistake is?
It should at least be white if the value was 0 shouldn't it?
(FYI: imageSizeX=imageSizeY=256)
.putPixel uses the conversion Float.intBitsToFloat.
If you want a direct access to the pixels, you can use setf(int x, int y, float value).
Moreover, if you already have the pixels into an array, you can use the constructors to immediately set the pixel values FloatProcessor(int width, int height, int[] pixels).
i have 2D array to keep color component value :
p[pixel_value][red]
p[pixel_value][green]
p[pixel_value][blue]
i just dont know how to use them to make an image.
i read about setRGB, what i understand is i should mix all of them to become a RGBArray. then how to make it?
is it any better way to make an image without setRGB ? i need some explanation.
The method setRGB() can be used to set the color of a pixel of an already existing image. You can open an already existing image and set all the pixels of it, using the values stored in your 2D array.
You can do it like this:
BufferedImage img = ImageIO.read(new File("image which you want to change the pixels"));
for(int width=0; width < img.getWidth(); width++)
{
for(int height=0; height < img.getHeight(); height++)
{
Color temp = new Color(p[pixel_value][red], p[pixel_value][green], p[pixel_value][blue]);
img.setRGB(width, height, temp.getRGB());
}
}
ImageIO.write(img, "jpg", new File("where you want to store this new image"));
Like this, you can iterate over all the pixels and set their color accordingly.
NOTE: By doing this, you will lose your original image. This is just a way which I know.
What you need is a BufferedImage. Create a BufferedImage of type TYPE_3BYTE_BGR, if RGB is what you want, with a specified width and height.
QuickFact:
The BufferedImage subclass describes an Image with an accessible
buffer of image data.
Then, call the getRaster() method to get a WritableRaster
QuickFact:
This class extends Raster to provide pixel writing capabilities.
Then, use the setPixel(int x, int y, double[] dArray) method to set the pixels.
Update:
If all you want is to read an image, use the ImageIO.read(File f) method. It will allow you to read an image file in just one method call.
Somewhat SSCCE:
BufferedImage img = null;
try {
img = ImageIO.read(new File("strawberry.jpg"));
} catch (IOException e) {
}
You want to manually set RGB values?
You need to know that since an int is 32bit it contains all 4 rgb values (1 for the transparency).
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
^Alpha ^red ^green ^blue
You can accomplish using 4 int values by the use of binary arithmetic:
int rgb = (red << 16) && () (green << 8) & (blue);
bufferedImage.setRGB(x, y, rgb);
IN the above you can add Alpha as well if needed. You just "push" the binary codes into the right places.
I'm trying get bytes from bitmap in blackberry using the next method in Bitmap:
getRGB565(byte[] rgbData, int offset, int scanLength, int x, int y, int width, int height)
But i have read the params and i don't know how must i calculate scanLength:
scanLength - Width of a scanline (in bytes) within the data array.
Any idea?
Here scanLength is the full width of the original image, while width is the width of the rectangle you are copying from.
If you are copying the whole image it is the same, but if you are copying only a part of the image you'll have scanLength > width.
See also the Bitmap#getRGB565 javadoc
To get byte[] from Bitmap I used this: http://blackberry-digger.blogspot.com/2009/05/code-convert-bitmap-to-png-and-then.html and it worked fine.
Sorry it was too easy . In getARG is another example , it must be used usually with the same int width param
I need a bit of a hand reading the buffer that is spat out by the glReadPixels feature in android's opengl-es api. Here is my code so far...
public static void pick(GL11 gl){
int[] viewport = new int[4];
IntBuffer pixel = IntBuffer.allocate(384000);
mColourR = BaseObject.getColourR();
mColourG = BaseObject.getColourG();
mColourB = BaseObject.getColourB();
x = MGLSurfaceView.X();
y = MGLSurfaceView.Y();
gl.glGetIntegerv(GL11.GL_VIEWPORT,viewport,0);
gl.glReadPixels((int)x,viewport[3]-(int)y, 1, 1, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixel);
}
the name of the output buffer in this code is "pixel" what do I need to add to this code to get the colour values back from the "pixel" buffer.
You can use one of the get() methods of the IntBuffer to access individual values.
RGB color values are usually stored in that very order, so calling pixel.get(0) will get you the red value of the first pixel, pixel.get(1) will get you the green channel and so on. Usually, the values are stored line-wise.
So, if you need a value for a particular pixel, (x,y) you will have to call get(screenWidth*3*y + x)
By the way, you can retrieve the raw int array from your IntBufferby calling pixels.array()