我对Android上的PixelFormat感到困惑。
我的设备是摩托罗拉Defy。
我有两个问题:
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(或模拟)吗?
getPixelFormat()
返回 5 。但是这个价值没有记载。它代表什么?实际上,在这种情况下,效果与常数4
相同。但是从this discussion我发现 5 代表RGBA_8888
(但没有证据证明该声明)。那么如何才能找出设备屏幕的真实格式?另外我在Android 2.2上发现了一个中文设备,也有PixelFormat
5 ,但实际格式是 4 (就像我的摩托罗拉一样)。我搜索了这些问题,一无所获。我发现的唯一事情是nexus 7 also has 5 format。
更新
我找到了方法getWindow().setFormat()
,但它实际上并没有改变主像素格式。
答案 0 :(得分:8)
我会在讨论中加上我的两分钱,但我应该提前承认我找不到你所有问题的确凿答案。
那么,为什么
getPixelFormat()
不会返回格式为3(或者像RGBA一样) 每像素字节数?它是否显示驱动程序问题?我可以订PixelFormat
到RGBA_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;