4

My Android Tide app displays a nautical chart from a .KAP file. This file format uses a four bit palettized display system, only 10 colors are used. My app decodes the file format into an array of four bit colors. It displays a portion of this array onto the display as follows:

for (displayLineNum  = 1; displayLineNum < displayHeight; displayLineNum++)
{   for (displayDotNum = 1; displayDotNum < displayWidth; displayDotNum++)
   {  color = colors [lineIndex-1][dotIndex-1];  
      switch (color)
      {   case 1:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color1); break;
          case 2:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color2); break;
          case 3:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color3); break;
          case 4:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color4); break;
          case 5:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color5); break;
          case 6:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color6); break;
          case 7:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color7); break;
          case 8:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color8); break;
          case 9:  displayCanvas.drawPoint(displayDotNum, displayLineNum, color9); break;
          case 10: displayCanvas.drawPoint(displayDotNum, displayLineNum, color10); break;
          default: displayCanvas.drawPoint(displayDotNum, displayLineNum, color1); break;                    
      }
   }
}
display_area.setImageBitmap(displayBitmap);

There are 10 paint colors pre set with the RGB codes necessary for display. But each pixel has to be drawn individually with the displayCanvas.drawPoint function. This works but it is DOG SLOW. I would rather pre set the palette codes on the other side of the display call, and pass in the palette values instead. This would run a lot faster but I can't find a way to do this with the display calls available. There are Android functions to evaluate an image to get a palette for it, etc but I cant see how to efficiently display a palettized image. Each pixel is getting blown up for a four bit pixel code to a sixteen bit RGB565 code in order to pass in a normal bitmap. How else could I do this, thank you.

Olivier
  • 13,283
  • 1
  • 8
  • 24
user1644002
  • 3,211
  • 3
  • 19
  • 21
  • 1
    In addition to what @Olivier has written, you should look at parallelizing the operation and perhaps even moving it to C code if you are trying to make it 'real-time' image generation. Author of [Android Java for loop uses less CPU and is slower than C++ for loop](https://stackoverflow.com/q/68500753/295004) links to his blog which is a interesting read. – Morrison Chang Dec 21 '21 at 06:11
  • thanks Morrison, Yes I am trying to make very fluid pan and zoom, equivalent to the built in functions when you load in a file to display, but the huge size is making me do that stuff myself. I will take a look at your reference thanks again, Lawrence Freytag – user1644002 Dec 21 '21 at 19:05
  • If you are trying to do fluid pan and zoom, just making sure you are aware of [Google Maps SDK TileProvider](https://stackoverflow.com/q/14784841/295004) or other deep zoom type library: https://github.com/davemorrissey/subsampling-scale-image-view – Morrison Chang Dec 21 '21 at 20:41

1 Answers1

3

To define the pixels of a Bitmap, you shouldn't use a Canvas because it adds an extra layer and is inefficient. You should deal with the Bitmap object directly. There are two ways to do that.

Calling setPixel

The setPixel() method allows to set the color of a pixel.

Example:

Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
for(int x = 0; x < width; x++)
{
    for(int y = 0; y < height; y++)
        bm.setPixel(x, y, Color.BLUE);
}

Calling createBitmap

To avoid the overhead of calling setPixel() a large number of times, you can build an array with the pixel colors and pass it directly to createBitmap(). This is probably the most efficient way.

Example:

int length = width * height;
int[] colors = new int[length];
for(int i = 0; i < length; i++)
    colors[i] = Color.BLUE;
Bitmap bm = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
Olivier
  • 13,283
  • 1
  • 8
  • 24
  • thank you, I will try #1 immediately, I have a question about #2. My colors are four bit palette codes, while the pixels are RGB 565 constructs. How is this conversion handled in method #2. thanks again – user1644002 Dec 19 '21 at 20:27
  • #1 is a lot faster, when I presave the colors as ints. – user1644002 Dec 19 '21 at 22:31
  • eg int color1 = Color.rgb(0,0,0); – user1644002 Dec 19 '21 at 22:32
  • @user1644002 Why do you need RGB_565? I would use ARGB_8888 to avoid unnecessary conversions. The only advantage of RGB_565 is reduced memory consumption. – Olivier Dec 20 '21 at 08:58
  • Oliver the charts I am using are high resolution. A smaller one is about 16000 lines by 8500 dots. Their pixel data, however, is four bit pallet. 10 colors. A RGB565 pixel works fine for that. My ideal solution for this is to somehow place the palette on the system side of my calls. I would like to draw using the four bit codes if possible that would be the most efficient. – user1644002 Dec 20 '21 at 15:34
  • @user1644002 A `Bitmap` has no concept of palette. – Olivier Dec 20 '21 at 17:35
  • Well, I can load .png files for display. and .png supports images with a palette included inside the file. I am hoping somewhere inside android is the ability to access this type of functionality inside drawn images. – user1644002 Dec 20 '21 at 19:58
  • Olivier, I think the second method will work, a few things slowing me down. I cannot get the constructor to accept 16 bit pixels, there might be some way. And it is requiring me to output the exact number of pixels per line and lines, or else the display gets garbled. I will get this going, thanks very much, and compare the two methods. It seems about as fast as the first method. – user1644002 Dec 21 '21 at 19:02
  • I can't get the second method to work, it creates an unrecognizable display. I am using the first recommendation, which speeds up the display considerably. That is, use setPixel() operating directly on the bitmap. – user1644002 Dec 24 '21 at 11:59
  • @user1644002 Does the simple test with a blue bitmap (as shown in my answer) work? – Olivier Dec 24 '21 at 12:12
  • I didn't try it as written, I placed my rows and columns into a combined single array as shown in your example. The display came up but it was garbled. Unless the single array is set up exactly with each row and column completely full it doesn't display right. It also won't support rgb 565 pixels. – user1644002 Dec 26 '21 at 19:34