Justin
Justin

Reputation: 35

Convert a Bitmap image to grayscale within BlackBerry J2Me

I have been trying to use the samples from here:
J2ME: Convert transparent PNG image to grayscale
and here:
http://www.java2s.com/Code/Java/Collections-Data-Structure/intarraytobytearray.htm

to convert an Bitmap image object to grayscale on the fly but I am running into issues when I am trying to re-encode my byte to an image and I get the following error/stack:

(Suspended (exception IllegalArgumentException))    
EncodedImage.createEncodedImage(byte[], int, int, String) line: 367 
EncodedImage.createEncodedImage(byte[], int, int) line: 279 
ScreenTemp.getGrayScaleImage(Bitmap) line: 404

Here is my code I am trying:

    Bitmap btemp = getGrayScaleImage(Bitmap.getBitmapResource("add.png"));
    BitmapField bftemp = new BitmapField(btemp, BitmapField.FOCUSABLE | BitmapField.FIELD_HCENTER | BitmapField.FIELD_VCENTER);
    add(bftemp);


    public Bitmap getGrayScaleImage(Bitmap image) {
    int width = image.getWidth();
    int height = image.getHeight();     
    int[] rgbData = new int[width * height];        
    image.getARGB(rgbData, 0, width, 0, 0, width, height);
    for (int x = 0; x < width*height ; x++) {
        rgbData[x] = getGrayScale(rgbData[x]);
    }
    byte[] b = int2byte(rgbData);
    final EncodedImage jpegPic = EncodedImage.createEncodedImage(b, 0, b.length);
    return jpegPic.getBitmap();
}
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;
}
private static byte[] int2byte(int[] src) {
    int srcLength = src.length;
    byte[]dst = new byte[srcLength << 2];

    for (int i=0; i<srcLength; i++) {
        int x = src[i];
        int j = i << 2;
        dst[j++] = (byte) ((x >>> 0) & 0xff);           
        dst[j++] = (byte) ((x >>> 8) & 0xff);
        dst[j++] = (byte) ((x >>> 16) & 0xff);
        dst[j++] = (byte) ((x >>> 24) & 0xff);
    }
    return dst;
}

Any help would be great!

Thanks, Justin

EDIT: Thanks to the below information I was able to fix this issue. Here is the code. You no longer need the int2byte and here is the updated the getGrayScaleImage method:

public Bitmap getGrayScaleImage(Bitmap image) {
    int width = image.getWidth();
    int height = image.getHeight();     
    int[] rgbData = new int[width * height];        
    image.getARGB(rgbData, 0, width, 0, 0, width, height);
    for (int x = 0; x < width*height ; x++) {
        rgbData[x] = getGrayScale(rgbData[x]);
    }
    byte[] b = int2byte(rgbData);
    Bitmap bit = new Bitmap(width, height);
    bit.setARGB(rgbData, 0, width, 0, 0, width, height);
    return bit;
}

Upvotes: 1

Views: 1063

Answers (2)

Vit Khudenko
Vit Khudenko

Reputation: 28418

To extend Scott W answer.

EncodedImage.createEncodedImage(byte[] data, int offset, int length) expects a byte array of a supported image type (TIFF, BMP, JPEG, GIF, WBMP or PNG). For instance, if you opened a JPEG image file, read the file bytes, then it would be possible to use the got bytes to create an EncodedImage (it would be JPEGEncodedImage actually).

So as Scott W says you should use Bitmap.setARGB() for the resulting byte array to have a Bitmap with converted data.

And then if you need to save the image as a JPEG file, you can use smth like this:

JPEGEncodedImage eImage = JPEGEncodedImage.encode(bitmap, 75);
byte[] fileData = eImage.getData();
// open a FileConnection and write the fileData

Upvotes: 2

Scott W
Scott W

Reputation: 9872

Quoting from the EncodedImage javadoc:

If the image format is not recognized, an IllegalArgumentException is thrown.

Why are you fiddling with EncodedImage? It seems like you ought to be able to just create a second Bitmap and use setARGB().

Upvotes: 4

Related Questions