/*
* $Id: ddlist.h,v1.0 2007/8/2 09:41:16 bolidhi Exp $ * * heap.h: the private heap header. * * Copyright (C) 2006 ~ 2008 bolidehi <bolidehi@163.com>. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include "lib_type.h" #include "read_bmp.h" #define BI_RGB 0x00L #define BI_RLE8 0x01L #define BI_RLE4 0x02L #define BI_BITFIELDS 0x03L typedef unsigned char BYTE; typedef signed char SBYTE; typedef unsigned short WORD; typedef signed short SWORD; typedef unsigned short USHORT; typedef signed short SHORT; typedef unsigned int DWORD; typedef signed int SDWORD; typedef unsigned int UINT; typedef unsigned long ULONG; typedef signed long SLONG; /*bitmap file header structure*/ typedef struct _file_header file_header; struct _file_header { BYTE type[2]; //bitmap file type; DWORD size; //bitmap file size; WORD reserved1; WORD reserved2; DWORD offset; }; #define FILE_HEADER_SIZE 14 /*bitmap windows information head structure*/ typedef struct _info_head info_head; struct _info_head { DWORD size; DWORD width; DWORD height; WORD planes; WORD bitcount; DWORD compression; DWORD sizeimage; DWORD xpixelspermeter; DWORD ypixelspermeter; DWORD colorused; DWORD colorimportant; }; #define INFO_HEAD_SIZE 40 /*bitmap os2 information head structure*/ typedef struct _core_head core_head; struct _core_head { DWORD size; WORD width; WORD height; WORD planes; WORD bitcount; } ; #define CORE_HEAD_SIZE 12 #define wswap(x) (x) #define dwswap(x) (x) #define dwread(addr)((((unsigned char *)(addr))[0] | \ (((unsigned char *)(addr))[1] << 8) | \ (((unsigned char *)(addr))[2] << 16) | \ (((unsigned char *)(addr))[3] << 24))) #define _ROUND8(n) (((n) +7) /8) /** * read_image_buf: read image buffer to dest in specices size * @img_buf : device image buffer; * @dest :destion buffers * @size : size of reader buffer; * return the real readed size */ size_t read_image_buf(img_buffer *img_buf, void *dest, size_t size) { size_t ret; if(eof_image_buf(img_buf)) return 0; ret = img_buf->offset + size > img_buf->size ? img_buf->size - img_buf->offset : size; memcpy(dest, (char *)(img_buf->start)+img_buf->offset, size); //DBG_INFO("dest=%s--buf=%s--start=%d--offset=%d--size=%d\n",(char *)dest, ((char *)(img_buf->start) + img_buf->offset), (char *)(img_buf->start), img_buf->offset, (size_t)size); img_buf->offset += size; return ret; } /** * seek_image_buf: seek image buffer to dest in specices size * @img_buf : device image buffer; * @offset : seeked offset * @whence : seeked postion * return seeked postion */ int seek_image_buf(img_buffer *img_buf, size_t offset, int whence) { int pos; switch(whence) { case SEEK_SET: if(offset >= img_buf->size || offset < 0) return -1; img_buf->offset = offset; break; case SEEK_CUR: pos = img_buf->size + offset; if(pos >= img_buf->size || pos < 0) return -1; img_buf->offset = pos; break; case SEEK_END: pos= img_buf->size + offset - 1; if (pos >= img_buf->size || pos < 0) return -1L; img_buf->offset = pos; break; default: return - 1; } return img_buf->offset; } static void calc_pitch(int bpp, int width, int height, unsigned int *pitch) { int linesize=0; switch(bpp) { case 1: linesize = _ROUND8(width); break; case 2: linesize = _ROUND8(width << 1); break; case 4: linesize = _ROUND8(width << 2); break; case 8: linesize = width; break; case 16: linesize = width * 2; break; case 24: linesize = width * 3; break; case 32: linesize = width * 4; break; } *pitch = (linesize + 3) & ~3; DBG_INFO("linesize = %d--pitch=%d\n",linesize, *pitch); } static int decode_RLE8(BYTE *buf, img_buffer *img_buf) { int c, n; BYTE *p = buf; for( ;;) { switch( n = getc_image_buf(img_buf)) { case EOF: return 0; case 0: /* 0 = escape*/ switch( n = getc_image_buf(img_buf)) { case 0: /* 0 0 = end of current scan line*/ case 1: /* 0 1 = end of data*/ return 1; case 2: /* 0 2 xx yy delta mode NOT SUPPORTED*/ getc_image_buf(img_buf); getc_image_buf(img_buf); continue; default: /* 0 3..255 xx nn uncompressed data*/ for( c=0; c<n; c++) *p++ = getc_image_buf(img_buf); if( n & 1) getc_image_buf(img_buf); continue; } default: c = getc_image_buf(img_buf); while( n--) *p++ = c; continue; } } } static BYTE *p; static int once; static __inline void put4(int b) { static int last; last = (last << 4) | b; if(++once ==2) { *p ++ = last; once = 0; } } static int decode_RLE4(BYTE *buf, img_buffer *img_buf) { int c, n, c1, c2; p = buf; once = 0; c1 = 0; for (;;) { switch (n = getc_image_buf(img_buf)) { case EOF: return 0; case 0: /* 0 = escape */ switch (n = getc_image_buf(img_buf)) { case 0: /* 0 0 = end of current scan line */ case 1: /* 0 1 = end of data */ if (once) put4(0); return 1; case 2: /* 0 2 xx yy delta mode NOT SUPPORTED */ getc_image_buf(img_buf); getc_image_buf(img_buf); continue; default: /* 0 3..255 xx nn uncompressed data */ c2 = (n + 3) & ~3; for (c = 0; c < c2; c++) { if ((c & 1) == 0) c1 = getc_image_buf(img_buf); if (c < n) put4((c1 >> 4) & 0x0f); c1 <<= 4; } continue; } default: c = getc_image_buf(img_buf); c1 = (c >> 4) & 0x0f; c2 = c & 0x0f; for (c = 0; c < n; c++) put4((c & 1) ? c2 : c1); continue; } } } int read_bmp(IMAGEHEADER *image, void *buffer, size_t size) { int h, compression =0 ; int headsize; file_header fheader; info_head ihead; core_head chead; img_buffer img_buf; BYTE head_buf[INFO_HEAD_SIZE]; BYTE *data = NULL; init_image_buf(&img_buf, buffer, size); if(read_image_buf(&img_buf, &head_buf, FILE_HEADER_SIZE) != FILE_HEADER_SIZE) { image->type = 0; return 1; } fheader.type[0] = head_buf[0]; fheader.type[1] = head_buf[1]; if(*((WORD *)(&fheader.type)) != wswap(0x4D42)) //0x4D42='BM' { image->type = 0; DBG_INFO(" This is not bitmap image\n"); return 1; } fheader.offset = dwswap(dwread(&head_buf[10])); if(read_image_buf(&img_buf, &headsize, sizeof(int)) != sizeof(int)) { image->type =0; return 1; } headsize = dwswap(headsize); if(headsize == CORE_HEAD_SIZE) { /* read os/2 header */ if(read_image_buf(&img_buf,&head_buf, CORE_HEAD_SIZE - sizeof(DWORD)) != CORE_HEAD_SIZE - sizeof(DWORD)) { return 1; } chead.width = wswap(*((WORD *)&head_buf[0])); chead.height = wswap(*((WORD *)&head_buf[2])); chead.planes = wswap(*((WORD *)&head_buf[4])); chead.bitcount = wswap(*((WORD *)&head_buf[6])); image->width = (int)chead.width; image->depth = (int)chead.height; image->bpp = chead.bitcount; compression = BI_RGB; } else { /* read windows header */ if(read_image_buf(&img_buf,&head_buf, INFO_HEAD_SIZE - sizeof(DWORD)) != INFO_HEAD_SIZE - sizeof(DWORD)) { return 1; } ihead.width = dwswap(*((DWORD*)&head_buf[0])); ihead.height = dwswap(*((DWORD*)&head_buf[4])); ihead.planes = dwswap(*((DWORD*)&head_buf[8])); ihead.bitcount = dwswap(*((DWORD*)&head_buf[10])); ihead.compression= dwswap(*((DWORD*)&head_buf[12])); ihead.sizeimage = dwswap(*((DWORD*)&head_buf[16])); ihead.xpixelspermeter = dwswap(*((DWORD*)&head_buf[20])); ihead.ypixelspermeter = dwswap(*((DWORD*)&head_buf[24])); ihead.colorused = dwswap(*((DWORD*)&head_buf[28])); ihead.colorimportant = dwswap(*((DWORD*)&head_buf[32])); image->width = (int)ihead.width; image->depth = (int)ihead.height; image->bpp = ihead.bitcount; //image->pal_size =(int)ihead.colorused; compression = ihead.compression; } if(image->bpp > 8 && image->bpp!=24) { DBG_INFO("load_bmp: image bpp is not 1 4 8 or 24\n"); return 1; } /*compreession = IMG_BGR; image->planes = 1;*/ //image->type = IMAGE_TYPE_BMP; calc_pitch(image->bpp, image->width, image->depth, &image->bytewidth); /* Allocate image */ image->data =(BYTE*) malloc(image->bytewidth * image->depth); if(image->data == NULL) { DBG_INFO(" Allocate image data failed\n"); goto err; } #if 0 if(image->bpp <= 8) { image->pal_tabs =(palette *)malloc(image->pal_size * sizeof(palette)); if(!image->pal_tabs) goto err; /* get colormap*/ for(i =0; i<image->pal_size;i++) { image->pal_tabs[i].b = getc_image_buf(&img_buf); image->pal_tabs[i].g = getc_image_buf(&img_buf); image->pal_tabs[i].r = getc_image_buf(&img_buf); if(headsize !=CORE_HEAD_SIZE) getc_image_buf(&img_buf); } } #endif /* decode image data*/ seek_image_buf(&img_buf, fheader.offset, SEEK_SET); h = image->depth; //data = image->data + (h-1)* image->bytewidth ; data = image->data; switch(compression) { case BI_RLE8: while(--h>=0) { if(!decode_RLE8(data, &img_buf)) break; //data -= image->bytewidth ; data += image->bytewidth ; } break; case BI_RLE4: while(--h>=0) { if(!decode_RLE4(data, &img_buf)) break; //data -= image->bytewidth ; data += image->bytewidth ; } break; default: while(--h>=0) { //DBG_INFO("---width=%d---\n",image->bytewidth); if(read_image_buf(&img_buf, data, image->bytewidth) != image->bytewidth) goto err; //data -= image->bytewidth ; data += image->bytewidth ; } break; } return 0; err: DBG_INFO("loadbmp:load image error\n"); if(image->data) { free(image->data); } /* if(image->pal_tabs) { free(image->pal_tabs); image->pal_size = 0; }*/ return 1; } int cetc_renderbmp(IMAGEHEADER *p_img, const char *filename) { int fd; struct stat st; void *buff; int ret; DBG_INFO( "Enter \n"); if(filename !=NULL && *filename !='\0') { fd = open(filename, O_RDONLY, 0); if(fd == -1) { DBG_INFO(" Open file %s failed\n", filename); return 1; } if(0 != fstat(fd, &st)) { DBG_INFO(" Get fd %d stat information failed\n", fd); return 1; } buff = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if((int)buff == -1) { DBG_INFO(" mmap the fd %d failed\n", fd); return 1; } ret = read_bmp(p_img, buff, st.st_size); // DBG_INFO("p_img->data=%s\n",p_img->data); munmap(buff, st.st_size); close(fd); return ret; } DBG_INFO(" Leave\n"); return 1; } |
|
来自: ColonelLee > 《解决之道》