BMP2ARGB1555图像格式相关总结

对照上图与下方结构体一一对应

// BMP文件头结构体
typedef struct {
    uint16_t bfType;//0-1:表示文件类型,BMP格式的文件这两个字节是0x4D42,10进制就是19778,字符显示就是‘BM’;
    uint32_t bfSize;//2-5:表示文件的大小,此处是0x00111F2A,十进制1122090,正确
    uint16_t bfReserved1;//6-7:保留位,必须设置为0
    uint16_t bfReserved2;//8-9:保留位,必须设置为0
    uint32_t bfOffBits;//a-d:表示偏移,即0x8a,十进制138
} BMPFileHeader;


// BMP信息头结构体
typedef struct {
    uint32_t biSize;//0e-11:信息头总大小0x0000007c,十进制124(标准的BMP信息头应该为40个字节,客户的图片不标准,不过可以fseek掉)
    int32_t biWidth;//12-15:图片宽0x00000706,十进制1798
    int32_t biHeight;//16-19:图片高0x0000009c,十进制156;同时,这是一个正数,表示图像是倒立的,即图像数据是从左下角到右上角排列的;
    uint16_t biPlanes;//1a-1b:2字节的biPlanes,值为0x0001;
    uint16_t biBitCount;//1c-1d:2字节的biBitCount,0x0020;32位深度
    uint32_t biCompression;//1e-21:值为0x00000003,BI_BITFIELDS,表示使用位字段掩码来指定每个像素的颜色。0-2表示:
                                                    0:BI_RGB,表示不压缩,每个像素占用位深度所需的位数。
                                                    1:BI_RLE8,表示采用RLE (Run-Length Encoding) 压缩,适用于8位颜色索引的图像。
                                                    2:BI_RLE4,表示采用RLE压缩,适用于4位颜色索引的图像。
    uint32_t biSizeImage;//22-25:值为0x00111EA0,十进制1121952;即biSizeImage=bfSize(1122090)-bfOffBits(138)
    int32_t biXPelsPerMeter;//26-29:水平分辨率
    int32_t biYPelsPerMeter;//2a-2d:垂直分辨率
    uint32_t biClrUsed;     //2e-31:颜色索引数
    uint32_t biClrImportant;//32-35:重要的颜色索引数
} BMPInfoHeader;

Windows默认的扫描的最小单位是4字节,如果数据对齐满足这个值的话对于数据的获取速度等都是有很大的增益的。因此,BMP图像顺应了这个要求,要求每行的数据的长度必须是4的倍数,如果不够需要进行比特填充(以0填充),这样可以达到按行的快速存取。这样的话,位图数据的大小就不一定是宽x高x每像素字节数了,因为每行还可能有0填充。

填充后的每行数据如下:

其中,BPP是每像素的比特数(Bits Per Pixel),即biBitCount,Width是宽度,单位是像素即bfWidth。

按照没填充计算:1798*156*3=841464bytes,与真实值1121952相差280488字节。

按照填充公式,每行有数据4*(32*1798/32)=7192字节  真正的数据有1798*3=5394字节  每行填充了1798个字节,一共156行 1798*156=280488与上述值相等;

所以对于这个客户的图片在代码里写的rowsize计算再*2就是正确的rowsize:

 uint32_t rowSize = (width * infoHeader.biBitCount + 31) / 32 * 4 * 2; // 每行字节数

然后转化ARGB1555格式图片代码如下:

 uint32_t rowSize = (width * infoHeader.biBitCount + 31) / 32 * 4 * 2; // 每行字节数
    uint8_t *buffer = (uint8_t *)malloc(rowSize);
    
    for (int32_t y = 0; y <height; y++)
    {
        fread(buffer, rowSize, 1, inputFile); // 读取一行像素数据
        for (int32_t x = 0; x < width; x++)
        {
            // 提取ARGB通道值
            uint8_t b = buffer[x * 4];
            uint8_t g = buffer[x * 4 + 1];
            uint8_t r = buffer[x * 4 + 2];
            uint8_t a = buffer[x * 4 + 3];
            // 转换为ARGB1555格式
            uint16_t argb1555 = ((a >> 7) << 15) | ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
            // 写入转换后的像素数据
            fwrite(&argb1555, sizeof(uint16_t), 1, outputFile);
        }
    }
ARGB1555的结构以及转化这部分代码是从网上找的,没有太多相关介绍只清楚最高位为alpha,后面每5位分别是red、green、blue
  • A(Alpha)位数 :1位,表示像素的透明度。在这种格式中,通常1位表示完全透明(0)或完全不透明(1),因此只有两种透明度状态。
  • R(红色)位数 :5位,表示红色分量的强度。这允许32个不同的红色强度级别。
  • G(绿色)位数 :5位,表示绿色分量的强度。这允许32个不同的绿色强度级别。
  • B(蓝色)位数 :5位,表示蓝色分量的强度。这允许32个不同的蓝色强度级别
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值