
fbv -- simple image viewer for the linux framebuffer
Copyright (C) 2002 Tomasz Sterna
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#ifdef FBV_SUPPORT_BMP
#include "fbv.h"
#include #include #include #include #define BMP_TORASTER_OFFSET10 #define BMP_SIZE_OFFSET18 #define BMP_BPP_OFFSET28 #define BMP_RLE_OFFSET30 #define BMP_COLOR_OFFSET54 #define fill4B(a)( ( 4 - ( (a) % 4 ) ) & 0x03) struct color { unsigned char red; unsigned char green; unsigned char blue; }; int fh_bmp_id(char *name)//读取位图头信息,判断是否为"BM" { int fd; char id[2]; fd = open(name, O_RDONLY);//打开文件 if (fd == -1) { return(0); } read(fd, id, 2); close(fd); if ( id[0]=='B' && id[1]=='M' ) { return(1); } return(0); } void fetch_pallete(int fd, struct color pallete[], int count)//获取调色板信息 { unsigned char buff[4]; int i; lseek(fd, BMP_COLOR_OFFSET, SEEK_SET);//fd,28,SEEK_SET:参数28为新的读写位置 for (i=0; i pallete[i].red = buff[2]; pallete[i].green = buff[1]; pallete[i].blue = buff[0]; } return; } int fh_bmp_load(char *name,unsigned char *buffer, unsigned char **alpha, int x,int y) { #if 1 int fd, bpp, raster, i, j, k, skip; unsigned char buff[4]; unsigned char *wr_buffer = buffer + x*(y-1)*3; struct color pallete[256]; fd = open(name, O_RDONLY); if (fd == -1) { return(FH_ERROR_FILE); } if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1) {//从文件10处开始读写 return(FH_ERROR_FORMAT); } read(fd, buff, 4); raster = buff[0] + (buff[1]<<8) + (buff[2]<<16) + (buff[3]<<24);//由上面可知:从bfOffBits //开始四个字节:每一行扫描的字节数? if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1) { return(FH_ERROR_FORMAT); } read(fd, buff, 2); bpp = buff[0] + (buff[1]<<8);//可得biBitCount(从28开始2个字节) switch (bpp){ case 1: /* monochrome 单色 */ skip = fill4B(x/8+(x%8?1:0)); /*#define fill4B(a)( ( 4 - ( (a) % 4 ) ) & 0x03) 1.BMP文件记录一行 图像是以字节为单位的。因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。也就是说, 设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节, 这个字节的后4位将没有意义。接下来的一个字节将开始记录下一行的信息。 2.为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。 如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节 (加1是因为里面有一个像素点要独占了一字节)。如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。 */ lseek(fd, raster, SEEK_SET); for (i=0; i for (k=0; k<8; k++) { if (buff[0] & 0x80) { *wr_buffer++ = 0xff; *wr_buffer++ = 0xff; *wr_buffer++ = 0xff; } else { *wr_buffer++ = 0x00; *wr_buffer++ = 0x00; *wr_buffer++ = 0x00; } buff[0] = buff[0]<<1; } } if (x%8) { read(fd, buff, 1); for (k=0; k *wr_buffer++ = 0xff; *wr_buffer++ = 0xff; *wr_buffer++ = 0xff; } else { *wr_buffer++ = 0x00; *wr_buffer++ = 0x00; *wr_buffer++ = 0x00; } buff[0] = buff[0]<<1; } } if (skip) { read(fd, buff, skip); } wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */ } break; case 4: /* 4bit palletized */ skip = fill4B(x/2+x%2);//#define fill4B(a)( ( 4 - ( (a) % 4 ) ) & 0x03) fetch_pallete(fd, pallete, 16); lseek(fd, raster, SEEK_SET); for (i=0; i buff[1] = buff[0]>>4; buff[2] = buff[0] & 0x0f; *wr_buffer++ = pallete[buff[1]].red; *wr_buffer++ = pallete[buff[1]].green; *wr_buffer++ = pallete[buff[1]].blue; *wr_buffer++ = pallete[buff[2]].red; *wr_buffer++ = pallete[buff[2]].green; *wr_buffer++ = pallete[buff[2]].blue; } if (x%2) { read(fd, buff, 1); buff[1] = buff[0]>>4; *wr_buffer++ = pallete[buff[1]].red; *wr_buffer++ = pallete[buff[1]].green; *wr_buffer++ = pallete[buff[1]].blue; } if (skip) { read(fd, buff, skip); } wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */ } break; case 8: /* 8bit palletized */ skip = fill4B(x); fetch_pallete(fd, pallete, 256); lseek(fd, raster, SEEK_SET); for (i=0; i *wr_buffer++ = pallete[buff[0]].red; *wr_buffer++ = pallete[buff[0]].green; *wr_buffer++ = pallete[buff[0]].blue; } if (skip) { read( fd, buff, skip); } wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */ } break; case 16: /* 16bit RGB */ return(FH_ERROR_FORMAT); break; case 24: /* 24bit RGB */ skip = fill4B(x*3); lseek(fd, raster, SEEK_SET); for (i=0; i *wr_buffer++ = buff[2]; *wr_buffer++ = buff[1]; *wr_buffer++ = buff[0]; } if (skip) { read(fd, buff, skip); } wr_buffer -= x*6; /* backoff 2 lines - x*2 *3 */ } break; default: return(FH_ERROR_FORMAT); } close(fd); return(FH_ERROR_OK); #endif } int fh_bmp_getsize(char *name,int *x,int *y) { int fd; unsigned char size[4]; fd = open(name, O_RDONLY); if (fd == -1) { return(FH_ERROR_FILE);//宏定义FH_ERROR_FILE 1; 见fbv.h } if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) {//BMP_SIZE_OFFSET :28 return(FH_ERROR_FORMAT);//FH_ERROR_FORMAT:2 } read(fd, size, 4); *x = size[0] + (size[1]<<8) + (size[2]<<16) + (size[3]<<24); //*x-=1; read(fd, size, 4); *y = size[0] + (size[1]<<8) + (size[2]<<16) + (size[3]<<24); close(fd); return(FH_ERROR_OK); } #endif
