C语言如何取出一张256色位的bmp图像的某个像素的颜色
C语言怎么取出一张256色位的bmp图像的某个像素的颜色
我想实现的是:将一张256色位图的bmp图像(1.bmp)上下左右移动N个像素(比如向右移5个像素,最左边的5个像素全涂成黑色)生成另一张图像(2.bmp)。我现在写的有些问题:
代码:
#include <stdio.h>
#include <windows.h>
int main()
{
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
FILE *pfin = fopen("F:\\1.bmp","rb");
FILE *pfout = fopen("F:\\2.bmp","wb");
fread(&fileHeader,sizeof(BITMAPFILEHEADER),1,pfin);
fread(&infoHeader,sizeof(BITMAPINFOHEADER),1,pfin);
int size = 512*512;
int i;
unsigned char img[512][512];
fread(img,sizeof(byte),size,pfin);
if(infoHeader.biBitCount == 8)
{
for(i=1;i<512;i++)
{
img[i][50]=0;
}
}
fwrite(&fileHeader,sizeof(fileHeader),1,pfout);
fwrite(&infoHeader,sizeof(infoHeader),1,pfout);
fwrite(img,sizeof(byte),size,pfout);
}
------解决思路----------------------
比如表示某个像素的值为0x12,找调色板中从0x00到0xff的第0x12项对应的RGB值。
------解决思路----------------------
bmp_simple_header_t + bmp_header_windows_t + bmp_info_windows_t
这是标准的 windows bitmap 的文件头结构。
下面是确认出 bitmap 文件的格式,
其中,
应该就是楼主的 8-bit 格式了,当然了读取就比较简单了
conv_palette 指向的是调色板,
conv_buffer 指向的是索引数据。
而将索引数据映射到调色板里就不用我说了吧,楼主自己会做了。
需要注意的是,调色板里的颜色格式是 x8r8g8b8。
跨度 pitch = align_to_4(width),需要 4 字节对齐。
我想实现的是:将一张256色位图的bmp图像(1.bmp)上下左右移动N个像素(比如向右移5个像素,最左边的5个像素全涂成黑色)生成另一张图像(2.bmp)。我现在写的有些问题:
代码:
#include <stdio.h>
#include <windows.h>
int main()
{
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
FILE *pfin = fopen("F:\\1.bmp","rb");
FILE *pfout = fopen("F:\\2.bmp","wb");
fread(&fileHeader,sizeof(BITMAPFILEHEADER),1,pfin);
fread(&infoHeader,sizeof(BITMAPINFOHEADER),1,pfin);
int size = 512*512;
int i;
unsigned char img[512][512];
fread(img,sizeof(byte),size,pfin);
if(infoHeader.biBitCount == 8)
{
for(i=1;i<512;i++)
{
img[i][50]=0;
}
}
fwrite(&fileHeader,sizeof(fileHeader),1,pfout);
fwrite(&infoHeader,sizeof(infoHeader),1,pfout);
fwrite(img,sizeof(byte),size,pfout);
}
------解决思路----------------------
比如表示某个像素的值为0x12,找调色板中从0x00到0xff的第0x12项对应的RGB值。
------解决思路----------------------
//////////////////////////////////////////////////////////////////////////
// Bitmap 文件(压缩)格式
typedef enum tag_bmp_encode
{
bmp_encode_none = 0, // 未压缩
bmp_encode_rle8, // rle8压缩
bmp_encode_rle4, // rle4压缩
bmp_encode_mask, // 由掩码(color_mask_abgr_t)决定
// os2 压缩方式
bmp_encode_os2_index4, // OS/2 的 4 位编码
bmp_encode_os2_index8, // OS/2 的 8 位编码
bmp_encode_os2_24, // OS/2 的 24 位编码
}bmp_encode_e;
#pragma pack(push, 1)
//////////////////////////////////////////////////////////////////////////
// 简单的 Bitmap 文件头,用于识别 Bitmap 文件类型。
struct bmp_simple_header_t
{
uint_16 type;
uint_32 file_size;
uint_32 reserved;
uint_32 data_offset;
uint_32 info_size;
};
//////////////////////////////////////////////////////////////////////////
// Windows Bitmap 文件头
struct bmp_info_windows_t
{
uint_32 size;
int_32 width;
int_32 height;
uint_16 plane_count;
uint_16 bit_count;
bmp_encode_e encode;
uint_32 image_size;
int_32 ppm_x; // pels per meter
int_32 ppm_y;
uint_32 color_used;
uint_32 color_important;
};
struct bmp_header_windows_t
{
uint_16 type;
uint_32 file_size;
uint_32 reserved;
uint_32 data_offset;
};
bmp_simple_header_t + bmp_header_windows_t + bmp_info_windows_t
这是标准的 windows bitmap 的文件头结构。
下面是确认出 bitmap 文件的格式,
const uint_16 BMP_HEADER_ID = 0x4D42; // 'BM',header.type
bmp_simple_header_t * header = (bmp_simple_header_t *)buffer;
if(header->type != BMP_HEADER_ID)
return 1;
int_x width = 0;
int_x height = 0;
color_mode_e src_mode = color_mode_invalid;
byte_t * conv_palette = nullptr;
byte_t * conv_buffer = nullptr;
int_x flags = 0;
bmp_header_windows_t * header = (bmp_header_windows_t *)buffer;
buffer += sizeof(bmp_header_windows_t);
if(header->type != BMP_HEADER_ID)
return false;
bmp_info_windows_t * info = (bmp_info_windows_t *)buffer;
buffer += sizeof(bmp_info_windows_t);
if(info->size != sizeof(bmp_info_windows_t) && info->size != sizeof(bmp_info_windows_t)+sizeof(color_mask_abgr_t))
return false;
width = (int_x)info->width;
height = (int_x)info->height;
// 翻转行序
if(height < 0)
height = -height;
else
flags
------解决思路----------------------
= IMAGE_CONVERT_FLIP_Y;
// 调色板、颜色掩码等额外信息
int_x extern_size = header->data_offset - sizeof(bmp_info_windows_t)-sizeof(bmp_header_windows_t);
conv_palette = nullptr;
conv_buffer = buffer;
// 颜色掩码确定颜色类型
if(info->encode == bmp_encode_mask)
{
IMAGE_ASSERT(extern_size == sizeof(color_mask_abgr_t));
color_mask_abgr_t * mask = (color_mask_abgr_t *)buffer;
src_mode = color_mode_from_mask_abgr(mask, info->bit_count);
conv_buffer = buffer + extern_size;
conv_palette = nullptr;
}
// rle8 编码
else if(info->encode == bmp_encode_rle8)
{
src_mode = color_mode_index8_rle2_x8r8g8b8;
conv_buffer = buffer + extern_size;
conv_palette = buffer;
}
// rle4 编码
else if(info->encode == bmp_encode_rle4)
{
src_mode = color_mode_index4_rle2_x8r8g8b8;
conv_buffer = buffer + extern_size;
conv_palette = buffer;
}
// 有调色板
else if(extern_size)
{
src_mode = color_mode_invalid;
switch(info->bit_count)
{
case 1:
src_mode = color_mode_index1_x8r8g8b8;
break;
case 2:
src_mode = color_mode_index2_x8r8g8b8;
break;
case 4:
src_mode = color_mode_index4_x8r8g8b8;
break;
case 8:
src_mode = color_mode_index8_x8r8g8b8;
break;
default:
break;
}
conv_buffer = buffer + extern_size;
conv_palette = buffer;
}
else // 没有调色板
{
src_mode = color_mode_invalid;
switch(info->bit_count)
{
case 2:
src_mode = color_mode_gray2;
break;
case 4:
src_mode = color_mode_gray4;
break;
case 8:
src_mode = color_mode_gray8;
break;
case 16:
src_mode = color_mode_x1r5g5b5;
break;
case 24:
src_mode = color_mode_r8g8b8;
break;
case 32:
src_mode = color_mode_a8r8g8b8;
break;
default:
break;
}
conv_buffer = buffer;
conv_palette = nullptr;
}
其中,
case 8:
src_mode = color_mode_index8_x8r8g8b8;
break;
应该就是楼主的 8-bit 格式了,当然了读取就比较简单了
conv_palette 指向的是调色板,
conv_buffer 指向的是索引数据。
而将索引数据映射到调色板里就不用我说了吧,楼主自己会做了。
需要注意的是,调色板里的颜色格式是 x8r8g8b8。
跨度 pitch = align_to_4(width),需要 4 字节对齐。