14

我对 Android 上的PixelFormat感到困惑。

我的设备是摩托罗拉 Defy。

我有两个问题:

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

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

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

那么,为什么getPixelFormat()不返回每像素 3 个(或 4 个如 RGBA)字节的格式呢?是显卡驱动问题还是什么?我可以设置PixelFormatRGBA_8888(或模拟)吗?

  • 在 Android 4.1(自定义 rom)上,getPixelFormat()返回5。但是这个值是无证的。它代表什么?实际上,在这种情况下效果与 constant 相同4。但是从这个讨论中我发现5代表RGBA_8888(但没有证据证明这个说法)。那么如何才能确定设备屏幕的真实格式呢?我还发现了一台 Android 2.2 上的中文设备,它也有PixelFormat 5,但真正的格式是4(作为我的摩托罗拉)。

我用谷歌搜索了这些问题,一无所获。我唯一发现的是nexus 7 也有 5 格式

更新:

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

4

3 回答 3

8

我将在这次讨论中加两分钱,尽管我应该提前承认,我无法为您的所有问题找到确凿的答案。

那么,为什么getPixelFormat()不返回每像素 3 个(或 4 个如 RGBA)字节的格式呢?是显卡驱动问题还是什么?我可以设置 PixelFormatRGBA_8888(或模拟)吗?

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

附带说明:实际上我之前在 Android 中遇到过未对齐的常量定义,尽管我目前不记得确切的位置......

只是为了确认一下,可能值得在运行时打印出像素格式的详细信息。如果确实定义了一个使用 JavaPixelFormat值但不匹配的本机常量,那么您可能会以这种方式显示“真实”格式。使用该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)
};

资料来源:(hardware.h第 121-148 行)

如果您将这些值与 中定义的值进行比较PixelFormat.java,您会发现它们相加得非常好(应该如此)。也说明了神秘的含义5,即BGRA_8888;RGBA_8888 的变体。

顺便说一句,您可能想尝试使用上述getPixelFormatInfo(...)方法通过5作为标识符传入来确定此整数值的像素格式详细信息。看看会返回什么会很有趣。我希望它显示与 BGRA_8888 定义匹配的值,因此类似于摩托罗拉板上链接讨论中给出的值。

于 2012-08-22T08:00:50.993 回答
4

根据motodev 论坛上的这个帖子,返回值 5 对应于 RGBA_8888 该线程指出 PixelFormat 的文档不完整且已过时,并链接到为其提交的错误。但是,该错误的链接现在返回 404。

此外,我似乎在PixelFormat 源代码(4.1) 中找不到任何支持该声明的东西,因为那里 RGBA_8888 被赋值为 1。

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

编辑:我给谷歌员工发了一封电子邮件,他告诉我 5 对应于 BGRA_8888,如 MH 的回答和我之前链接的摩托罗拉论坛帖子所示。他建议我为文档问题提交一个错误,我已经这样做了。请为错误报告加注星标,以便尽快采取行动。

于 2012-08-16T14:54:32.607 回答
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;
于 2012-08-18T11:20:56.610 回答