windows显示64位位图问题(libpng)
本帖最后由 vegapan 于 2013-04-19 09:28:07 编辑 首先,一直以为位图里面每个颜色分量取值范围是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;
} Windows Bitmap libpng
[解决办法]
0~65535/256 → 0..255