hereson3 发表于 2013-2-4 21:08:17

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;
      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, in_ptr, in_ptr, &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, in, in, &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;

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

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

      bmpf.bfOffBits = *((DWORD*)&headbuffer);

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

      read(fd, &headbuffer, INFOHEADSIZE - sizeof(DWORD));
      pbmp->info.BiWidth = *(DWORD*)(&headbuffer);
      pbmp->info.BiHeight = *(DWORD*)(&headbuffer);
      pbmp->info.BiBitCount = *(DWORD*)(&headbuffer);
      pbmp->info.BiSizeImage = *(DWORD*)(&headbuffer);

      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;
}
页: [1]
查看完整版本: C语言读取bmp位图文件(含bmp格式定义)