Processing has a class named PImage from which you can get an array of int that contains values for all pixels. Then, you manipulate this array and call updatePixels() and voila you have applied an effect to the image.
I was wondering if the same can be done in BufferedImage with some appropriate mechanism. I found that BufferedImage does indeed have a method to get pixels as int[]:
public int[] getRGB(int startX,
int startY,
int w,
int h,
int[] rgbArray,
int offset,
int scansize)
Returns an array of integer pixels in the default RGB color model (`TYPE_INT_ARGB`) and default sRGB color space, from a portion of the image data.
Color conversion takes place if the default model does not match the image `ColorModel`.
There are only 8-bits of precision for each color component in the returned data when using this method.
How do I modify these pixels and show the appropriate changes in BufferedImage ?
I guess I will need to obtain a WritableRaster for the image and use
public void setPixels(int x,
int y,
int w,
int h,
int[] iArray)
but I am still unsure.
To create a WritableRaster, you have to choose a ColorModel first.
I think the RGB default should suit your needs.
ColorModel colorModel = ColorModel.getRGBdefault();
WritableRaster raster = colorModel.createCompatibleWritableRaster(width, height);
Then, you can fill it with your pixels and create a new BufferedImage.
raster.setPixels(0, 0, width, height, pixels);
BufferedImage image = new BufferedImage(colorModel, raster, true, null);
And just as a reminder, here is a way to extract pixels from a BufferedImage:
Raster raster = bufferedImage.getRaster();
int[] pixels = raster.getPixels(0, 0, raster.getWidth(), raster.getHeight(), (int[]) null);
The PImage class integrates a bit with the BufferedImage class:
//BufferedImage to PImage
PImage img = new PImage(yourBufferedImageInstance);
//PImage to BufferedImage
BufferedImage img = (BufferedImage)yourPImageInstance.getNative();
Related
I am currently trying to get some kind of 2D dungeoncrawler (think: roguelike) running. Now I want to work with square tiles (32x32) but I wonder if there's a way to make my textures in a higher resolution, say 64x64, and scale them down onto a 32x32 square?
I imagine there has to be since almost all games do this in one way or another but all I can seem to find online is about 3D stuff.
Yeah. When you draw an image, you can add the new width and height to it to resize it.
public static BufferedImage resizeImage(BufferedImage image, int newwidth, int newheight) {
BufferedImage image2 = new BufferedImage(newwidth, newheight, BufferedImage.TYPE_INT_ARGB);
Graphics g = image2.getGraphics();
g.drawImage(image, 0, 0, newwidth, newheight, null);
g.dispose();
return image2;
}
Refer to here for more info.
I would like to create a BufferedImage with certin width, height (800x600) and bit depth of 24 and I would like image background to be transparent.
How do I do that?
Thanking you.
You use the constructor and pass a suitable format parameter:
new BufferedImage(w, h, BufferedImage.TYPE_?);
where TYPE_? is on of the constants that define a format with alpha channel, like TYPE_INT_ARGB.
Edit: Straight from BufferedImage
/**
* Represents an image with 8-bit RGBA color components packed into
* integer pixels. The image has a <code>DirectColorModel</code>
* with alpha. The color data in this image is considered not to be
* premultiplied with alpha. When this type is used as the
* <code>imageType</code> argument to a <code>BufferedImage</code>
* constructor, the created image is consistent with images
* created in the JDK1.1 and earlier releases.
*/
public static final int TYPE_INT_ARGB = 2;
These are the options you have with BufferedImage:
BufferedImage(ColorModel cm, WritableRaster raster, boolean isRasterPremultiplied, Hashtable<?,?> properties)
BufferedImage(int width, int height, int imageType)
BufferedImage(int width, int height, int imageType, IndexColorModel cm)
I have no problem setting up an image from an array of integers. (As the integer version of MemoryImageSource can be instantiated with a far simpler constructor).
I tried:
ComponentColorModel model = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
false,
false,
ComponentColorModel.OPAQUE,
DataBuffer.TYPE_BYTE);
ImageProducer ip = new MemoryImageSource(width, height, model, bytes, 0, width);
But the image seems to be empty (totally transparent). I tried with image data and without alpha and also constructed the model with and without alpha channel. - No image shows.
There is no problem at all if I convert my byte[] to int[] and use the constructor:
MemoryImageSource(int w, int h, int[] pix, int off, int scan)
... but won't work with:
MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off, int scan)
I'm probably having the color model wrong, but even then I expect to see some distorted pixel data (espacially with usong ComponentColorModel.OPAQUE).
to my understanding the following code
int [] pixels = image.getRaster().getPixels(0, 0, width, height, (int[])null);
should generate an array which has exactly the size width x height, but in practice it seems to be much larger, why?
image may be a bufferedimage, toolkitimage or volatileimage.
it generates a array with
new int[numBands * w * h]; // The number of bands of the image data.
from the SampleModel from your Raster
I want to create a blank bitmap, which I will conditionally fill with Rects of pixels obtained from another bitmap that holds a resource. Is it possible to do that? How would I go about doing something like that?
I only want to draw the bitmap once it is ready to be drawn.
Right now I'm using Canvas to draw the bitmap using Rect segments, but I don't need it to be drawn until it is ready.
Thanks!
Bitmap other = ...;
//create a blank bitmap
Bitmap newBitmap = Bitmap.createBitmap(other.getWidth(),
other.getHeight(), other.getConfig());
//copy some pixels from 'other'
int x=14,y=45,width=23,height=56;
int [] pixels = new int[width * height];
other.getPixels(pixels, 0, width, x, y, width, height);
newBitmap.setPixels(pixels, 0, width, x, y, width, height);