【问题标题】:Confused about PixelFormat对 PixelFormat 感到困惑
【发布时间】:2023-03-08 07:33:01
【问题描述】:

我对 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 (但没有证据证明这种说法)。那么我怎样才能弄清楚设备屏幕的 real 格式呢?我还发现了一台Android 2.2的中文设备,也有PixelFormat5,但真正的格式是4(就像我的摩托罗拉)。

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

更新:

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

【问题讨论】:

    标签: android pixelformat


    【解决方案1】:

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

    那么,为什么getPixelFormat() 不返回格式为 3(或 RGBA 之类的 4) 每像素字节数?是显卡驱动问题还是什么?我可以设置 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 定义匹配的值,因此类似于摩托罗拉板上链接讨论中给出的值。

    【讨论】:

    • 感谢您的回答 - 我奖励了您。
    • @Astor:很高兴为您提供帮助。你有没有尝试过我的任何建议?我有兴趣看看实际返回了哪些数据。
    • getPixelFormatInfo 将其结果放入一个 PixelFormat 对象中,该对象有 2 个字段:bitsPerPixel (32) 和 bytesPerPixel (4)。
    【解决方案2】:

    根据motodev论坛this的帖子,返回值5对应RGBA_8888。该线程指出 PixelFormat 的文档不完整且已过时,并且为它归档了 links to a bug但是,该错误的链接现在返回 404。

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

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

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

    【讨论】:

    • 5 代表 RGBA_8888 是不正确的(甚至没有来自那个人的证明链接)。实际上,格式 4 (RGB_565) 在 ICS 或 Jelly Bean 上运行良好(与 Android 2.3 相同)。如果是 RGBA_8888,我可能会遇到颜色问题。
    • 正如我在第二点中所说的,我也找不到他声称的证据。但是,线程上的其他人运行了一些测试,表明它是 RGBX_8888 或 RGBA_8888。
    【解决方案3】:

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

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

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

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

    有趣的是,对 Galaxy Nexus 和 Nexus 7 的描述并没有太多共同之处。 GNN7

    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;
    

    【讨论】:

    • 感谢您的回复 (+1),但对我一点帮助都没有 :(
    • 您想了解什么?除了知道这个细节之外,这对其他任何事情都有影响吗?
    • 格式 5 代表什么?如何将视图的格式设置为设备屏幕的真实格式?
    • 嗯..对。但是,如果您的目标设备具有超过 2 种不同的像素格式,那又有什么意义呢?大概就是这样。至少只要屏幕更加规范化,就会发生这种情况。不幸的是,我想我们需要等待:S。要了解更多信息,我们应该进入被调用的本机方法,看看该决定 (getPixelFormat) 是如何做出的。
    猜你喜欢
    • 1970-01-01
    • 2019-09-13
    • 2012-07-22
    • 2013-05-13
    • 2020-04-16
    • 2019-08-04
    • 2019-12-30
    • 2022-01-20
    • 2016-09-05
    相关资源
    最近更新 更多