image - 为什么您看到内存中加载的图像大小(在libgdx中)占用了您自己的更多照片

标签 image memory bitmap libgdx

我没有使用2048 x 2048和437kb的大小进行拍摄。但是,当它加载libgdx时,我的内存急剧增加(4mb)。似乎在一般的opengl文件中,类型和压缩不是必需的,而仅仅是在内存中看到位图。

问题在于,一次资产加载程序的数量无误退出时,许多图像都在Android中。

我的游戏具有战略意义,包括墙纸和建筑物以及许多角色。同时根据现场需要,没有交叉装载的可能性。 (像部落冲突的游戏)。

现在的问题是我有多少东西,我将图像加载到内存中以在适用于低内存的Android手机上播放。

最佳答案

这是因为OpenGL以未压缩的图片格式存储图像。可以使用S3TC_DXT纹理压缩算法来压缩内存。要启用它,您只需要在glTexImage2D调用中指定纹理压缩算法即可。

glTexImage2D(GL_TEXTURE2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, width, height, 0, externalFormat, GL_BYTE);

您还可以检查纹理是否被压缩调用:
int iFlag;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &iFlag);

或通过调用以下命令加载已压缩的DDS纹理:
void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat,
                        GLsizei width, GLsizei height,
                        GLint border, GLsizei imageSize, void *data);

下面提供了有关S3纹理压缩(S3TC)的更多信息(摘自https://www.opengl.org/wiki/S3_Texture_Compression):

S3TC是一种压缩图像以用作纹理的技术。像JPEG和PNG这样的标准图像压缩技术可以实现比S3TC更高的压缩率。但是,S3TC被设计为在高性能硬件中实现。 JPEG和PNG一次全部解压缩图像,而S3TC允许独立地解压缩图像的特定部分。

S3TC是基于块的格式。图像分为4x4块。对于大小不是4的倍数的非2的幂的图像,将4x4块的其他颜色视为黑色。每个4x4块彼此独立,因此可以独立进行解压缩。

OpenGL接受3种形式的S3TC。这些格式以以下格式的旧Direct3D名称命名:DXT1,DXT3和DXT5。

DXT1格式

DXT1压缩的图像是RGB图像格式。这样,任何颜色的alpha都假定为1。每个4x4块占用64位数据,因此与24位RGB格式相比,它提供6:1压缩。您可以使用GL_COMPRESSED_RGB_S3TC_DXT1_EXT作为图像的内部格式来获取DXT1图像。

每个4x4块按如下方式存储颜色数据。有2个16位颜色值,color0后跟color1。其后是一个32位无符号整数,该整数包含描述两种颜色如何组合以确定给定像素的颜色的值。

2个16位颜色值以Little-endian格式存储,因此16位颜色的低字节在每种情况下都排在首位。颜色值以5_6_5位的RGB顺序(从高位到低位)存储。

32位无符号整数也以little-endian格式存储。整数的每2位代表一个像素;这两位是定义如何将color0和color1组合以产生该像素颜色的代码。按照从最高位到最低位的顺序(在小端顺序转换之后),像素按行优先顺序存储。每8位(4个2位代码)是图像的一行。

这是设置图:
63       55       47       39       31       23       15       7        0
| c0-low | c0-hi  | c1-low | c1-hi  | codes0 | codes1 | codes2 | codes3 |
-------------------------------------------------------------------------

c0-low是16位颜色0的低字节;类似地,c0-hi是颜色0的高字节。要重构颜色0,只需执行以下操作:((bytes[1] << 8) + bytes[0])​,其中bytes是包含上述字节序列的数组。颜色1来自((bytes[3] << 8) + bytes[2])​

同样,这些代码是组成32位整数位代码的字节。它们必须以相反的顺序重建,因此code3是最左边的字节。

重建为正确的顺序后,您可以像这样获得单个的2位值。像素值采用cXY形式,其中Y按照OpenGL的标准从下到上排列:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
 | c00 | c10 | c20 | c30 | c01 | c11 | c21 | c31 | c02 | c12 | c22 | c32 | c03 | c13 | c23 | c33 
 |       codes3          |       codes2          |       codes1          |       codes0
 ------------------------------------------------------------------------------------------------

2位值的解释取决于color0和color1相互比较的方式。如果color0的整数值大于color1,则2位值的含义与color0小于或等于color1的含义有所不同。 2位值的含义如下:
code | color0 > color1         | color0 <= color1 
----------------------------------------------------
0    | color0                  | color0  
1    | color1                  | color1  
2    | (2*color0 + color1) / 3 | (color0 + color1) / 2  
3    | (color0 + 2*color1) / 3 | Black 

算术运算是按分量完成的,而不是颜色的整数值。而值“Black”仅是R = G = B = 0。

带有1位Alpha的DXT1

DXT1有一种形式,可提供简单的开/关alpha值。因此,此格式使用RGBA基本格式。要获得此格式,请使用GL_COMPRESSED_RGBA_S3TC_DXT1_EXT内部格式。

数据格式与上述情况相同,这就是为什么它仍是DXT1压缩的原因。解释略有不同。除非像素使用上表中的“黑色”代码,否则您始终将alpha值设为1。在这种情况下,您获得的alpha值为0。

请注意,这意味着在任何具有0 alpha的像素上,RGB颜色也将为0。这也意味着相邻纹理像素之间的双线性滤波将导致颜色与黑色结合。如果您正在使用预乘alpha混合,这就是您想要的。如果不是,那么几乎可以肯定不是您想要的。

当使用OpenGL压缩纹理时,GL实现将假定alpha值<0.5的任何像素的alpha均应为0。这是手动压缩图像的另一个原因。

DXT3格式

DXT3格式是RGBA格式。每个4x4块占用128位数据。因此,与32位RGBA纹理相比,它提供4:1压缩。您可以使用GL_COMPRESSED_RGBA_S3TC_DXT3_EXT内部格式来获取它。

每个128位块分为2个64位块。第二个块包含颜色信息,几乎像在DXT1情况下一样进行了压缩;在确定如何使用代码提取颜色值方面,始终假定color0小于color1。第一块包含Alpha信息。

alpha 64位块存储为Little-endian 64位无符号整数。 Alpha值存储为每像素4位的Alpha值。从64位无符号整数的最高位开始,按行优先顺序存储alpha值。

DXT5格式

DXT5格式是另一种RGBA格式。与DXT3情况一样,每个4x4块占用128位。因此,它提供与DXT3情况相同的4:1压缩。您可以使用GL_COMPRESSED_RGBA_S3TC_DXT5_EXT格式来获取它。

就像DXT3格式一样,每个块有两个64位数据块:一个与DXT1压缩的RGB块(与DXT3相同的警告)和一个alpha块。同样,第二个块是颜色块;第一个是Alpha。

DXT3和DXT5的不同之处在于alpha块的压缩方式。 DXT5使用类似于DXT1的压缩方案压缩alpha。

alpha数据存储为2个8位alpha值alpha0和alpha1,后跟一个48位无符号整数,该整数描述了如何组合这两个参考alpha值以获得最终的alpha值。 48位整数也按小端顺序存储。

48位无符号整数包含描述如何计算最终alpha值的3位代码。这些代码的存储顺序与DXT1中的代码相同。它们只是3位而不是2位。

就像在DXT1情况下一样,这些代码具有不同的含义,具体取决于alpha0和alpha1相互比较的方式。这是代码和计算表:
code | alpha0 > alpha1        | alpha0 <= alpha1 
---------------------------------------------
0    |alpha0                  | alpha0  
1    |alpha1                  | alpha1
2    |(6*alpha0 + 1*alpha1)/7 | (4*alpha0 + 1*alpha1)/5  
3    |(5*alpha0 + 2*alpha1)/7 | (3*alpha0 + 2*alpha1)/5  
4    |(4*alpha0 + 3*alpha1)/7 | (2*alpha0 + 3*alpha1)/5  
5    |(3*alpha0 + 4*alpha1)/7 | (1*alpha0 + 4*alpha1)/5  
6    |(2*alpha0 + 5*alpha1)/7 | 0.0  
7    |(1*alpha0 + 6*alpha1)/7 | 1.0 

有关更多信息,请访问S3 Texture Compression

还有更多现代的纹理压缩算法

对于OpenGL 4.2 OpenGL-ES 3.0 Ericsson Texture Compression (ETC):
GL_COMPRESSED_RGB8_ETC2
GL_COMPRESSED_SRGB8_ETC2
GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
GL_COMPRESSED_RGBA8_ETC2_EAC
GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
GL_COMPRESSED_R11_EAC
GL_COMPRESSED_SIGNED_R11_EAC
GL_COMPRESSED_RG11_EAC
GL_COMPRESSED_SIGNED_RG11_EAC

还有 Adaptive Scalable Texture Compression

关于image - 为什么您看到内存中加载的图像大小(在libgdx中)占用了您自己的更多照片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35356746/

相关文章:

iphone - "ping pong"你如何做一个UIView图像序列动画

android - 删除以位图为背景的 Canvas 上的线条

multithreading - Delphi指针内存和释放

c#-4.0 - "Bitmap locking"实际上是什么意思?

android - 如何设置壁纸使用应用程序服务壁纸和联系人照片?

html - 图片未在 Chrome 中显示

image - Summernote 显示已上传到文件夹的图像

html - 使用填充在悬停时为图像添加边框

c++ - 如何从进程内部确定 CPU 和内存消耗

linux - 什么是私有(private)页面?