问题
is there any possiblity in J2ME to convert an image (loaded from a png file with alpha) to a new transparent grayscale image?
Until now I only got the rgb values, but not the alpha.
Thanks.
Edit: yes, it should be 32 bit grayscale.
回答1:
I found the solution and here is the code:
public Image getGrayScaleImage() {
int[] rgbData = new int[getWidth() * getHeight()];
image.getRGB(rgbData, 0, getWidth(), 0, 0, getWidth(), getHeight());
for (int x = 0; x < getWidth() * getHeight(); x++) {
rgbData[x] = getGrayScale(rgbData[x]);
}
Image grayImage = Image.createRGBImage(rgbData, getWidth(), getHeight(), true);
return grayImage;
}
private int getGrayScale(int c) {
int[] p = new int[4];
p[0] = (int) ((c & 0xFF000000) >>> 24); // Opacity level
p[1] = (int) ((c & 0x00FF0000) >>> 16); // Red level
p[2] = (int) ((c & 0x0000FF00) >>> 8); // Green level
p[3] = (int) (c & 0x000000FF); // Blue level
int nc = p[1] / 3 + p[2] / 3 + p[3] / 3;
// a little bit brighter
nc = nc / 2 + 127;
p[1] = nc;
p[2] = nc;
p[3] = nc;
int gc = (p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
return gc;
}
getRGB returns the color value that also includes the alpha channel. So I only had to change each value in the array and create an image from that.
I found a helpful document in the nokia forum: MIDP 2.0: Working with Pixels and drawRGB()
回答2:
Thanks for the code on converting to greyscale. However, I noticed that, on Nokia Series 40 devices, this code runs rather slowly.
There are 2 optimisations . The main one is to remove any object creation in getGrayScale(). Currently , an array object is created for every pixel . For an average ,say QVGA, display that is 76800 array objects created, which is a lot of garbage, and will probably invoke GC. Defining the int[4] as a field in the class removes this object creation. The trade off here is a small amount of additional RAM used for the class.
The second is to cache the width and height into getGrayScaleImage(). On some devices, the method calls to getWidth() and getHeight() will be repeatedly called without optimisations ( a JIT compiler will be OK but some interpreted devices not ). So , again for QVGA, the getWidth() and getHeight() will be called some >150000 between them.
In all, I found this modified version ran much quicker :-)
public Image getGrayScaleImage(Image screenshot) {
int width = getWidth();
int height = getHeight();
int screenSizeInPixels = (width * height);
int[] rgbData = new int[width * height];
image.getRGB(rgbData, 0, width, 0, 0, width, height);
for (int x = 0; x < screenSizeInPixels ; x++) {
rgbData[x] = getGrayScale(rgbData[x]);
}
Image grayImage = Image.createRGBImage(rgbData, width, height, true);
return grayImage;
}
static int[] p = new int[4];
private int getGrayScale(int c) {
p[0] = (int) ((c & 0xFF000000) >>> 24); // Opacity level
p[1] = (int) ((c & 0x00FF0000) >>> 16); // Red level
p[2] = (int) ((c & 0x0000FF00) >>> 8); // Green level
p[3] = (int) (c & 0x000000FF); // Blue level
int nc = p[1] / 3 + p[2] / 3 + p[3] / 3;
// a little bit brighter
nc = nc / 2 + 127;
p[1] = nc;
p[2] = nc;
p[3] = nc;
int gc = (p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
return gc;
}
( If you really don't want to use class data space, just replace the int[] with four separate local int variables which would live on the stack)
来源:https://stackoverflow.com/questions/2412054/j2me-convert-transparent-png-image-to-grayscale