为了尽量减少位图的内存使用,但仍然试图最大化它们的质量,我想问一个简单的问题:
有没有办法让我检查一个给定的图像文件(.png
文件)是否具有使用API的透明度,而不检查其中的每个像素?
如果图像没有任何透明度,最好使用仅使用RGB值的不同位图格式。
问题是Android也没有只有3种颜色的格式。只有RGB_565,他们说这会降低图像的质量,并且应该启用抖动功能。
是否还有一种方法可以只读取RGB值并显示它们?
答案 0 :(得分:2)
对我来说,bitmap.hasAlpha()
可以正常检查位图是否具有alpha值。之后你必须运行像素并创建第二个位图,没有我建议的alpha。
答案 1 :(得分:1)
让我们开始有点偏离主题
问题是android也没有只有3种颜色的格式。只有RGB_565,他们说这会降低图像的质量,并且应该启用抖动功能。
该问题的原因并非真正针对Android。它是关于绘制图像时的性能。如果像素数据恰好适合1 32位存储单元,则可获得最佳性能。
所以最明显的良好像素格式是ARGB_8888
格式,它使用的确是32位(24代表alpha的颜色8)。在绘制时,您不需要做任何事情,只需循环覆盖图像数据,您可以直接绘制您读取的每个单元格。唯一的缺点是使用这些图像所需的内存,无论是当它们只是坐在内存中还是在显示它们时,因为图形硬件必须传输更多数据。
第二个最佳选择是使用一种格式,其中几个像素适合1个单元格。在32位中使用2个像素,每个像素剩下16位,使用16位的格式之一是565格式。 5位红色,6位绿色,5位蓝色。在绘制它时,您仍然可以单独处理存储器单元,您所要做的就是将1个单元分成几部分。由于图像所需的内存较小,因此绘图有时甚至比使用32位颜色更快。因为在Android内存的开头是一个更大的问题,他们选择这种格式作为默认值。
最糟糕的格式是那些像素不适合这些细胞的格式。如果您只使用3种颜色,则可获得24位,而需要在4种情况中的3种中分配2种颜色。例如,第二像素将使用来自第一单元和第二单元的剩余8位。下一个单元格的前16位。使用24位颜色所需的额外工作是如此之大,以至于不使用它。在绘制图像时,你通常会在某些时候使用alpha,如果不是,你只需使用32位但忽略alpha位。
因此16位方法看起来很丑陋24位方法没有意义。由于Android的内存限制并不像以前那么紧,硬件变得更快,Android已将其默认设置为32位(在http://www.curious-creature.org/2010/12/08/bitmap-quality-banding-and-dithering/更详细解释)
回到你真正的问题
有没有办法让我检查一个给定的图像文件(png文件)是否具有使用API的透明度,而不检查其中的每个像素?
我不知道。但JPEG图像不支持alpha和PNG图像通常具有alpha。在大多数情况下,您可以简单地滥用文件扩展名以使其正确。
但我建议你不要为此烦恼,只需使用ARGB_8888
并应用Android培训文档中详细介绍的有关Displaying Bitmaps Efficiently的精彩图片加载技术。
人们遇到内存问题的原因通常是他们在内存中加载的图像比当前显示的图像多,或者他们使用无法在手机的小屏幕上显示的巨型图像。在我看来,添加良好的内存管理比使代码复杂化降低图像质量更有意义。
答案 2 :(得分:0)
我找到了下一个可能有助于检查png文件是否具有透明度的链接。遗憾的是,它只是png文件的解决方案。其余的文件(如webP,bmp,...)需要有不同的解析器。
链接:
http://www.java2s.com/Code/Java/2D-Graphics-GUI/PNGDecoder.htm
http://hg.l33tlabs.org/twl/file/tip/src/de/matthiasmann/twl/utils/PNGDecoder.java
答案 3 :(得分:0)
有一种方法可以检查PNG文件是否具有透明度,或者至少是否支持它:
public final static int COLOR_GREY = 0;
public final static int COLOR_TRUE = 2;
public final static int COLOR_INDEX = 3;
public final static int COLOR_GREY_ALPHA = 4;
public final static int COLOR_TRUE_ALPHA = 6;
private final static int DECODE_BUFFER_SIZE = 16 * 1024;
private final static int HEADER_DECODE_BUFFER_SIZE = 1024;
/** given an inputStream of a png file , returns true iff found that it has transparency (in its header) */
private static boolean isPngInputStreamContainTransparency(final InputStream pngInputStream) {
try {
// skip: png signature,header chunk declaration,width,height,bitDepth :
pngInputStream.skip(12 + 4 + 4 + 4 + 1);
final byte colorType = (byte) pngInputStream.read();
switch (colorType) {
case COLOR_GREY_ALPHA:
case COLOR_TRUE_ALPHA:
return true;
case COLOR_INDEX:
case COLOR_GREY:
case COLOR_TRUE:
return false;
}
return true;
} catch (final Exception e) {
}
return false;
}
除此之外,我不知道这样的事情是否可能。