我正在寻找将位图从 16 bpp 转换为 8,我的灵感来自我发现将 24 bpp 转换为 8 bpp 的代码,我认为我的文件的写入是正确的(见图)但文件是仍然无效!
我认为数据是以小端存储的,但我不确定所以我认为我的问题在于提取 RGB 颜色,即使它不应该使文件无效
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#pragma pack(push, 2)
typedef struct {
int16_t bfType;
int32_t bfSize;
int16_t bfReserved1;
int16_t bfReserved2;
int32_t bfOffBits;
} BITMAPFILEHEADER;
typedef struct {
int32_t biSize;
int32_t biWidth;
int32_t biHeight;
int16_t biPlanes;
int16_t biBitCount;
int32_t biCompression;
int32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
int32_t biClrUsed;
int32_t biClrImportant;
} BITMAPINFOHEADER;
#pragma pack(pop)
int main()
{
FILE* fin = fopen("SCR.bmp", "rb");
FILE* fout = fopen("fout.bmp", "wb");
if(!fin) { printf("fin error\n"); goto error; }
if(!fout) { printf("fout error\n"); goto error; }
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
fread(&bf, sizeof bf, 1, fin);
fread(&bi, sizeof bi, 1, fin);
if(sizeof bf != 14) { printf("Wrong pragma pack\n"); goto error; }
if(sizeof bi != 40) { printf("Wrong pragma pack\n"); goto error; }
if(bf.bfType != 0x4D42) { printf("not bmp, or not LE system\n"); goto error; }
//if(bi.biSize != 40) { printf("Can't handle this bitmap format\n"); goto error; }
//if(bi.biBitCount != 24) { printf("not 24-bit\n"); goto error; }
int height = bi.biHeight;
if(height < 0) height = -height;
//width in bytes:
int src_wb = ((bi.biWidth * 16 + 31) / 32) * 4;
printf(" src wb =%d et width =%d et %d",src_wb,bi.biWidth,bi.biHeight);
int dst_wb = ((bi.biWidth * 8 + 31) / 32) * 4;
int src_size = src_wb * height;
int dst_size = dst_wb * height;
//allocate for source and destination
uint8_t *src = malloc(src_size);
uint8_t *dst = malloc(dst_size);
//read pixels
fread(src, 1, src_size, fin);
//make gray scale color-table
uint8_t clr[1024] = { 0 };
for(int i = 0; i < 256; i++)
clr[i * 4 + 0] = clr[i * 4 + 1] = clr[i * 4 + 2] = (uint8_t)i;
for(int y = height - 1; y >= 0; y--)
{
for(int x = 0; x < bi.biWidth; x++)
{
uint8_t pt1 = src[y * src_wb + x * 2 + 0]; // first byte of pixel (LSB because little endian)
uint8_t pt2 = src[y * src_wb + x * 2 + 1]; // second byte of pixel (MSB)
//uint8_t grn = src[y * src_wb + x * 3 + 2];
uint8_t red = pt2>>3;// 5 bit
uint8_t grn = (uint8_t)((pt1 & 0xE)<<5)| (uint8_t)((pt2 &7)>>5) ;// 6 bit
uint8_t blu = (pt1 & 0x11); // 5 bit
uint8_t gry = (uint8_t)(.33 * red + .34 * grn + .33 * blu);
dst[y * dst_wb + x] = gry; //this will match the index in color-table
}
}
//modify bitmap headers
bf.bfSize = 54 + 1024 + dst_size;
bf.bfOffBits =54 +1024 ;
bi.biBitCount = 8;
bi.biSizeImage = dst_size;
bi.biClrUsed=256;
bi.biCompression=0;
fwrite(&bf, sizeof bf, 1, fout);
fwrite(&bi, sizeof bi, 1, fout);
fwrite(clr, 1, 1024, fout);
fwrite(dst, 1, dst_size, fout);
free(src);
free(dst);
error:
fclose(fout);
fclose(fin);
return 0;
}