24位位深bmp文件转换为8位位深bmp文件

位深(Bit Depth)是衡量数字图像中每个像素可以表示的颜色数量的一个指标。位深越高,每个像素可以表示的颜色就越丰富,图像的细节和质量也就越高。常见的位深为8位、16位、24位和32位。

8位深图片:

  1. 每个像素由8位二进制数表示。
  2. 可以表示256种不同的颜色(每种颜色通道8位)。
  3. 通常用于网页图像和低质量的图像,因为颜色数量有限,可能出现色带现象。

16位深图片:

  1. 每个像素由16位二进制数表示。
  2. 可以表示65536种不同的颜色(每种颜色通道16位)。
  3. 比8位图像有更高的颜色精度,适合需要更丰富色彩的图像处理。

24位深图片:

  1. 每个像素由24位二进制数表示。
  2. 每个通道8位,即红、绿、蓝(RGB),总共24位,可以表示大约1677万种颜色。
  3. 这是最常见的位深,用于高质量的图像,如JPEG和BMP格式。

32位深图片:

  1. 每个像素由32位二进制数表示。
  2. 可以表示大约42亿种颜色,通常是24位用于RGB颜色通道,加上8位用于透明度(Alpha通道)。
  3. 常用于需要透明度信息的图像,如PNG格式。​

总结一下:

  1. 位深越高,每个像素可以表示的颜色数量越多,图像的细节和质量也越高。
  2. 位深越高,所需的存储空间和处理能力也越大。
  3. 8位和16位通常不包含透明度信息,而24位和32位可以包含透明度信息。
  4. 24位图像常用于标准质量的图像显示,而32位图像则常用于需要透明度的高级图像处理。

在这里插入图片描述

​由于dsp上的限制,在RTOS上只能显示8位位深的bmp,所以需要将24位位深的bmp转为8位位深的bmp。代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
​
#define MAX_COLORS 256
​
struct bmp_info_header {
    unsigned int biSize;
    unsigned int biWidth;
    unsigned int biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned int biCompression;
    unsigned int biSizeImage;
    unsigned int biXPelsPerMeter;
    unsigned int biYPelsPerMeter;
    unsigned int biClrUsed;
    unsigned int biClrImportant;
} __attribute__((packed));
​
struct bmp_file_header {
    unsigned short bfType;
    unsigned int bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int bfOffBits;
} __attribute__((packed));
​
typedef struct {
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    unsigned char index; // BMP palette may include an extra reserved byte
} ColorWithIndex;
​
// 读取24位位深的BMP文件
void read24BitBMP(const char *filename, unsigned char **imageData, int *width, int *height) {
    FILE *bmpFile = fopen(filename, "rb");
    if (!bmpFile) {
        perror("Error: Cannot open the BMP file");
        exit(1);
    }
​
    struct bmp_file_header fileHeader;
    struct bmp_info_header infoHeader;
​
    // 读取文件头和信息头
    fread(&fileHeader, sizeof(fileHeader), 1, bmpFile);
    fread(&infoHeader, sizeof(infoHeader), 1, bmpFile);
​
    if (infoHeader.biBitCount != 24) {
        fprintf(stderr, "Error: BMP is not 24-bit.\n");
        exit(1);
    }
​
    *width = infoHeader.biWidth;
    *height = infoHeader.biHeight;
​
    // 跳过颜色数据
    fseek(bmpFile, fileHeader.bfOffBits - sizeof(fileHeader) - sizeof(infoHeader), SEEK_CUR);
​
    // 为图像数据分配内存
    *imageData = (unsigned char *)malloc(*width * *height * 3);
    if (!*imageData) {
        perror("Error: Cannot allocate memory for image data");
        exit(1);
    }
​
    // 读取图像数据
    fread(*imageData, *width * *height * 3, 1, bmpFile);
​
    fclose(bmpFile);
}
​
// 写入8位位深的BMP文件
void write8BitBMP(const char *filename, unsigned char *indexedData, int width, int height, unsigned char *palette) {
    FILE *bmpFile = fopen(filename, "wb");
    if (!bmpFile) {
        perror("Error: Cannot open the BMP file for writing");
        exit(1);
    }
​
    struct bmp_file_header fileHeader;
    struct bmp_info_header infoHeader;
  printf("setting file \n");
    // 设置文件头
  const char bmp_file_type[] = {'B', 'M'};
    fileHeader.bfType = bmp_file_type[0] | (bmp_file_type[1] << 8);
    fileHeader.bfSize = sizeof(fileHeader) + sizeof(infoHeader) + (width * height) + (MAX_COLORS * 4);
    fileHeader.bfReserved1 = 0;
    fileHeader.bfReserved2 = 0;
    fileHeader.bfOffBits = sizeof(fileHeader) + sizeof(infoHeader) + (MAX_COLORS * 4);
  printf("setting info \n");
    // 设置信息头
    infoHeader.biSize = sizeof(infoHeader);
    infoHeader.biWidth = width;
    infoHeader.biHeight = height;
    infoHeader.biPlanes = 1;
    infoHeader.biBitCount = 8;
    infoHeader.biCompression = 0;
    infoHeader.biSizeImage = 0;
    infoHeader.biXPelsPerMeter = 0;
    infoHeader.biYPelsPerMeter = 0;
    infoHeader.biClrUsed = MAX_COLORS;
    infoHeader.biClrImportant = MAX_COLORS;
  printf("write setting file begin\n");
    // 写入文件头和信息头
    fwrite(&fileHeader, sizeof(fileHeader), 1, bmpFile);
    fwrite(&infoHeader, sizeof(infoHeader), 1, bmpFile);
  printf("write setting file end\n");
​
    // 写入调色板
    fwrite(palette, 1, MAX_COLORS * 4, bmpFile);
  printf("write palette end\n");
    // 写入索引图像数据
    fwrite(indexedData, width * height, 1, bmpFile);
  printf("write indexedData end\n");
    fclose(bmpFile);
}
​
// 将24位颜色数据映射到8位索引数据
void mapColorsToIndices(unsigned char *imageData, ColorWithIndex *palette, unsigned char *indexedData, int width, int height) {
    int paletteIndex = 0;
  int j = 0;
​
    for (int i = 0; i < width * height; ++i) {
        unsigned char r = imageData[i * 3];
        unsigned char g = imageData[i * 3 + 1];
        unsigned char b = imageData[i * 3 + 2];
        ColorWithIndex searchColor = {r, g, b, 0};
​
        // 查找调色板中的颜色
        for (j = 0; j < paletteIndex; ++j) {
            if (searchColor.red == palette[j].red && searchColor.green == palette[j].green && searchColor.blue == palette[j].blue) {
                indexedData[i] = palette[j].index;
                break;
            }
        }
​
        if (j == paletteIndex && paletteIndex < MAX_COLORS) {
            palette[paletteIndex] = (ColorWithIndex){r, g, b, paletteIndex};
            indexedData[i] = paletteIndex;
            ++paletteIndex;
        }
    }
}
​
int main() {
    const char *inputFilename = "24bit.bmp";
    const char *outputFilename = "8bit.bmp";
​
    ColorWithIndex *imageData = NULL;
    int width, height;
​
    // 读取24位位深的BMP图像数据
  printf("begin \n");
    read24BitBMP(inputFilename, &imageData, &width, &height);
  printf("width:%d, height:%d\n",width,height);
    // 分配内存以存储索引数据
    unsigned char *indexedData = (unsigned char *)malloc(width * height * sizeof(unsigned char));
    if (!indexedData) {
        free(imageData);
        perror("Error: Cannot allocate memory for indexed data");
        exit(EXIT_FAILURE);
    }
    // 简化的量化逻辑
  ColorWithIndex palette[MAX_COLORS] = {0};
    mapColorsToIndices(imageData, palette, indexedData, width, height);
    // 将24位颜色数据映射到8位索引数据
    // 这里需要实现映射逻辑
    // ...
  printf("write begin\n");
    // 写入8位位深的BMP文件
    write8BitBMP(outputFilename, indexedData, width, height, palette);
  printf("write end\n");
    // 释放内存
    free(imageData);
    free(indexedData);
​
    printf("Conversion successful.\n");
​
    return 0;
}

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值