opengl c++:如何将 32 位 png 文件转换为 16 位 565RGB 文件

发布于 2025-01-07 11:50:32 字数 202 浏览 0 评论 0原文

我正在尝试将 32 位 png 文件转换为 16 位文件格式,我了解如何在彼此之间转换 16 位文件格式(例如 RGB565 RGBA4444),但是我不确定如何从 32 位转换为 16 位。

我的主要问题是:如何找到 32 位 png 的存储方式(每个 8 位分配给 R、B、G 和 A 值)?

如何失去精度但仍保持大致相同的值?

提前致谢

I am trying to convert 32bit png files to 16 bit file formats, I understand how to convert 16 bit file formats between eachother (e.g RGB565 RGBA4444) However I'm not sure how to go about converting from a 32 bit to a 16 bit.

My main questions are: How do I find how the 32 bit pngs stored (are 8 bits each assigned to R,B,G, and A values)?

How do I lost precision but still maintain roughly the same value?

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

溺ぐ爱和你が 2025-01-14 11:50:32

使用 libpng 比手动实现要好得多。

You'd be much better off using libpng than implementing this by hand.

过气美图社 2025-01-14 11:50:32

我不熟悉 32 位 png 像素的确切布局,但假设它与其他格式相对一致,您可能想做类似的事情:

// Get the pixel from the png:
unsigned int pngPixel = getPngPixel();

unsigned char r = (pngPixel & 0xFF000000) >> 24;
unsigned char g = (pngPixel & 0x00FF0000) >> 16;
unsigned char b = (pngPixel & 0x0000FF00) >> 8;
unsigned char a = (pngPixel & 0x000000FF);

// you can collapse this to one line, but for clarity...
// masking off the least significant bits.
unsigned short rgb565Pixel = (r & 0xF8) << 11; 
rgb565Pixel |= (g & 0xFC) << 5;
rgb565Pixel |= (b & 0xF8);

// Again you could collapse this down to one line, but for clarity...
// masking off the least significant bits.
unsigned short rgba4Pixel = (r & 0xF0) << 12;
rgba4Pixel |= (g & 0xF0) << 8;
rgba4Pixel |= (b & 0xF0) << 4;
rgba4Pixel |= (a & 0xF0);  

考虑这个伪代码。

有人可能会争辩说,屏蔽最低有效位(尤其是从 8 位转换为 4 位时)并不是在两者之间进行转换的好方法,而且他们是对的。您可以使用转换函数:

unsigned int convertColor(unsigned char c, unsigned int oldMax, unsigned int newMax) {
   double oldColor = c;
   double percentOfMax = oldColor / oldMax;
   return ((unsigned int)(newMax * percentOfMax)) & newMax;
}

// now we can do this
unsigned short rgba4Pixel = convertColor(r, 0xFF, 0x0F) << 12;
rgba4Pixel |= convertColor(g, 0xFF, 0x0F) << 8;
rgba4Pixel |= convertColor(b, 0xFF, 0x0F) << 4;
rgba4Pixel |= convertColor(a, 0xFF, 0x0F); 

I am not familiar with the exact layout of the 32bit png pixel, but assuming it is relatively consistent with other formats you probably want to do something similar to this:

// Get the pixel from the png:
unsigned int pngPixel = getPngPixel();

unsigned char r = (pngPixel & 0xFF000000) >> 24;
unsigned char g = (pngPixel & 0x00FF0000) >> 16;
unsigned char b = (pngPixel & 0x0000FF00) >> 8;
unsigned char a = (pngPixel & 0x000000FF);

// you can collapse this to one line, but for clarity...
// masking off the least significant bits.
unsigned short rgb565Pixel = (r & 0xF8) << 11; 
rgb565Pixel |= (g & 0xFC) << 5;
rgb565Pixel |= (b & 0xF8);

// Again you could collapse this down to one line, but for clarity...
// masking off the least significant bits.
unsigned short rgba4Pixel = (r & 0xF0) << 12;
rgba4Pixel |= (g & 0xF0) << 8;
rgba4Pixel |= (b & 0xF0) << 4;
rgba4Pixel |= (a & 0xF0);  

Consider this pseudocode.

One could argue that masking off the least significant bits, especially when converting from 8 bit to 4 bit, is not a very good way to convert between the two, and they would be right. You could instead use a conversion function:

unsigned int convertColor(unsigned char c, unsigned int oldMax, unsigned int newMax) {
   double oldColor = c;
   double percentOfMax = oldColor / oldMax;
   return ((unsigned int)(newMax * percentOfMax)) & newMax;
}

// now we can do this
unsigned short rgba4Pixel = convertColor(r, 0xFF, 0x0F) << 12;
rgba4Pixel |= convertColor(g, 0xFF, 0x0F) << 8;
rgba4Pixel |= convertColor(b, 0xFF, 0x0F) << 4;
rgba4Pixel |= convertColor(a, 0xFF, 0x0F); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文