C语言读取bmp位图文件(含bmp格式定义)

loadbmp.h

#ifndef _LOADBMP_H_
#define _LOADBMP_H_
typedef unsigned char    BYTE;
typedef unsigned short    WORD;
typedef unsigned long    DWORD;

typedef struct {
    /* BITMAPFILEHEADER*/
    BYTE    bfType[2];
    DWORD    bfSize;
    WORD    bfReserved1;
    WORD    bfReserved2;
    DWORD    bfOffBits;
} BMPFILEHEAD;

#define FILEHEADSIZE 14

/* windows style*/
typedef struct {
    /* BITMAPINFOHEADER*/
    DWORD    BiSize;
    DWORD    BiWidth;
    DWORD    BiHeight;
    WORD    BiPlanes;
    WORD    BiBitCount;
    DWORD    BiCompression;
    DWORD    BiSizeImage;
    DWORD    BiXpelsPerMeter;
    DWORD    BiYpelsPerMeter;
    DWORD    BiClrUsed;
    DWORD    BiClrImportant;
} BMPINFOHEAD;

#define INFOHEADSIZE 40

typedef struct _BMP {
    BMPINFOHEAD info;
    unsigned char *rgba;
    unsigned char *yuy2;
    unsigned char *yv12;
} BMP, *PBMP;

int LoadBMP(char *name, PBMP pbmp);
int ReleaseBMP(PBMP pbmp);
void rgb_to_yuv(unsigned int r, unsigned int g, unsigned int b,
    unsigned int *y, unsigned int *u, unsigned int *v);
#endif/*_LOADBMP_H_*/

loadbmp.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#include "loadbmp.h"

void rgb_to_yuv(unsigned int r, unsigned int g, unsigned int b,
    unsigned int *y, unsigned int *u, unsigned int *v)
{
    double dy, du, dv;

    dy = (0.257 * (double)r) +
        (0.504 * (double)g) + (0.098 * (double)b) + 16.0;
    dv= (0.439 * (double)r) - (0.368 * (double)g) - (0.071 * (double)b) +
        128.0;
    du = -(0.148 * (double)r) - (0.291 * (double)g) +
        (0.439 * (double)b) + 128.0;

    *y = (unsigned int)dy & 0xff;
    *v = (unsigned int)dv & 0xff;
    *u = (unsigned int)du & 0xff;
}

static void
convert_to_yv12(PBMP pbmp)
{
    int x, y;
    unsigned char *in_ptr, *out_ptr_y, *out_ptr_u, *out_ptr_v;
    unsigned int Y, U, V;

    in_ptr = pbmp->rgba;
    out_ptr_y = pbmp->yv12;
    out_ptr_u = out_ptr_y + pbmp->info.BiWidth * pbmp->info.BiHeight;
    out_ptr_v = out_ptr_u + pbmp->info.BiWidth * pbmp->info.BiHeight / 4;
    for (y = 0; y < pbmp->info.BiHeight; y++) {
        for (x = 0; x < pbmp->info.BiWidth; x++) {
            rgb_to_yuv(in_ptr[0], in_ptr[1], in_ptr[2], &Y, &U, &V);
            in_ptr += pbmp->info.BiBitCount / 8;
            *out_ptr_y++ = Y;
            if (x % 2 == 0 && y % 2 == 0) {
                *out_ptr_u++ = V;
                *out_ptr_v++ = U;
            }
        }
    }
}

static void
convert_to_yuy2(PBMP pbmp)
{
    int x, y;
    unsigned char *in, *out;
    unsigned int Y, U, V;

    in = pbmp->rgba;
    out = pbmp->yuy2;
    for (y = 0; y < pbmp->info.BiHeight; y++) {
        for (x = 0; x < pbmp->info.BiWidth; x++) {
            static int cnt = 0;
            rgb_to_yuv(in[0], in[1], in[2], &Y, &U, &V);
            in += pbmp->info.BiBitCount / 8;
            *(out) = Y;
            if (cnt %2 == 0)
                *(out+1) = V;
            else
                *(out+1) = U;
            out+= 2;
            cnt++;
        }
    }
}

int LoadBMP(char *name, PBMP pbmp)
{
    int        fd;
    int        headsize;
    BMPFILEHEAD    bmpf;
    unsigned char     headbuffer[INFOHEADSIZE];

    fd = open(name, O_RDONLY);
    if (fd < 0) {
        perror("open");
        return -1;
    }

    read(fd, &headbuffer, FILEHEADSIZE);
    bmpf.bfType[0] = headbuffer[0];
    bmpf.bfType[1] = headbuffer[1];
    if (*(WORD*)&bmpf.bfType[0] != 0x4D42) /* 'BM' */
        return -2;    /* not bmp image*/

    bmpf.bfOffBits = *((DWORD*)&headbuffer[10]);

    if (read(fd,&headsize,sizeof(DWORD)) != sizeof(DWORD))
        return 0;    /* not bmp image*/

    read(fd, &headbuffer, INFOHEADSIZE - sizeof(DWORD));
    pbmp->info.BiWidth = *(DWORD*)(&headbuffer[0]);
    pbmp->info.BiHeight = *(DWORD*)(&headbuffer[4]);
    pbmp->info.BiBitCount = *(DWORD*)(&headbuffer[10]);
    pbmp->info.BiSizeImage = *(DWORD*)(&headbuffer[16]);

    pbmp->rgba = (unsigned char *)malloc(pbmp->info.BiSizeImage);
    if (!pbmp->rgba) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
//    pbmp->yuy2 = (unsigned char *)malloc(pbmp->info.BiWidth * pbmp->info.BiHeight * 2);
//    if (!pbmp->yuy2) {
//        perror("malloc");
//        exit(EXIT_FAILURE);
//    }
//    pbmp->yv12 = (unsigned char *)malloc(pbmp->info.BiWidth * pbmp->info.BiHeight * 3 / 2);
//    if (!pbmp->yv12) {
//        perror("malloc");
//        exit(EXIT_FAILURE);
//    }

    lseek(fd, bmpf.bfOffBits, SEEK_SET);
    if (read(fd, pbmp->rgba, pbmp->info.BiSizeImage) != pbmp->info.BiSizeImage) {
        perror("read");
        return -4;
    }

//    convert_to_yv12(pbmp);
//    convert_to_yuy2(pbmp);
    printf("LoadBMP: %s %ldx%ldx%d\n", name, pbmp->info.BiWidth, pbmp->info.BiHeight, pbmp->info.BiBitCount);
    close(fd);

    return 0;
}

int ReleaseBMP(PBMP pbmp)
{
    if (pbmp->rgba) {
        free(pbmp->rgba);
        pbmp->rgba = NULL;
    }
//    if (pbmp->yuy2) {
//        free(pbmp->yuy2);
//        pbmp->yuy2 = NULL;
//    }
//    if (pbmp->yv12) {
//        free(pbmp->yv12);
//        pbmp->yv12 = NULL;
//    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C语言程序,用于读取一个bmp文件,并将其灰度值保存到一个数组中: ```c #include <stdio.h> #include <stdlib.h> #include <stdint.h> // 位图文件头结构体 typedef struct { uint16_t bfType; // 位图文件类型,必须为"BM" uint32_t bfSize; // 位图文件大小,以字节为单位 uint16_t bfReserved1; // 保留,必须为0 uint16_t bfReserved2; // 保留,必须为0 uint32_t bfOffBits; // 从文件头到像素数据的偏移量,以字节为单位 } BITMAPFILEHEADER; // 位图信息头结构体 typedef struct { uint32_t biSize; // 位图信息头大小,以字节为单位 int32_t biWidth; // 图像宽度,以像素为单位 int32_t biHeight; // 图像高度,以像素为单位 uint16_t biPlanes; // 必须为1 uint16_t biBitCount; // 每个像素的位数,必须是1, 4, 8或24 uint32_t biCompression; // 压缩类型,0为不压缩 uint32_t biSizeImage; // 图像大小,以字节为单位 int32_t biXPelsPerMeter; // 水平分辨率,以像素/米为单位 int32_t biYPelsPerMeter; // 垂直分辨率,以像素/米为单位 uint32_t biClrUsed; // 实际使用的调色板索引数,0为使用所有调色板索引 uint32_t biClrImportant; // 对图像显示有重要影响的颜色索引数,0表示所有颜色都是重要的 } BITMAPINFOHEADER; // 读取位图文件头 BITMAPFILEHEADER read_file_header(FILE* fp) { BITMAPFILEHEADER header; fread(&header.bfType, sizeof(header.bfType), 1, fp); fread(&header.bfSize, sizeof(header.bfSize), 1, fp); fread(&header.bfReserved1, sizeof(header.bfReserved1), 1, fp); fread(&header.bfReserved2, sizeof(header.bfReserved2), 1, fp); fread(&header.bfOffBits, sizeof(header.bfOffBits), 1, fp); return header; } // 读取位图信息头 BITMAPINFOHEADER read_info_header(FILE* fp) { BITMAPINFOHEADER header; fread(&header.biSize, sizeof(header.biSize), 1, fp); fread(&header.biWidth, sizeof(header.biWidth), 1, fp); fread(&header.biHeight, sizeof(header.biHeight), 1, fp); fread(&header.biPlanes, sizeof(header.biPlanes), 1, fp); fread(&header.biBitCount, sizeof(header.biBitCount), 1, fp); fread(&header.biCompression, sizeof(header.biCompression), 1, fp); fread(&header.biSizeImage, sizeof(header.biSizeImage), 1, fp); fread(&header.biXPelsPerMeter, sizeof(header.biXPelsPerMeter), 1, fp); fread(&header.biYPelsPerMeter, sizeof(header.biYPelsPerMeter), 1, fp); fread(&header.biClrUsed, sizeof(header.biClrUsed), 1, fp); fread(&header.biClrImportant, sizeof(header.biClrImportant), 1, fp); return header; } // 读取位图像素数据,返回灰度值数组 unsigned char* read_pixels(FILE* fp, BITMAPINFOHEADER info_header) { // 计算每一行像素占用的字节数 int row_bytes = (info_header.biBitCount * info_header.biWidth + 31) / 32 * 4; // 分配内存并读取像素数据 unsigned char* pixels = (unsigned char*)malloc(info_header.biHeight * info_header.biWidth); int i, j; for (i = 0; i < info_header.biHeight; i++) { // 计算当前行的灰度值,并保存到数组中 for (j = 0; j < info_header.biWidth; j++) { unsigned char bgr[3]; fread(bgr, 1, 3, fp); pixels[i * info_header.biWidth + j] = 0.299 * bgr[2] + 0.587 * bgr[1] + 0.114 * bgr[0]; } // 跳过当前行的填充字节 fseek(fp, row_bytes - info_header.biWidth * 3, SEEK_CUR); } return pixels; } int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: %s filename\n", argv[0]); return 1; } FILE* fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Failed to open file: %s\n", argv[1]); return 1; } BITMAPFILEHEADER file_header = read_file_header(fp); BITMAPINFOHEADER info_header = read_info_header(fp); printf("Image size: %dx%d\n", info_header.biWidth, info_header.biHeight); unsigned char* pixels = read_pixels(fp, info_header); // 在这里,灰度值数组已经读取完毕,可以进行后续处理了 // ... free(pixels); fclose(fp); return 0; } ``` 注意,上面的程序只能处理24位真彩色位图,对于其他格式bmp文件可能会出错,需要进行适当的修改。同时,需要注意读取像素数据时跳过的填充字节,以及灰度值的计算方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值