1

为了尽量减少位图的内存使用,但仍然尽量提高它们的质量,我想问一个简单的问题:

有没有办法让我.png使用 API 检查给定的图像文件(文件)是否具有透明度,而不检查其中的每个像素?

如果图像没有任何透明度,最好使用仅使用 RGB 值的不同位图格式。

问题是 Android 也没有仅适用于 3 种颜色的格式。只有 RGB_565,他们说这会降低图像质量,应该启用抖动功能。

还有一种方法可以只读取 RGB 值并能够显示它们吗?

4

4 回答 4

2

对我来说bitmap.hasAlpha(),首先检查位图是否具有 alpha 值可以正常工作。之后,您必须遍历像素并创建第二个没有 alpha 的位图,我建议您这样做。

于 2014-02-02T12:00:13.790 回答
1

让我们开始一点题外话

问题是 android 也没有仅适用于 3 种颜色的格式。只有 RGB_565 ,他们说这会降低图像质量并且应该启用抖动功能。

这个问题的原因并不是真正的 Android 特定的。这是关于绘制图像时的性能。如果像素数据完全适合 1 个 32 位存储单元,您将获得最佳性能。

所以最明显的好像素格式是ARGB_8888正好使用 32 位的格式(24 表示颜色 8 表示 alpha)。绘图时,您无需执行任何操作,只需遍历图像数据,您读取的每个单元格都可以直接绘制。唯一的缺点是处理此类图像所需的内存,无论是当它们只是放在内存中还是在显示它们时,因为图形硬件必须传输更多数据。

第二个最佳选择是使用几个像素适合 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/ )


回到你真正的问题

有没有办法让我使用 API 检查给定的图像文件(png 文件)是否具有透明度,而不检查其中的每个像素?

我不知道。但是 JPEG 图像不支持 alpha,而 PNG 图像通常具有 alpha。在大多数情况下,您可以简单地滥用文件扩展名来使其正确。

但我建议您不要打扰所有这些,只需使用ARGB_8888和应用 Android 培训文档中关于有效显示位图的详细介绍的漂亮图像加载技术。

人们遇到内存问题的原因通常是他们在内存中加载的图像比他们当前显示的要多得多,或者他们使用无法在手机的小屏幕上显示的巨大图像。在我看来,添加良好的内存管理比使代码复杂化以降低图像质量更有意义。

于 2012-08-22T21:32:44.337 回答
1

有一种方法可以检查 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;
}

除此之外,我不知道这样的事情是否可能。

于 2015-07-09T08:11:03.733 回答
0

我发现下一个链接可能有助于检查 png 文件是否具有透明度。可悲的是,它仅适用于 png 文件。其余文件(如 webP、bmp、...)需要有不同的 parser 。

链接:

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

http://www.java-gaming.org/index.php/topic,24202

于 2012-08-24T10:36:30.130 回答