Does .Net PixelFormat have Java equivalent? - java

What in Java matches to C# PixelFormat's members.
i.e. Format24bppRgb matches to BufferedImage.TYPE_INT_RGB?
Here is my code. I got an image which has .Net's PixelFormat = Format32bppArgb. I am creating BufferedImage like this:
int sizeBytes = width * height;
DataBufferByte dataBuffer = new DataBufferByte(myImageBytes, sizeBytes);
WritableRaster raster = Raster.createInterleavedRaster(dataBuffer, // dataBuffer
width, // width
height, // height
width * 4, // scanlineStride
4, // pixelStride
new int[]{0, 1, 2, 3}, // bandOffsets
null); // location
java.awt.image.ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), // ColorSpace
new int[]{8, 8, 8, 8}, // bits
true, // hasAlpha
false, // isPreMultiplied
ComponentColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);
BufferedImage result = new BufferedImage(colorModel, raster, false, null);
After I create a bufferedImage red and blue colors are swapped in it.
Next, I tried to create an image as follow
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
WritableRaster r = result.getRaster();
int[] pixels = byteToInt(bytes);
r.setPixels(0, 0, width, height , pixels); // ! Here an exception occures, because after I converted the byte array to int one the width becomes too long.
Byte array was convert by this method
private int[] byteToInt(byte[] pixels) {
int[] ints = new int[pixels.length / 3];
int byteIdx = 0;
for (int pixel = 0; pixel < ints.length; pixel++) {
int red = (int) pixels[byteIdx++] & 0xFF;
int green = (int) pixels[byteIdx++] & 0xFF;
int blue = (int) pixels[byteIdx++] & 0xFF;
int rgb = (red << 16) | (green << 8) | blue;
ints[pixel] = rgb;
}
return ints;
}
The colors look fine now, but I got the exception
java.lang.ArrayIndexOutOfBoundsException: 27600
at sun.awt.image.ByteInterleavedRaster.setPixels(ByteInterleavedRaster.java:1106)
If I use the smaller width (e.g. width / 3) the colors look fine but the picture itself shrinks.

BufferedImage is definately a good place to start. Many of the values in PixelFormat will match up to values in BufferedImage - they each have 24-bit and 32-bit RGB/ARGB values, both have 5-5-5 and 5-6-5 combinations, etc.
If you're having trouble, post some code and we'll have a look at it, try to help. The thing I would recommend would be to play around with the byte ordering (in the pixel ints) until you get the result that you expect - try drawing the BufferedImage onto a GUI object like JPanel so you can see what it looks like.
If you've got an array of int[] for your pixel values, this is the code I usually use for displaying the array as an image...
int[] pixels;
ColorModel model = new DirectColorModel(32,0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
Image image = new JLabel().createImage(new MemoryImageSource(width,height,model,pixels,0,width));

Related

Convert 8bit Grayscale image byte array to a BufferedImage

I have a byte array containing data of the raw grayscale 8bit image, which I need to convert to a BufferedImage. I've tried doing:
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));
However, the resulting image object is null which means I'm doing something wrong here.
What's the correct way of making such a conversion?
There are two good ways to do this, depending on your use case.
Either create a new, gray image, and copy the data into it. This will keep the image "managed", which may lead to better rendering performance (ie. on screen). But it will need twice as much memory, and copy the data from your input to the image.
The other, is to create the gray image directly "around" your existing pixel data. This will be faster, and use almost no extra heap, as it avoids copying the pixel data. But the image will not be managed (as the backing array is exposed and mutable).
Both options are demonstrated below:
int w = 640;
int h = 480;
byte[] imageBytes = new byte[w * h];
// 1 Keeps the image "managed" at the expense of twice the memory + a large array copy
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
image.getRaster().setDataElements(0, 0, w, h, imageBytes);
System.out.println("image: " + image);
// 2 Faster, and uses less memory, but will make the image "unmanaged"
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
WritableRaster raster = Raster.createInterleavedRaster(new DataBufferByte(imageBytes, imageBytes.length), w, h, w, 1, new int[]{0}, null);
BufferedImage image2 = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
System.out.println("image2: " + image2);
If the image data isn't in linear gray color space, one could use an IndexColorModel to map the input into whatever range you want:
// Alternate, using IndexColorModel, if your input isn't in linear gray color space
int[] cmap = new int[256]; // TODO: Add ARGB packed colors here...
IndexColorModel icm = new IndexColorModel(8, 256, cmap, 0, false, -1, DataBuffer.TYPE_BYTE);
// As 1
BufferedImage image3 = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED, icm);
image3.getRaster().setDataElements(0, 0, w, h, imageBytes);
System.out.println("image3: " + image3);
// As 2
BufferedImage image4 = new BufferedImage(icm, raster, cm.isAlphaPremultiplied(), null);
System.out.println("image4: " + image4);
I've managed to did the conversion for the 640x480 resolution the following way:
BufferedImage image = new BufferedImage(640,480,BufferedImage.TYPE_BYTE_INDEXED);
int i = 0;
for(int y = 0; y < 480; y++)
{
for(int x = 0; x < 640; x++)
{
int g = imageBytes[i++] & 0xFF;
image.setRGB(x,y,new Color(g,g,g).getRGB());
}
}
EDIT: removed useless code (thanks to Marco13)
Java
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
image.getRaster().setDataElements(0, 0, width, height, array));
Kotlin
val image = BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY)
image.raster.setDataElements(0, 0, width, height, byteArray )

How to set RGB pixel in a BufferedImage to display a 16-bit-depth PNG?

I am trying to read and show a PNG file.
I have no problem dealing with images with 8-bit depth.
I proceed as follow:
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Then I read the 3*8=24 bits of each pixel, save them in an array of byte data and put them in the image with:
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
result.setRGB(x, y, ((data[x * 3 + 0] & 0xff) << 16)
+ ((data[x * 3 + 1] & 0xff) << 8)
+ ((data[x * 3 + 2] & 0xff)));
The problem is now with 16-bit depth images. Of course data is bigger now and it contains 48bits, divided in 6 bytes, for each RGB triple: from the debugger data has the values I expect.
How can I set the RGB pixel? Do I have to change the BufferedImage declaration? Maybe with:
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_565_RGB);
Many thanks in advance!
P.S.: following PNG standars, the image has color type 2 (RGB without alpha).
Maybe I'll have to use http://docs.oracle.com/javase/7/docs/api/java/awt/image/ColorModel.html
#haraldK has pointed in the right direction. I'm providing some working code which is from "PNGReader" of "icafe" Java image library.
if(bitsPerPixel == 16) {
if(interlace_method==NON_INTERLACED)
spixels = generate16BitRGBPixels(compr_data, false);
else {
spixels = generate16BitRGBInterlacedPixels(compr_data, false);
}
int[] off = {0, 1, 2}; //band offset, we have 3 bands
int numOfBands = 3;
boolean hasAlpha = false;
int trans = Transparency.OPAQUE;
int[] nBits = {16, 16, 16};
if(alpha != null) { // Deal with single color transparency
off = new int[] {0, 1, 2, 3}; //band offset, we have 4 bands
numOfBands = 4;
hasAlpha = true;
trans = Transparency.TRANSLUCENT;
nBits = new int[] {16, 16, 16, 16};
}
db = new DataBufferUShort(spixels, spixels.length);
raster = Raster.createInterleavedRaster(db, width, height, width*numOfBands, numOfBands, off, null);
cm = new ComponentColorModel(colorSpace, nBits, hasAlpha, false, trans, DataBuffer.TYPE_USHORT);
}
return new BufferedImage(cm, raster, false, null);
Here is the generate16BitRGBPixels() method:
private short[] generate16BitRGBPixels(byte[] compr_data, boolean fullAlpha) throws Exception {
//
int bytesPerPixel = 0;
byte[] pixBytes;
if (fullAlpha)
bytesPerPixel = 8;
else
bytesPerPixel = 6;
bytesPerScanLine = width*bytesPerPixel;
// Now inflate the data.
pixBytes = new byte[height * bytesPerScanLine];
// Wrap an InflaterInputStream with a bufferedInputStream to speed up reading
BufferedInputStream bis = new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(compr_data)));
apply_defilter(bis, pixBytes, height, bytesPerPixel, bytesPerScanLine);
short[] spixels = null;
if(alpha != null) { // Deal with single color transparency
spixels = new short[width*height*4];
short redMask = (short)((alpha[1]&0xff)|(alpha[0]&0xff)<<8);
short greenMask = (short)((alpha[3]&0xff)|(alpha[2]&0xff)<<8);;
short blueMask = (short)((alpha[5]&0xff)|(alpha[4]&0xff)<<8);
for(int i = 0, index = 0; i < pixBytes.length; index += 4) {
short red = (short)((pixBytes[i++]&0xff)<<8|(pixBytes[i++]&0xff));
short green = (short)((pixBytes[i++]&0xff)<<8|(pixBytes[i++]&0xff));
short blue = (short)((pixBytes[i++]&0xff)<<8|(pixBytes[i++]&0xff));
spixels[index] = red;
spixels[index + 1] = green;
spixels[index + 2] = blue;
if(spixels[index] == redMask && spixels[index + 1] == greenMask && spixels[index + 2] == blueMask) {
spixels[index + 3] = (short)0x0000;
} else {
spixels[index + 3] = (short)0xffff;
}
}
} else
spixels = ArrayUtils.toShortArray(pixBytes, true);
return spixels;
}
and the ArrayUtils.toShortArray() method:
public static short[] toShortArray(byte[] data, int offset, int len, boolean bigEndian) {
ByteBuffer byteBuffer = ByteBuffer.wrap(data, offset, len);
if (bigEndian) {
byteBuffer.order(ByteOrder.BIG_ENDIAN);
} else {
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
ShortBuffer shortBuf = byteBuffer.asShortBuffer();
short[] array = new short[shortBuf.remaining()];
shortBuf.get(array);
return array;
}
If you want to create an image with 16 bits per sample (or 48 bits per pixel), there is no BufferedImage.TYPE_... constant for that. TYPE_USHORT_565_RGB creates an image with 16 bits per pixel, with samples of 5 (red), 6 (green) and 5 (blue) bits respectively. I think these USHORT RGB values are leftovers from a time when some computes actually had the option of a 16 bit display (aka "Thousands of colors").
What you need to do, to actually create an image with 16 bits per sample, is:
ColorModel cm;
WritableRaster raster;
BufferedImage result = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
The raster is created from a data buffer of type DataBufferUShort with either 3 banks and a BandedSampleModel with 3 bands, or use a single bank and a PixelInterleavedSampleModel with a pixelStride of 3, scanLineStride of 3 * width and bandOffsets {0, 1, 2}.
Here's a full sample, using interleaved sample model:
ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB)
ColorModel cm = new ComponentColorModel(sRGB, false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, w, h, 3, null);
BufferedImage rgb = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
PS: With the data buffer exposed, you can access the short samples directly, to manipulate the pixels. This is much faster than using BufferedImage.getRGB(...)/setRGB(...), and will keep the original 16 bit per sample precision. BufferedImage.getRGB(...) will convert the pixel values to 32 bit pixel/8 bit per sample, and thus lose the extra precision.

Wrong brightness converting image to grayscale in Java

I'm converting a image to gray scale in Java with the following code:
BufferedImage originalImage = ImageIO.read(new File("/home/david/input.bmp"));
BufferedImage grayImage = new BufferedImage(originalImage.getWidth()
, originalImage.getHeight()
, BufferedImage.TYPE_BYTE_GRAY);
ColorSpace gray = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorConvertOp colorConvert = new ColorConvertOp(gray, null);
colorConvert.filter(originalImage, grayImage);
ImageIO.write(grayImage, "bmp", new File("/home/david/output_java.bmp"));
That seems to work, but the problem is that the output image is very different from the gray scale image generated by gimp (see examples below).
Can I control someway how is the image generated?
How I can make the result more similar to the gimp result?
Original image:
Gray scale image generated in Java:
Gray scale image generated in Gimp (Image -> Mode -> Grayscale):
BTW: I have a bunch of images coming from ffmpeg (with gray option) and they are like Gimp images so because of that I want my image in that way.
Finally I've wrote GrayscaleFilter class implementing BufferedImageOp interface.
I've followed this really good guide about Java image processing.
This is the relevant code fragment:
public class GrayscaleFilter extends AbstractFilter
{
public final static double[] METHOD_AVERAGE = {1.0/3.0, 1.0/3.0, 1.0/3.0};
public final static double[] METHOD_GIMP_LUMINOSITY = {0.21, 0.71, 0.07};
public GrayscaleFilter(final double[] rgb)
{
this(rgb[0], rgb[1], rgb[2]);
}
public BufferedImage filter(BufferedImage src, BufferedImage dest)
{
if (src.getType() == BufferedImage.TYPE_BYTE_GRAY)
{
dest = src;
return dest;
}
if (dest == null)
dest = createCompatibleDestImage(src, null);
final int width = src.getWidth();
final int height = src.getHeight();
int[] inPixels = new int[width * height];
GraphicsUtilities.getPixels(src, 0, 0, width, height, inPixels);
byte[] outPixels = doFilter(inPixels);
GraphicsUtilities.setPixels(dest, 0, 0, width, height, outPixels);
return dest;
}
private byte[] doFilter(int[] inputPixels)
{
int red, green, blue;
int i = 0;
byte[] outPixels = new byte[inputPixels.length];
for(int pixel : inputPixels)
{
// Obtengo valores originales
red = (pixel >> 16) & 0xFF;
green = (pixel >> 8) & 0xFF;
blue = pixel & 0xFF;
// Calculo valores nuevos
outPixels[i++] = (byte)(
red * red_part +
green * green_part +
blue * blue_part
);
}
return outPixels;
}
public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM)
{
return new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
}
}
Find out the conversion formula used by Gimp. It probably takes some human color perception into account, while the Java implementation is mathematical (R+G+B)/ 3.

How to convert array of bytes into Image in Java SE

What is the right way to convert raw array of bytes into Image in Java SE.
array consist of bytes, where each three bytes represent one pixel, with each byte for corresponding RGB component.
Can anybody suggest a code sample?
Thanks,
Mike
You can do it using Raster class. It's better because it does not require iterating and copying of byte arrays.
byte[] raw = new byte[width*height*3]; // raw bytes of our image
DataBuffer buffer = new DataBufferByte(raw, raw.length);
//The most difficult part of awt api for me to learn
SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 3, width*3, new int[]{2,1,0});
Raster raster = Raster.createRaster(sampleModel, buffer, null);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
image.setData(raster);
Assuming you know the height and width of the image.
BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for(int r=0; r<height; r++)
for(int c=0; c<width; c++)
{
int index=r*width+c;
int red=colors[index] & 0xFF;
int green=colors[index+1] & 0xFF;
int blue=colors[index+2] & 0xFF;
int rgb = (red << 16) | (green << 8) | blue;
img.setRGB(c, r, rgb);
}
Roughly. This assumes the pixel data is encoded as a set of rows; and that the length of colors is 3 * width * height (which should be valid).
folkyatina's approach works if your RGB values are in B,G,R order, but if they are in R,G,B order I have found the following code to work:
DataBuffer rgbData = new DataBufferByte(rgbs, rgbs.length);
WritableRaster raster = Raster.createInterleavedRaster(
rgbData, width, height,
width * 3, // scanlineStride
3, // pixelStride
new int[]{0, 1, 2}, // bandOffsets
null);
ColorModel colorModel = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{8, 8, 8}, // bits
false, // hasAlpha
false, // isPreMultiplied
ComponentColorModel.OPAQUE,
DataBuffer.TYPE_BYTE);
return new BufferedImage(colorModel, raster, false, null);
There is a setRGB variant which accepts an int array of RGBA values:
BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] raw = new int[data.length * 4 / 3];
for (int i = 0; i < data.length / 3; i++) {
raw[i] = 0xFF000000 |
((data[3 * i + 0] & 0xFF) << 16) |
((data[3 * i + 1] & 0xFF) << 8) |
((data[3 * i + 2] & 0xFF));
}
img.setRGB(0, 0, width, height, raw, 0, width);
The performance characteristics is similar to CoderTao's solution.
Assuming that your raw data is a 1d array like:
byte[] imageBytes = new byte[1024];
// transform to bufferImage
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
// if you want to do some operations to the image, like resize,
// use the lib (net.coobird.thumbnailator)
BufferedImage image = Thumbnails.of(bufferedImage).forceSize(WIDTH, HEIGHT)
.outputFormat("bmp").asBufferedImage();

Set BufferedImage alpha mask in Java

I have two BufferedImages I loaded in from pngs. The first contains an image, the second an alpha mask for the image.
I want to create a combined image from the two, by applying the alpha mask. My google-fu fails me.
I know how to load/save the images, I just need the bit where I go from two BufferedImages to one BufferedImage with the right alpha channel.
I'm too late with this answer, but maybe it is of use for someone anyway. This is a simpler and more efficient version of Michael Myers' method:
public void applyGrayscaleMaskToAlpha(BufferedImage image, BufferedImage mask)
{
int width = image.getWidth();
int height = image.getHeight();
int[] imagePixels = image.getRGB(0, 0, width, height, null, 0, width);
int[] maskPixels = mask.getRGB(0, 0, width, height, null, 0, width);
for (int i = 0; i < imagePixels.length; i++)
{
int color = imagePixels[i] & 0x00ffffff; // Mask preexisting alpha
int alpha = maskPixels[i] << 24; // Shift blue to alpha
imagePixels[i] = color | alpha;
}
image.setRGB(0, 0, width, height, imagePixels, 0, width);
}
It reads all the pixels into an array at the beginning, thus requiring only one for-loop. Also, it directly shifts the blue byte to the alpha (of the mask color), instead of first masking the red byte and then shifting it.
Like the other methods, it assumes both images have the same dimensions.
I played recently a bit with this stuff, to display an image over another one, and to fade an image to gray.
Also masking an image with a mask with transparency (my previous version of this message!).
I took my little test program and tweaked it a bit to get the wanted result.
Here are the relevant bits:
TestMask() throws IOException
{
m_images = new BufferedImage[3];
m_images[0] = ImageIO.read(new File("E:/Documents/images/map.png"));
m_images[1] = ImageIO.read(new File("E:/Documents/images/mapMask3.png"));
Image transpImg = TransformGrayToTransparency(m_images[1]);
m_images[2] = ApplyTransparency(m_images[0], transpImg);
}
private Image TransformGrayToTransparency(BufferedImage image)
{
ImageFilter filter = new RGBImageFilter()
{
public final int filterRGB(int x, int y, int rgb)
{
return (rgb << 8) & 0xFF000000;
}
};
ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
return Toolkit.getDefaultToolkit().createImage(ip);
}
private BufferedImage ApplyTransparency(BufferedImage image, Image mask)
{
BufferedImage dest = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = dest.createGraphics();
g2.drawImage(image, 0, 0, null);
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.DST_IN, 1.0F);
g2.setComposite(ac);
g2.drawImage(mask, 0, 0, null);
g2.dispose();
return dest;
}
The remainder just display the images in a little Swing panel.
Note that the mask image is gray levels, black becoming full transparency, white becoming full opaque.
Although you have resolved your problem, I though I could share my take on it. It uses a slightly more Java-ish method, using standard classes to process/filter images.
Actually, my method uses a bit more memory (making an additional image) and I am not sure it is faster (measuring respective performances could be interesting), but it is slightly more abstract.
At least, you have choice! :-)
Your solution could be improved by fetching the RGB data more than one pixel at a time(see http://java.sun.com/javase/6/docs/api/java/awt/image/BufferedImage.html), and by not creating three Color objects on every iteration of the inner loop.
final int width = image.getWidth();
int[] imgData = new int[width];
int[] maskData = new int[width];
for (int y = 0; y < image.getHeight(); y++) {
// fetch a line of data from each image
image.getRGB(0, y, width, 1, imgData, 0, 1);
mask.getRGB(0, y, width, 1, maskData, 0, 1);
// apply the mask
for (int x = 0; x < width; x++) {
int color = imgData[x] & 0x00FFFFFF; // mask away any alpha present
int maskColor = (maskData[x] & 0x00FF0000) << 8; // shift red into alpha bits
color |= maskColor;
imgData[x] = color;
}
// replace the data
image.setRGB(0, y, width, 1, imgData, 0, 1);
}
For those who are using alpha in the original image.
I wrote this code in Koltin, the key point here is that if you have the alpha on your original image you need to multiply these channels.
Koltin Version:
val width = this.width
val imgData = IntArray(width)
val maskData = IntArray(width)
for(y in 0..(this.height - 1)) {
this.getRGB(0, y, width, 1, imgData, 0, 1)
mask.getRGB(0, y, width, 1, maskData, 0, 1)
for (x in 0..(this.width - 1)) {
val maskAlpha = (maskData[x] and 0x000000FF)/ 255f
val imageAlpha = ((imgData[x] shr 24) and 0x000000FF) / 255f
val rgb = imgData[x] and 0x00FFFFFF
val alpha = ((maskAlpha * imageAlpha) * 255).toInt() shl 24
imgData[x] = rgb or alpha
}
this.setRGB(0, y, width, 1, imgData, 0, 1)
}
Java version (just translated from Kotlin)
int width = image.getWidth();
int[] imgData = new int[width];
int[] maskData = new int[width];
for (int y = 0; y < image.getHeight(); y ++) {
image.getRGB(0, y, width, 1, imgData, 0, 1);
mask.getRGB(0, y, width, 1, maskData, 0, 1);
for (int x = 0; x < image.getWidth(); x ++) {
//Normalize (0 - 1)
float maskAlpha = (maskData[x] & 0x000000FF)/ 255f;
float imageAlpha = ((imgData[x] >> 24) & 0x000000FF) / 255f;
//Image without alpha channel
int rgb = imgData[x] & 0x00FFFFFF;
//Multiplied alpha
int alpha = ((int) ((maskAlpha * imageAlpha) * 255)) << 24;
//Add alpha to image
imgData[x] = rgb | alpha;
}
image.setRGB(0, y, width, 1, imgData, 0, 1);
}
Actually, I've figured it out. This is probably not a fast way of doing it, but it works:
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
Color c = new Color(image.getRGB(x, y));
Color maskC = new Color(mask.getRGB(x, y));
Color maskedColor = new Color(c.getRed(), c.getGreen(), c.getBlue(),
maskC.getRed());
resultImg.setRGB(x, y, maskedColor.getRGB());
}
}

Categories

Resources