#include "img.h"
#define __WIN32__
#ifdef __WIN32__
#include <math.h>
#include <stdio.h>
// BMP文件头
#pragma pack(push,2)
typedef struct {
uint16_t bfType; // 文件类型
uint32_t bfSize; // 文件大小
uint16_t bfReserved1; // 保留位
uint16_t bfReserved2; // 保留位
uint32_t bfOffBits; // 数据偏移位置
}BMPFILEHEADER;
#pragma pack(pop)
// BMP信息头
typedef struct {
uint32_t biSize; /*此结构大小*/
int32_t biWidth; /*图像宽度*/
int32_t biHeight; // 图像高度
uint16_t biPlanes; // 调色板数量
uint16_t biBitCount; // 每个象素对应的位数,24:24位图,32:带alpha通道的24位图
uint32_t biCompression; // 压缩
uint32_t biSizeImage; // 图像大小
int32_t biXPelsPerMeter;// 横向分辨率
int32_t biYPelsPerMeter;// 纵向分辨率
uint32_t biClrUsed; // 颜色使用数
uint32_t biClrImportant; // 重要颜色数
}BMPINFOHEADER;
/*BMP 调色板信息结构*/
typedef struct tagRGBQUAD {
uint8_t rgbBlue;
uint8_t rgbGreen;
uint8_t rgbRed;
uint8_t rgbReserved;
} RGBQUAD;
#define WIDTHBYTES(i) ((i+31)/32*4)
/*
*读取bmp格式文件,同时把24位彩色转换成256色的灰度图象
* *img: 图象数据存储对象.
* *filename: BMP文件名.
*/
static int8_t read_image_bmp_win32(image_t *img, const int8_t *filename)
{
int i, j, k, pixel_size;
uint8_t temp;
FILE *file;
BMPFILEHEADER bmpFile;
BMPINFOHEADER bmpInfo;
RGBQUAD rgb[256];
uint8_t *img_data, *ptr_cur;
uint32_t image_size,line_bytes,offset;
file = fopen(filename,"rb ");
if (file == NULL) {
printf("Open File Error \n");
return -1;
}
/*获取BMP文件头和信息头*/
rewind(file);
fread(&bmpFile, sizeof(BMPFILEHEADER), 1, file);
fread(&bmpInfo, sizeof(BMPINFOHEADER), 1, file);
/*验证文件类型 */
if (bmpFile.bfType != 0x4D42) {
printf("File Type Error \n");
fclose(file);
return -1;
}
/*获取图像色彩数 */
pixel_size = bmpInfo.biBitCount >> 3;
img->height = bmpInfo.biHeight;
img->width = bmpInfo.biWidth;
line_bytes = img->width * pixel_size + 3 - ((img->width * pixel_size + 3) & 3);
image_size = img->height * line_bytes;
img_data = (uint8_t*)malloc(image_size * sizeof(uint8_t));
if(NULL == img_data )
{
printf("malloc img_data error,not enough memory !\n");
fclose(file);
return -1;
}
img->release_image(img);
img->data = (uint8_t*)malloc(img->height * img->width);
if(NULL == img->data )
{
printf("malloc img_data error,not enough memory !\n");
free(img_data);
fclose(file);
return -1;
}
offset = 1 << bmpInfo.biBitCount;
/*读取颜色表*/
if(bmpInfo.biBitCount <= 8)
fread(rgb,4,offset,file);
/* 读取图象数据*/
fread(img_data ,1, image_size, file);
if(1 == pixel_size)/*256色BMP*/
{
for( i=0; i<img->height; ++i)
{
memcpy(img->data + img->width * i,img_data + ((img->height - i - 1) * line_bytes),img->width);
}
}
else if(3 == pixel_size)/*24位BMP*/
{
init_RGB_table();
k = 0;
/*转换RGB格式的亮度值Y*/
for (i=0; i<img->height; i++)
{
for (j=0; j<img->width; j++)
{
ptr_cur = img_data + ((img->height - i - 1) * line_bytes) + j * pixel_size;
temp = R[*(ptr_cur + 2)] + G[*(ptr_cur + 1)] + B[*ptr_cur];
memcpy(img->data + k++, &temp,1);
}
}
}
else
{
printf("is not support this colors now!\n");
}
free(img_data);
return 0;
}
/*
*保存成BMP文件(256灰度图象,即yuv格式的y值)
* *img:image_t对象.
* *filename: 文件名.
*/
static int8_t save_image_data_bmp_win32(image_t *img, const int8_t *filename)
{
FILE *fp;
uint16_t line_bytes;
// int *bmp256;
int32_t i,j,temp;
uint32_t width,height;
BMPFILEHEADER bmpheader;
BMPINFOHEADER bmpinfo;
RGBQUAD rgb[256];
width = img->width;
height = img->height;
if(!img)
{
printf("img paramer is NULL!\n");
return -1;
}
/*初始化BMP文件头和信息头*/
memset(&bmpheader,0,sizeof(BMPFILEHEADER));
memset(&bmpinfo,0,sizeof(BMPINFOHEADER));
bmpheader.bfType = 0x4D42;
bmpheader.bfSize = sizeof(BMPFILEHEADER) + sizeof(BMPINFOHEADER) + 256 * 4 + img->width * img->height * sizeof(uint8_t);
bmpheader.bfOffBits = sizeof(BMPFILEHEADER) + sizeof(BMPINFOHEADER) + 256 * 4;
bmpinfo.biBitCount = 8;
bmpinfo.biHeight = img->height;
bmpinfo.biWidth = img->width;
bmpinfo.biSize = sizeof(BMPINFOHEADER);
/*初始化RGB表*/
for(i=0; i<256; ++i)
{
rgb[i].rgbBlue = i;
rgb[i].rgbGreen = i;
rgb[i].rgbRed = i;
rgb[i].rgbReserved = 0;
}
/*新建一个bmp文件*/
fp = fopen(filename,"wb");
if (fp == NULL){
printf("can not open the file!\n");
return -1;
}
fwrite(&bmpheader,sizeof(BMPFILEHEADER),1,fp);
fwrite(&bmpinfo,sizeof(BMPINFOHEADER),1,fp);
fwrite(rgb,4,256,fp);
line_bytes = (img->width + 3) - ((img->width + 3) & 3);
for(i=0; i<img->height; ++i)
{
fwrite(img->data + (img->height - i - 1) * img->width ,1,line_bytes,fp);
}
fclose(fp);
return 0;
}
#endif
static int8_t read_image_y_bmp(image_t *img, const int8_t *filename)
{
#ifdef __WIN32__
return read_image_bmp_win32(img,filename);
#else
return 0;
#endif
}
static int8_t save_image_data_bmp(image_t *img, const int8_t *filename)
{
#ifdef __WIN32__
return save_image_data_bmp_win32(img, filename);
#else
return 0;
#endif
}
/*
*默认初始化回调函数
* *img: 初始化对象.
*/
void init_image_callback_bmpio(image_t *img)
{
img->read_image = read_image_y_bmp;
img->save_image = save_image_data_bmp;
}