Blackberry Programming: Alter Bitmap Color on the Fly

While working on my current Blackberry game, I ran into a situation where I needed to change the color of of a bitmap. Specifically, I wanted to signify an object was “hit” by temporarily tinting it red – i.e. I wanted to keep the original bitmap color pattern, but wanted to increase the red portion of all the pixels so it had a red shade to it.

Example
Fighter - Before
Before
Fighter - After
After

ARGB Methods

Off the bat, I couldn’t find any method of directly altering the bitmap color using built in routines. There are a few routines for altering the alpha channel of bitmaps, but nothing for the color channels. After sifting through all the members of the Bitmap class, I came across the getARGB method (see link for details). This method will populate an int array with argb data, e.g. an int (4 bytes) per pixel signifying the alpha, red, green, and blue values (each value stored per byte). And sure enough, there is a setARGB method as well, for taking such an int array and applying it to a bitmap object.

The Strategy

With these methods at our disposal, it now becomes a matter of populating an array with ARGB data, then altering each int in the manner desired to achieve a specific effect. In this case, increasing the value of the RED byte (2nd byte) to increase the red tint of each pixel. However, the sky is the limit, as you could alter transparency for each pixel (alpha byte) and create a disintegration effect, average and equalize each of the color bytes to create greyscale, invert the colors, dim/brighten, etc. However, for now, lets stick to adding a red tint.

The Code

 public static Bitmap generateHitBitmap(Bitmap passBitmap) {
      Bitmap retBitmap;  // Altered, tinted bitmap being returned
      int[] argbData; // Array holding the ARGB data
      int redData;  // The red value of a pixel

      // Create a new, empty bitmap with the same dimensions
      retBitmap = new Bitmap(passBitmap.getType(), passBitmap.getWidth(), passBitmap.getHeight());

      // Prepare the ARGB array
      argbData = new int[passBitmap.getWidth() * passBitmap.getHeight()];
      
      // Grab the ARGB data
      passBitmap.getARGB(argbData, 0, passBitmap.getWidth(), 0, 0, passBitmap.getWidth(), passBitmap.getHeight());

      // Loop through each pixel in the array
      for (int lcv = 0 ; lcv < argbData.length ; lcv++) {
         // Get the red data by masking out the 2nd byte
         redData = (argbData[lcv] & 0x00FF0000) >> 16;

         // Increase the red value by 80 (maximum of 255)
         redData += 80; 
         if (redData > 255) redData = 255;

         // Shift it back to the right place, and set it back into array
         redData = redData << 16;
         argbData[lcv] = (argbData[lcv] & 0xFF00FFFF) + redData;
      }

      //  Set the return Bitmap to use this altered ARGB array 
      retBitmap.setARGB(argbData, 0, passBitmap.getWidth(), 0, 0, passBitmap.getWidth(), passBitmap.getHeight());

      return retBitmap;
   }

Note: There is some bitwise math going on here, and a few ways to accomplish this. I like to isolate out the value first and work with it separately, but you may feel more comfortable working directly with the array – either works.

Please feel free to share any cool effects you’ve achieved altering the ARGB data, or even constructing completely new ARGB data on the fly – I would love to see programmatically generated bitmaps!

5 Responses to Blackberry Programming: Alter Bitmap Color on the Fly

  1. Harish says:

    Thanks for the useful information!!! Great routine for writing games. Is this the same way to change the alpha of the bitmap or is there a simpler way?

  2. Toni says:

    Hi Harish – thanks for the kudos! Luckily, if you’re concerned with the alpha channel only, there is a method within the Graphics class, “SetGlobalAlpha”, that can achieve this. Here is a link to the specifications out of the 4.5 api (its been in there for a while)

    SetGlobalAlpha

    It basically takes an int 0-255 to set how transparent any further operations are going to be, so you can set this back and forth as you draw. However, since it operates on operations like DrawImage, its going to affect the whole image – if you need to just operate on part of a bitmap, you’d need to go the route outlined above. Good luck!

  3. Harish says:

    Thanks a ton again! ๐Ÿ™‚ I have other widgets like textbox, label, checkbox, button and images (sprites) that needs to be animated. So, I was looking for best ways to do it. Any suggestions? I used some concepts from your tutorial for rendering sprites using DRAW, but can’t do that for other widgets. So, how does combining these work? etc.

  4. Toni says:

    Are you saying you need to animate textboxes, buttons, etc? If so, you’ll need to create a custom layout manager, since the default ones tend to arrange fields in a block manner, with left/center/right alignment, but that’s about it.

    With a custom layout manager, you can override the sublayout method (which is called to arrange each field within the manager) to place fields exactly where you’d like them. You can override your fields as well to store individual coordinates per field.

    I create a custom layout manager with fields drawn to specific coordinates here. Hope that helps!

  5. Nagarjuna Metla says:

    Hi

    How to calculate RGB values for setting up custom color to bitmap like yellow,purple etc.

Leave a Reply

Your email address will not be published.