如何在 Android 图形中高效创建一个调色板颜色的显示位图?

4

我的Android Tide应用程序显示从.KAP文件中获取的海图。这种文件格式使用四位调色板显示系统,仅使用10种颜色。我的应用程序将该文件格式解码为一个四位颜色数组,并按以下方式在显示器上显示其中一部分:

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);

有10种预设的颜色,具有显示所需的RGB代码。但每个像素都必须使用displayCanvas.drawPoint函数单独绘制。这样虽然可以工作,但速度非常缓慢。 我宁愿在调用显示方法的另一侧预先设置调色板代码,并传入调色板值。这样能够更快地运行,但我找不到使用可用显示调用实现此功能的方法。 虽然可以使用Android函数来评估图像并获取其调色板等信息,但我不知道如何有效地显示调色板图像。每个像素都会从4位像素代码放大到16位RGB565代码,以便传递普通位图。还有其他什么方法可以实现这个,谢谢。


1
除了@Olivier所写的内容外,如果您尝试进行“实时”图像生成,还应该考虑并行化操作甚至将其移动到C代码中。[Android Java for loop uses less CPU and is slower than C++ for loop](https://stackoverflow.com/q/68500753/295004)的作者链接到他的博客,这是一篇有趣的阅读材料。 - Morrison Chang
谢谢Morrison,是的,我正在尝试制作非常流畅的平移和缩放效果,相当于加载文件以显示时内置的功能,但巨大的大小使我不得不自己处理这些事情。我会查看你提供的参考资料,再次感谢,Lawrence Freytag - user1644002
如果您正在尝试进行流畅的平移和缩放,请确保您了解Google Maps SDK TileProvider或其他深度缩放类型库:https://github.com/davemorrissey/subsampling-scale-image-view - Morrison Chang
1个回答

3

为了定义位图的像素,不应使用Canvas,因为它会添加额外的层并且效率低下。你应该直接处理Bitmap对象。有两种方法可以做到这一点。

调用setPixel方法

setPixel()方法允许设置像素的颜色。

例如:

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);
}

调用 createBitmap

为了避免大量调用 setPixel() 带来的开销,您可以构建一个包含像素颜色的数组,并将其直接传递给createBitmap()。这可能是最有效的方法。

示例:

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);

谢谢,我会立即尝试#1。我对#2有一个问题。我的颜色是四位调色板代码,而像素是RGB 565结构。在方法#2中如何处理此转换?再次感谢。 - user1644002
当我将颜色预先保存为整数时,#1的速度要快得多。 - user1644002
int color1 = Color.rgb(0,0,0); int color1 = Color.rgb(0,0,0); - user1644002
好的,我可以加载.png文件进行显示。而且.png支持在文件内包含调色板的图像。我希望在Android中能够访问绘制图像中这种类型的功能。 - user1644002
Olivier,我认为第二种方法会起作用,有一些事情在拖慢我的速度。我无法让构造函数接受16位像素,可能有某种方法。而且它要求我输出每行和每列的确切像素数,否则显示会变得混乱。我会让它运转起来,非常感谢,并比较这两种方法。它看起来与第一种方法差不多快。 - user1644002
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接