windows显示64位位图问题(libpng)

vegapan 2013-04-18 05:33:59
首先,一直以为位图里面每个颜色分量取值范围是0-255,
现在遇到了64位图片,每个分量为0-65535。
问题是同一个颜色在两种表示方式中如何转换?

这是我自己写的一个小工具,用libpng读取图片之后,显示到窗口。
读取32位png没有问题,如果是64位的就遇到以上问题。我的解决方式遇到的问题是
图片中会出现很多噪点,就是在颜色分界处会出现很多斑点。

HBITMAP png_convert_bmp(image_data* img_data, int row, int col, int height, int width){
if (img_data == NULL){
return NULL;
}

png_structp png_ptr = img_data->png_ptr;
png_infop info_ptr = img_data->info_ptr;

png_bytep* row_ptr = png_get_rows(png_ptr, info_ptr);

// Read into CBitmap
int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
png_byte color_type = png_get_color_type(png_ptr, info_ptr);
int step = get_step(color_type);

if (width == 0 && height == 0){
width = png_get_image_width(png_ptr, info_ptr);
height = png_get_image_height(png_ptr, info_ptr);
}
int _rowbytes = png_get_rowbytes(png_ptr, info_ptr);
// int _rb = png_get_rowbytes(png_ptr, info_ptr);

/////
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));

BITMAPINFOHEADER& bih = bmi.bmiHeader;
bih.biSize = sizeof(bih);
bih.biWidth = width;
bih.biHeight = -height;
bih.biPlanes = 1;
bih.biBitCount = 32;
bih.biCompression = BI_RGB;



// Create the DIB section with an alpha channel.
BYTE* lpBits = NULL;
HBITMAP hBitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, (void**)&lpBits, 0, 0);
// free(bmi); bmi = NULL;

img_data->x = img_data->y = 10000;
img_data->r = img_data->b = 0;

//int C = 0;
for (int i = 0; i < height; i++){
unsigned char* tar = (unsigned char*)(lpBits + i * _rowbytes / 2);
if (bit_depth == 16){
for (int j = 0; j < width; j++){
int col_offset = col * 4 + j * 4;
unsigned short* src = (unsigned short*)row_ptr[i + row];
unsigned int r = src[col_offset + 0];
unsigned int g = src[col_offset + 1];
unsigned int b = src[col_offset + 2];
unsigned int a = src[col_offset + 3];

tar[j * 4 + 3] = (BYTE)(a >> 8);
tar[j * 4 + 2] = (BYTE)((r * a) >> 16); //Blue
tar[j * 4 + 1] = (BYTE)((g * a) >> 16); //Green
tar[j * 4 + 0] = (BYTE)((b * a) >> 16); //Red


int _x = j;
if (a > 0){
// Parse the boundary
if (img_data->y > i){
img_data->y = i;
}
else if (img_data->b < i){
img_data->b = i;
}
if (img_data->x > _x){
img_data->x = _x;
}
else if (img_data->r < _x){
img_data->r = _x;
}
}
}
}
else{
int tar_offset = _rowbytes * i;
for (int j = 0; j < width; j++){
int src_offset = step * (j + col);
int r = row_ptr[i + row][src_offset + 0];
int g = row_ptr[i + row][src_offset + 1];
int b = row_ptr[i + row][src_offset + 2];
int a = row_ptr[i + row][src_offset + 3];
////RGBA -> BGRA Pre-Multipie
lpBits[tar_offset + j * step + 3] = (BYTE)(a >> 8);
lpBits[tar_offset + j * step + 2] = (BYTE)(r * a >> 16); //Blue
lpBits[tar_offset + j * step + 1] = (BYTE)(g * a >> 16); //Green
lpBits[tar_offset + j * step + 0] = (BYTE)(b * a >> 16); //Red
// 至此为止功能结束,下面代码与显示没有直接关系。
int _x = j;
if (a > 0){
// Parse the boundary
if (img_data->y > i){
img_data->y = i;
}
else if (img_data->b < i){
img_data->b = i;
}
if (img_data->x > _x){
img_data->x = _x;
}
else if (img_data->r < _x){
img_data->r = _x;
}
}
}
}
}

// defer
// png_destroy_read_struct(&png_ptr, &info_ptr, 0);
return hBitmap;
}
...全文
249 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
vegapan 2013-04-26
  • 打赏
  • 举报
回复
多谢老师的回复。 我找这个做之后效果还是不理想。感觉问题不是出在精度丢失或者符号位上。 老师能够关注一下,我把源码发过去帮忙看一下吗?
vegapan 2013-04-26
  • 打赏
  • 举报
回复
找到解决方式了。libpng里面有一个png_set_strip_16函数可以解决这个问题。 直接把调整位深。 多谢老师的帮助。
赵4老师 2013-04-25
  • 打赏
  • 举报
回复
lpBits[tar_offset + j * step + 3] = (BYTE)(    a >>  8 & 0x000000FFu);
lpBits[tar_offset + j * step + 2] = (BYTE)(r * a >> 16 & 0x000000FFu); //Blue
lpBits[tar_offset + j * step + 1] = (BYTE)(g * a >> 16 & 0x000000FFu); //Green
lpBits[tar_offset + j * step + 0] = (BYTE)(b * a >> 16 & 0x000000FFu); //Red
试试看。 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
vegapan 2013-04-25
  • 打赏
  • 举报
回复
好冷清啊,自己顶
vegapan 2013-04-22
  • 打赏
  • 举报
回复
大侠都休息了吗?
vegapan 2013-04-22
  • 打赏
  • 举报
回复
我代码中这样处理之后导致图片出现了很多噪点。 请问是不是我处理方式不正确,或者是走了弯路,windows 位图可以直接支持64为的位深? lpBits[tar_offset + j * step + 3] = (BYTE)(a >> 8); lpBits[tar_offset + j * step + 2] = (BYTE)(r * a >> 16); //Blue lpBits[tar_offset + j * step + 1] = (BYTE)(g * a >> 16); //Green lpBits[tar_offset + j * step + 0] = (BYTE)(b * a >> 16); //Red
赵4老师 2013-04-22
  • 打赏
  • 举报
回复
0~65535/256 → 0..255

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧