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;
}