BMP图像的读取和生成

1. BMP.h

#ifndef _BMP_H_
#define _BMP_H_


#ifdef __cplusplus
extern "C" {
#endif

    typedef enum _BIT_DATA_TYPE_{
        BIT32 = 1,                      //读取或存储成32位
        BIT24 = 2,                      //读取或存储成24位
    }BITDATATYPE;

    typedef struct _BMPFILEHEAD_{
        unsigned char   type[2];        //存储 'B' 'M'                    2字节
        unsigned int    size;           //位图文件大小                    4字节
        unsigned short  reserved1;      //保留字                          2字节
        unsigned short  reserved2;      //保留字                          2字节
        unsigned int    offBits;        //位图数据起始位置                4字节
    }BMPHEAD;
    typedef struct _BMPFILEINFOHEAD_{
        unsigned int    selfSize;       //位图信息头的大小                 4字节
        long            bitWidth;       //位图的宽度,以像素为单位          4字节
        long            bitHeight;      //位图的高度,以像素为单位          4字节
        unsigned short  bitPlanes;      //目标设备的级别,必须为1           2字节
        unsigned short  pixelBitCount;  //每个像素所需的位数               2字节
        unsigned int    compression;    //位图压缩类型,0(不压缩)           4字节
        unsigned int    sizeImage;      //位图的大小,以字节为单位          4字节
        long            pixelXPerMeter; //位图的水平分辨率,每米像素数      4字节
        long            pixelYPerMeter; //位图的垂直分辨率,每米像素数      4字节
        unsigned int    colorUsed;      //位图实际使用的颜色表中的颜色数   4字节
        unsigned int    colorImportant; //位图显示过程中重要的颜色数       4字节
    }BMPINFOHEAD;
    typedef struct _IMAGE_{
        int width;
        int height;
        int channels;
        unsigned char * data;
    }IMAGE;

int LoadBMP(const char * file, IMAGE* out_img, BITDATATYPE bit_data_type);
int WriteBMP(const char * file, IMAGE * in_img, BITDATATYPE bit_data_type);
int freeImage(IMAGE * img);
#ifdef __cplusplus
}
#endif

#endif

2. LoadBMP.c

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#include "BMP.h"

#define BMP_SIZE_FILEHEADER 14
#define BMP_SIZE_INFOHEADER 40

#define BMP_COLOR_BITS_24 24
#define BMP_COLOR_BITS_32 32


static unsigned int uInt16Number(unsigned char buf[2]){
    return (buf[1] << 8) | buf[0];
}

static unsigned int uInt32Number(unsigned char buf[4]){
    unsigned numb = buf[3];
    numb = (numb << 8) | buf[2];
    numb = (numb << 8) | buf[1];
    numb = (numb << 8) | buf[0];
    return numb;
}

static void IntTo2Bytes(int val, unsigned char buf[2]){
    buf[0] = (unsigned char)val;
    buf[1] = (unsigned char)(val >> 8);
}

static void IntTo4Bytes(int val, unsigned char buf[4]){
    buf[0] = (unsigned char)val;
    buf[1] = (unsigned char)(val >> 8);
    buf[2] = (unsigned char)(val >> 16);
    buf[3] = (unsigned char)(val >> 24);
}


static int ReadFileHeader(FILE* f, int* bitmap_pos){

    unsigned char header[BMP_SIZE_FILEHEADER];
    BMPHEAD bmp_head;

    int numb = 0;
    int offset = 0;

    if (fseek(f, 0, SEEK_SET))
        return -1;
    //读取bmp head信息
    numb = fread(header, BMP_SIZE_FILEHEADER, 1, f);
    if (numb != 1)
        return -2;
    // 0 - 1
    if (header[0] != 'B' || header[1] != 'M')
        return -3;
    bmp_head.type[0] = header[0];
    bmp_head.type[1] = header[1];

    // 2 - 5
    bmp_head.size = uInt32Number(header + 2);
    // 6 - 7
    // 8 - 9

    // 10 - 13
    offset = uInt32Number(header + 10);
    if(offset != 54)
        return -4;    

    *bitmap_pos  = offset;
    return 0;
}

static int ReadFileInfoHead(FILE* f, IMAGE * img){

    unsigned char header[BMP_SIZE_INFOHEADER];
    BMPINFOHEAD bmp_info_head;

    int numb = 0;

    if (fseek(f, BMP_SIZE_FILEHEADER, SEEK_SET))
        return -1;
    //读取bmp info head信息
    numb = fread(header, BMP_SIZE_INFOHEADER, 1, f);
    if (numb != 1)
        return -2;

    // 14 - 17
    bmp_info_head.selfSize = uInt32Number(header);
    if(bmp_info_head.selfSize != 40)
        return -3;

    // 18 - 21
    bmp_info_head.bitWidth = (long)uInt32Number(header + 4);
    // 22 - 25
    bmp_info_head.bitHeight = (long)uInt32Number(header + 8);
    // 26 - 27
    bmp_info_head.bitPlanes = (unsigned short)uInt16Number(header + 12);
    // 28 - 29
    bmp_info_head.pixelBitCount = (unsigned short)uInt16Number(header + 14);
    // 30 - 33
    bmp_info_head.compression = uInt32Number(header + 16);
    // 34 - 37
    bmp_info_head.sizeImage = uInt32Number(header + 20);
    // 38 - 41
    bmp_info_head.pixelXPerMeter = (long)uInt32Number(header + 24);
    // 42 - 45
    bmp_info_head.pixelYPerMeter = (long)uInt32Number(header + 28);
    // 46 - 49
    bmp_info_head.colorUsed = uInt32Number(header + 32);
    // 50 - 53
    bmp_info_head.colorImportant = uInt32Number(header + 36);

    img->width = bmp_info_head.bitWidth;
    img->height = bmp_info_head.bitHeight;

    return (int)(bmp_info_head.pixelBitCount);
}

int LoadBMP(const char* file, IMAGE* out_img, BITDATATYPE bit_data_type){

    FILE* f;
    int bitmap_pos;
    int n_bits;

    int flErr = 0;

    fopen_s(&f, file, "rb");

    if (!f)
        return -11;

    if (out_img == NULL)
        return -12;

    if (0 > (flErr = ReadFileHeader(f, &bitmap_pos))){
        fclose(f);
        return flErr;
    }

    n_bits = ReadFileInfoHead(f, out_img);

    if(n_bits == BMP_COLOR_BITS_24){
        int rgb_size;
        int rgba_size;
        unsigned char* rgb;
        int y;
        unsigned char* line;
        int rest_4;

        if (fseek(f, bitmap_pos, SEEK_SET)){
            fclose(f);
            return -16;
        }

        rgb_size = 3 * out_img->width;
        rgba_size = 4 * out_img->width;

        rest_4 = rgb_size % 4;
        if (rest_4 > 0)
            rgb_size += 4 - rest_4;

        if(bit_data_type == 1)
        {
            out_img->channels = 4;
            out_img->data = (unsigned char*)malloc(out_img->width * out_img->height * 4);

            if (out_img->data == NULL)
                return -17;

            rgb = (unsigned char*)malloc(rgb_size);

            if(NULL == rgb)
                return -18;

            for(y = out_img->height - 1; y >= 0; y --){
                int numb = 0;
                int x = 0;

                numb = fread(rgb, rgb_size, 1, f);
                if (numb != 1){
                    fclose(f);
                    free(rgb);
                    return -19;
                }

                numb = 0;
                line = out_img->data + out_img->width * 4 * y;
                for (x = 0; x < out_img->width ; x++){
                    line[3] = 255;
                    line[2] = rgb[numb++];
                    line[1] = rgb[numb++];
                    line[0]= rgb[numb++];
                    line += 4;
                }
            }
        }else if(bit_data_type == 2)
        {
            out_img->channels = 3;
            out_img->data = (unsigned char*)malloc(out_img->width * out_img->height * 3);

            if (out_img->data == NULL)
                return -17;

            rgb = (unsigned char*)malloc(rgb_size);

            if(NULL == rgb)
                return -18;

            for(y = out_img->height - 1; y >= 0; y --){
                int numb = 0;
                int x = 0;

                numb = fread(rgb, rgb_size, 1, f);
                if (numb != 1){
                    fclose(f);
                    free(rgb);
                    return -19;
                }

                numb = 0;
                line = out_img->data + out_img->width * 3 * y;
                for (x = 0; x < out_img->width ; x++){
                    line[2] = rgb[numb++];
                    line[1] = rgb[numb++];
                    line[0]= rgb[numb++];
                    line += 3;
                }
            }
        }
        fclose(f);
        free(rgb);
    }else if(n_bits == BMP_COLOR_BITS_32)
    {
        int rgba_size;
        unsigned char* rgba;
        int y;
        unsigned char* line;

        if (fseek(f, bitmap_pos, SEEK_SET)){
            fclose(f);
            return -16;
        }

        rgba_size = 4 * out_img->width;
        if(bit_data_type == 1)
        {
            out_img->channels = 4;
            out_img->data = (unsigned char*)malloc(out_img->width * out_img->height * 4);

            if (out_img->data == NULL)
                return -17;

            rgba = (unsigned char*)malloc(rgba_size);

            if(NULL == rgba)
                return -18;

            for (y = out_img->height - 1; y >= 0; y --){
                int numb = 0;
                int x = 0;

                numb = fread(rgba, rgba_size, 1, f);
                if (numb != 1){
                    fclose(f);
                    free(rgba);
                    return -19;
                }

                numb = 0;
                line = out_img->data + out_img->width * 4 * y;
                for (x = 0; x < out_img->width ; x++){
                    line[2] = rgba[numb++];//B
                    line[1] = rgba[numb++];//G
                    line[0] = rgba[numb++];//R
                    line[3]= rgba[numb++];//A
                    line += 4;
                }
            }
        }else if(bit_data_type == 2)
        {
            out_img->channels = 3;
            out_img->data = (unsigned char*)malloc(out_img->width * out_img->height * 3);

            if (out_img->data == NULL)
                return -17;

            rgba = (unsigned char*)malloc(rgba_size);

            if(NULL == rgba)
                return -18;

            for (y = out_img->height - 1; y >= 0; y --){
                int numb = 0;
                int x = 0;

                numb = fread(rgba, rgba_size, 1, f);
                if (numb != 1){
                    fclose(f);
                    free(rgba);
                    return -19;
                }

                numb = 0;
                line = out_img->data + out_img->width * 3 * y;
                for (x = 0; x < out_img->width ; x++){
                    line[2] = rgba[numb++];//B
                    line[1] = rgba[numb++];//G
                    line[0] = rgba[numb++];//R
                    line += 3;
                    numb ++;
                }
            }
        }
        fclose(f);
        free(rgba);
    }
    else{
        return -20;
    }
    return 0;
}

static int WriteFileHeader(FILE* f, IMAGE * in_img, BITDATATYPE bit_data_type)
{
    unsigned char header[BMP_SIZE_FILEHEADER];
    int imgWidth, imgHeight;
    int imageSize;

    int numb = 0;
    int offset = 0;

    if (fseek(f, 0, SEEK_SET))
        return -1;

    header[0] = 'B';
    header[1] = 'M';

    imgWidth = in_img->width;
    imgHeight = in_img->height;

    if(bit_data_type == 1)
    {
        imageSize = imgWidth * 4 * imgHeight + BMP_SIZE_FILEHEADER + BMP_SIZE_INFOHEADER;
    }else if(bit_data_type == 2)
    {
        int rgbSize;
        int rest_4;
        rgbSize = imgWidth * 3;
        rest_4 = rgbSize % 4;
        if (rest_4 > 0)
            rgbSize += 4 - rest_4;
        imageSize = rgbSize * imgHeight + BMP_SIZE_FILEHEADER + BMP_SIZE_INFOHEADER;
    }
    IntTo4Bytes(imageSize, header + 2);
    IntTo4Bytes(0, header + 6);
    IntTo4Bytes((BMP_SIZE_FILEHEADER + BMP_SIZE_INFOHEADER), header + 10);

    //读取bmp head信息
    numb = fwrite(header, BMP_SIZE_FILEHEADER, 1, f);
    if (numb != 1)
        return -2;

    return 0;
}

static int WriteFileInfoHead(FILE* f, IMAGE * in_img, BITDATATYPE bit_data_type){

    unsigned char header[BMP_SIZE_INFOHEADER];
    int imageSize = 0;
    int numb = 0;

    if (fseek(f, BMP_SIZE_FILEHEADER, SEEK_SET))
        return -1;
    // 14- 17
    IntTo4Bytes(BMP_SIZE_INFOHEADER, header);
    // 18 - 21 
    IntTo4Bytes(in_img->width, header + 4);
    // 22 - 25
    IntTo4Bytes(in_img->height, header + 8);
    // 26 - 27
    IntTo2Bytes(1, header + 12);
    // 28 - 29
    if(bit_data_type == 1)
    {
        IntTo2Bytes(32, header + 14);
    }else if(bit_data_type == 2)
    {
        IntTo2Bytes(24, header + 14);
    }
    // 30 - 33
    IntTo4Bytes(0, header + 16);
    // 34 - 37
     if(bit_data_type == 1)
    {
        imageSize = in_img->width * 4 * in_img->height;
    }else if(bit_data_type == 2)
    {
        int rgbSize;
        int rest_4;
        rgbSize = in_img->width * 3;
        rest_4 = rgbSize % 4;
        if (rest_4 > 0)
            rgbSize += 4 - rest_4;
        imageSize = rgbSize * in_img->height;
    }
    IntTo4Bytes(imageSize, header + 20);
    // 38 - 41
    IntTo4Bytes(0, header + 24);
    // 42 - 45
    IntTo4Bytes(0, header + 28);
    // 46 - 49
    IntTo4Bytes(0, header + 32);
    // 50 - 53
    IntTo4Bytes(0, header + 36);



    numb = fwrite(header, BMP_SIZE_INFOHEADER, 1, f);
    if (numb != 1)
        return -2;

    return 0;
}
int WriteBMP(const char * file, IMAGE * in_img, BITDATATYPE bit_data_type){
    FILE* f;

    int flErr = 0;

    fopen_s(&f, file, "wb");

    if (!f)
        return -1;

    if (in_img == NULL)
        return -2;

    if (0 != WriteFileHeader(f, in_img, bit_data_type)){
        fclose(f);
        return -3;
    }

    if(0 != WriteFileInfoHead(f, in_img, bit_data_type)){
        fclose(f);
        return -4;
    }


    if(bit_data_type == 2){
        int rgb_size;
        unsigned char * rgb;
        int y;
        unsigned char* line;
        int rest_4;

        rgb_size = 3 * in_img->width;

        rest_4 = rgb_size % 4;
        if (rest_4 > 0)
            rgb_size += 4 - rest_4;


        rgb = (unsigned char *)malloc(rgb_size * in_img->height);

        if (rgb == NULL)
            return -6;

        if(in_img->channels == 4)
        {
            for (y = 0; y < in_img->height; y ++){
                int numb = 0;
                int x = 0;

                numb = in_img->width * 4 * y;
                line = rgb + rgb_size * (in_img->height - y - 1);
                for (x = 0; x < in_img->width; x++){
                    line[2] = in_img->data[numb++];
                    line[1] = in_img->data[numb++];
                    line[0]= in_img->data[numb++];
                    line += 3;
                    numb ++;
                }
            }
        }else if(in_img->channels == 3)
        {
            for (y = 0; y < in_img->height; y ++){
                int numb = 0;
                int x = 0;

                numb = in_img->width * 3 * y;
                line = rgb + rgb_size * (in_img->height - y - 1);
                for (x = 0; x < in_img->width; x++){
                    line[2] = in_img->data[numb++];
                    line[1] = in_img->data[numb++];
                    line[0]= in_img->data[numb++];
                    line += 3;
                }
            }
        }
        if (fseek(f, (BMP_SIZE_FILEHEADER + BMP_SIZE_INFOHEADER), SEEK_SET)){
            fclose(f);
            return -5;
        }
        fwrite(rgb, rgb_size * in_img->height, 1, f); 
        fclose(f);
        free(rgb);
    }else if(bit_data_type == 1)
    {
        int rgba_size;
        unsigned char * rgba;
        int y;
        unsigned char* line;
        rgba_size = 4 * in_img->width;


        rgba = (unsigned char *)malloc(rgba_size * in_img->height);

        if (rgba == NULL)
            return -6;

        if(in_img->channels == 4)
        {
            for (y = 0; y < in_img->height; y ++){
                int numb = 0;
                int x = 0;

                numb = in_img->width * 4 * y;
                line = rgba + rgba_size * (in_img->height - y - 1);
                for (x = 0; x < in_img->width; x++){
                    line[2] = in_img->data[numb++];//R
                    line[1] = in_img->data[numb++];//G
                    line[0]= in_img->data[numb++];//B
                    line[3]= in_img->data[numb++];//A
                    line += 4;
                }
            }
        }else if(in_img->channels == 3)
        {
            for (y = 0; y < in_img->height; y ++){
                int numb = 0;
                int x = 0;

                numb = in_img->width * 3 * y;
                line = rgba + rgba_size * (in_img->height - y - 1);
                for (x = 0; x < in_img->width; x++){
                    line[2] = in_img->data[numb++];
                    line[1] = in_img->data[numb++];
                    line[0]= in_img->data[numb++];
                    line[3]= 255;
                    line += 4;
                }
            }
        }
        if (fseek(f, (BMP_SIZE_FILEHEADER + BMP_SIZE_INFOHEADER), SEEK_SET)){
            fclose(f);
            return -5;
        }
        fwrite(rgba, rgba_size * in_img->height, 1, f); 
        fclose(f);
        free(rgba);
    }
    else{
        return -20;
    }
    return 0;
}
int freeImage(IMAGE * img){
    if(img == NULL)
    {
        return -1;
    }
    if(img->data != NULL)
    {
        free(img->data);
        img->data = NULL;
        img->width = 0;
        img->height = 0;
    }
    return 0;
}

3. main.cpp 测试函数

#include <stdio.h>
#include <stdlib.h>
#include "BMP.h"

int main(void)
{
    IMAGE img;    
    LoadBMP("test002.bmp", &img, BIT24);
    WriteBMP("test003.bmp", &img, BIT24);
    freeImage(&img);
    system("pause");
    return 0;
}

如有疑问可留言

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要使用Python实现对BMP图像的处理,可以按照以下步骤进行: 1. 读取BMP图像:将BMP图像文件作为二进制文件读取并解析其文件头和像素数据。 2. 调整图像大小(Resize):使用插值算法(例如最近邻插值、双线性插值)计算新图像中每个像素的值,并生成调整后的图像。 3. 旋转图像(Rotate):通过对图像进行几何变换,将像素从原始位置移动到新的位置来实现旋转效果。 4. 保存BMP图像:将处理后的图像数据写入新的BMP文件中,并确保文件头和像素数据的正确格式。 下面是完整的Python代码示例,展示了如何实现对BMP图像的处理: ```python import struct # 读取BMP图像 def read_bmp_image(file_path): with open(file_path, 'rb') as f: # 解析文件头 file_header = f.read(14) # 解析图像信息头 info_header = f.read(40) # 获取图像的宽度和高度 width = struct.unpack('<i', info_header[4:8])[0] height = struct.unpack('<i', info_header[8:12])[0] # 读取像素数据 pixel_data = f.read() return file_header + info_header + pixel_data, width, height # 调整图像大小 def resize_image(image_data, width, height, new_width, new_height): # 实现图像大小的调整算法 return resized_image_data, new_width, new_height # 旋转图像 def rotate_image(image_data, width, height, angle): # 实现图像旋转算法 return rotated_image_data, new_width, new_height # 保存BMP图像 def save_bmp_image(file_path, image_data, width, height): with open(file_path, 'wb') as f: f.write(image_data) print('BMP图像已保存至', file_path) # 读取BMP图像 image_data, width, height = read_bmp_image('input.bmp') # 调整图像大小 resized_image_data, new_width, new_height = resize_image(image_data, width, height, 640, 480) # 旋转图像 rotated_image_data, new_width, new_height = rotate_image(resized_image_data, new_width, new_height, 90) # 保存BMP图像 save_bmp_image('output.bmp', rotated_image_data, new_width, new_height) ``` 一些
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值