Changing colors of an image in real time

By Felipe Coury

Recently I needed the ability to change colors of a picture in real-time. I was developing a game where I needed to paint the player costumes many times within the game. I have researched on the internet and didn’t find any J2ME code available.

I digged all around for an algorithm to do that and found a way to do it.

After reading some codes that did the trick in other languages, I finally figured out how to create a routine to change the colors. The basics behind it is the following:

The MIDP 2.0 API has the ability to extract an array of RBG data from an image by calling the Image’s getRGB() method. This method takes the following parameters:

getRGB(int[] rgbData, int offset, int scanlength, int x, int y, int width, int height)

Where:

rgbData – an array of integers in which the ARGB pixel data is stored
offset – the index into the array where the first ARGB value is stored
scanlength – the relative offset in the array between corresponding pixels in consecutive rows of the region
x – the x-coordinate of the upper left corner of the region
y – the y-coordinate of the upper left corner of the region
width – the width of the region
height – the height of the region

So, to get all image data you need:

int[] raw = new int[image.getWidth() * image.getHeight()];
image.getRGB(raw, 0, image.getWidth(), 0, 0, image.getWidth(), image.getHeight());

What you have now is an array of integers representing each pixel of the image in the AARRGGBB format where RR is red, GG is green, BB is blue and the leading AA is alpha). The alpha attibute defines the opacity of that particular pixel and 00 means completly transparent and FF (255) means completly opaque (solid).

So, to change colors we need to change all pixels that matches an RGB value regardless of what the alpha byte is. To do that we need to “mask” the pixel value with the “&” operator. The first mask we need is to extract (and later on preserve) the alpha value. This mask is 0xff000000 and, as you probably noticed, the ff matches the AA position on the integer (it is the leftmost byte on the integer).

Once we have the alpha value, we need to mask the integer again to extract the RGB color. The mask to do that is the opposite of the previous mask: 0×00ffffff. This mask drops the leftmost byte and extracts the desired RGB value.

Now that you have the alpha value and the RGB value, all you need to do is iterate throughout the pixels array and match the RGB color with the one you are replacing. This step is illustrated on the following snippet:

        // check each color to replace
        for (int j = 0; j < maskedOldColor.length; j++) {
            if (currentMaskedPixel == maskedOldColor[j]) {
                raw[i] = (currentPixel & alphaOnlyBitmask) | maskedNewColor[j];
                break;
            }
        }

Well, I think you got the idea. Anyway, this is my first post and I’d like to know what you think about it so please: comment it!

Regards,

Felipe.

14 Responses to “Changing colors of an image in real time”

  1. psm Says:

    Hi, This seems to be very interesting.. but I m not able to understand the code snippet u have written here. Can u please send me the code with example? It would be very nice of you if you could send.

    Thanks in advance,
    Priya

  2. Felipe Coury Says:

    psm,

    Just e-mailed you what you requested. Best regards!

    Felipe.

  3. abhay Says:

    Hi,

    How can i find RGB value of any image in MIDP1.0,where u have no
    getRGB() method.Can you give some idea how to find RGB value for MIDP1.0.

    Thanks

  4. Felipe Coury Says:

    abhay,

    Thanks for visiting my blog.

    Unfortunatelly I have no ideas on how you could mimic getRGB() in
    MIDP1. I’ll try to search for something and if I found anything, I’ll
    let you know ok?

    Take care,

    Felipe.

  5. mmenchu Says:

    I used your approach in a small j2me client recently that tried to send and image of what the user had drawn on a canvas with a stylus. Unfortunately the phone I worked with, was very limited (very few JSRs) and so I eneded up reading the RGB values off each pixel on the canvas and sent it over sockets to the server driving the interactive screen where it’d be displayed. I ended up sending a string like this RR,GG,BB,RR,GG,BB … so the image was painted pixel by pixel on arrival… very inefficient i’m sure but it saved my day. I found your article very helpful … thanks for sharing this.

  6. Felipe Coury Says:

    Thanks for your comment! Those kinds of feedback is what
    get me going, really. I appreciated you had used my article and it was
    worth for you.

  7. Paranoid Android Says:

    I think there’s an issue in your solution.
    If i try to mask a value like red (0xff000000) everything works fine.

    But if i try to mask another value, to extract the alpha value, i get a wrong value.

    For example:

    int p=0xa2e3ffff; // ARGB value of a pixel
    int c2=p & 0×00FFFFFF; // extracting color…OK
    int a= p & 0xff000000;//extracting alpha…wrong :(

    a is actually: ffffffffa2000000 instead of a2000000

    What’s wrong with it?

  8. Arvind Says:

    Hi,
    thanks for the article,
    can you mail me the full code,
    thanks in advance,
    regards,
    arvind

  9. Gajanan Says:

    Hi,
    I have read your article .
    It is very good.
    I am developing application in which i am sending the RGB values of pixel from server (P.C.) to j2me.
    But performance is very slow.
    Can You give me your full code and suggestions for my application .
    Thank You.

    mail : gtemgire@yahoo.co.in

  10. kanwar Says:

    Hi Felipe,
    Thanks for this nice article, very nice.
    One thing i am into right now is , i need to convert an image ( color or black& white) into golden and silver image, i hope u r getting what i am looking for.

    I will really appricieate if you can let me know how that can be achived.

    Thanks in advance,
    Kanwar

  11. rupal Says:

    I wl b very thankful 3 u if u provide the full program for this .

  12. Shwarup Says:

    Hi,

    The above example is working fine in simulator. if i install it in real device Nokia 6600 the getRGB() method is not working for large .png image like size (88X57) but it is working fine for small image.

    Pls give me some idea how to use getRGB() for large image.

  13. mosa Says:

    Thanks you ,i am looking solution for this problem from long time but i can not find such approch ,i hope you can email me the code example please.

  14. selasie Says:

    hi Felipe if it wouldn’t be too much to ask i need this exact thing for a project am currently working. Trust me i have searched for quite for this. It’s a nice thing you putting this out.

Leave a Reply