对PixelFormat感到困惑

时间:2012-08-14 09:46:56

标签: android pixelformat

我对Android上的PixelFormat感到困惑。

我的设备是摩托罗拉Defy。

我有两个问题:

  • 在Android 2.3 getWindowManager().getDefaultDisplay().getPixelFormat()上返回 4 代表RGB_565。据我所知,我的设备有 16M 颜色,这意味着每个像素3个(或4个带alpha通道)字节:
                2^(8*3) = 2^24 = 16M

但是RGB_565格式每个像素有2个字节(16位),代表 65K 颜色:

                2^(8*2) = 2^16 = 65K

那么,为什么getPixelFormat()不返回每像素3个(或4个RGBA)字节的格式?它是否显示驱动程序问题?我可以将PixelFormat设置为RGBA_8888(或模拟)吗?

  • 在Android 4.1(自定义ROM)上,getPixelFormat()返回 5 。但是这个价值没有记载。它代表什么?实际上,在这种情况下,效果与常数4相同。但是从this discussion我发现 5 代表RGBA_8888(但没有证据证明该声明)。那么如何才能找出设备屏幕的真实格式?另外我在Android 2.2上发现了一个中文设备,也有PixelFormat 5 ,但实际格式是 4 (就像我的摩托罗拉一样)。

我搜索了这些问题,一无所获。我发现的唯一事情是nexus 7 also has 5 format

更新

我找到了方法getWindow().setFormat(),但它实际上并没有改变主像素格式。

3 个答案:

答案 0 :(得分:8)

我会在讨论中加上我的两分钱,但我应该提前承认我找不到你所有问题的确凿答案。

  

那么,为什么getPixelFormat()不会返回格式为3(或者像RGBA一样)   每像素字节数?它是否显示驱动程序问题?我可以订   PixelFormatRGBA_8888(或模拟)?

我对你在这里问的内容感到有些困惑。 getPixelFormat()的返回值只是一个整数,它提供了一种识别活动像素格式的方法;它并不意味着代表压缩成数字的任何数据(例如与MeasureSpec一样)。不幸的是,我没有解释为什么返回的不同于你的预期。我最好的猜测是由于操作系统的决定,因为从硬件的角度来看似乎没有限制,或者,本机实现中定义的常量与Java中的常量不匹配。如果摩托罗拉搞砸了定义,那么你以4作为像素格式返回的事实并不一定意味着它真的是RGB_565。

旁注:在Android之前我实际上遇到了错位常量定义,虽然我现在无法回想起究竟在哪里......

要确认,在运行时打印像素格式细节可能是值得的。如果确实定义了使用Java PixelFormat值但不匹配的本机常量,则可以通过这种方式显示“真实”格式。使用getPixelFormatInfo(int format, PixelFormat info)方法,只需委派从本机实现中检索实际值。

  

在Android 4.1(自定义ROM)上,getPixelFormat()返回5.但是这样   价值没有记录。它代表什么?

如前所述,有时在本机代码中定义的常量与Java中的常量不匹配,或者根本没有定义。这可能就是这种情况。你需要做一些挖掘来找出它代表什么,但它相当简单:

/**
 * pixel format definitions
 */

enum {
    HAL_PIXEL_FORMAT_RGBA_8888          = 1,
    HAL_PIXEL_FORMAT_RGBX_8888          = 2,
    HAL_PIXEL_FORMAT_RGB_888            = 3,
    HAL_PIXEL_FORMAT_RGB_565            = 4,
    HAL_PIXEL_FORMAT_BGRA_8888          = 5,
    HAL_PIXEL_FORMAT_RGBA_5551          = 6,
    HAL_PIXEL_FORMAT_RGBA_4444          = 7,
    /* 0x8 - 0xF range unavailable */
    HAL_PIXEL_FORMAT_YCbCr_422_SP       = 0x10,     // NV16
    HAL_PIXEL_FORMAT_YCrCb_420_SP       = 0x11,     // NV21 (_adreno)
    HAL_PIXEL_FORMAT_YCbCr_422_P        = 0x12,     // IYUV
    HAL_PIXEL_FORMAT_YCbCr_420_P        = 0x13,     // YUV9
    HAL_PIXEL_FORMAT_YCbCr_422_I        = 0x14,     // YUY2 (_adreno)
    /* 0x15 reserved */
    HAL_PIXEL_FORMAT_CbYCrY_422_I       = 0x16,     // UYVY (_adreno)
    /* 0x17 reserved */
    /* 0x18 - 0x1F range unavailable */
    HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x20,     // NV12_adreno_tiled
    HAL_PIXEL_FORMAT_YCbCr_420_SP       = 0x21,     // NV12
    HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED = 0x22,     // NV21_adreno_tiled
    HAL_PIXEL_FORMAT_YCrCb_422_SP       = 0x23,     // NV61
    HAL_PIXEL_FORMAT_YCrCb_422_P        = 0x24,     // YV12 (_adreno)
};

Source: hardware.h (lines 121-148)

如果你要将这些值与PixelFormat.java中定义的值进行比较,你会发现它们相当不错(正如他们应该的那样)。它还显示了神秘5的含义,即BGRA_8888; RGBA_8888的变种。

顺便说一句,您可能希望尝试使用前面提到的getPixelFormatInfo(...)方法确定此整数值的像素格式详细信息,方法是将5作为标识符传递。看到返回的内容会很有趣。我希望它能显示与BGRA_8888定义相匹配的值,因此类似于摩托罗拉电路板上链接讨论中给出的值。

答案 1 :(得分:4)

根据motodev论坛上的this帖子,返回值5对应于RGBA_8888。该主题声明PixelFormat的文档不完整且过时,并且已为其提交了links to a bug但是,该bug的链接现在返回404。

此外,我似乎无法在PixelFormat source code(4.1)中找到支持该声明的任何内容,因为在那里RGBA_8888被赋值为1.

我的猜测是这个值特定于摩托罗拉和其他一些设备,因为我在Nexus 7和Galaxy Nexus上看到相同的输出。

编辑:我通过电子邮件向谷歌员工发送了关于此事的电子邮件,他告诉我,5对应于BGRA_8888,正如MH的回答和我之前链接的摩托罗拉论坛帖子所示。他建议我为文档问题which I have done提交一个bug。请为错误报告加注星标,以便尽快采取行动。

答案 2 :(得分:3)

RGBA_8888对应1,如下附件所示。

如果你转到与mPixelFormat相关的代码,你会发现以下内容。

// Following fields are initialized from native code
private int mPixelFormat;

这意味着由于某种原因,由于操作系统的决定而不是硬件功能,您的设备被视为RGB_565。 实际上,这让我感到很好奇。

有趣的是,对Galaxy Nexus和Nexus 7的描述并不太多。 GN N7

public static final int RGBA_8888   = 1;
public static final int RGBX_8888   = 2;
public static final int RGB_888     = 3;
public static final int RGB_565     = 4;

@Deprecated
public static final int RGBA_5551   = 6;
@Deprecated
public static final int RGBA_4444   = 7;
public static final int A_8         = 8;
public static final int L_8         = 9;
@Deprecated
public static final int LA_88       = 0xA;
@Deprecated
public static final int RGB_332     = 0xB;