diff options
Diffstat (limited to 'source/nds/bitmap.c')
-rw-r--r-- | source/nds/bitmap.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/source/nds/bitmap.c b/source/nds/bitmap.c new file mode 100644 index 0000000..bda4cf7 --- /dev/null +++ b/source/nds/bitmap.c @@ -0,0 +1,204 @@ +/* bitmap.c + * + * Copyright (C) 2010 dking <dking024@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licens e 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +//v1.1 + +#include "fs_api.h" +#include "bitmap.h" + +int BMP_read(char* filename, char *buf, unsigned int width, unsigned int height, unsigned int* type) +{ + FILE* fp; + BMPHEADER bmp_header; + int flag; + u32 bytepixel; + u32 x, y, sx, sy, m; + unsigned char *dest; + s32 fpos; + unsigned short st[54/2]; + + fp= fopen(filename, "rb"); + if(fp == NULL) + return BMP_ERR_OPENFAILURE; + + flag= fread(st, sizeof(st), 1, fp); + if(!flag) { + fclose(fp); + return BMP_ERR_FORMATE; + } + + bmp_header.bfType= st[0]; + bmp_header.bfSize= st[1] | (st[2]<<16); + bmp_header.bfReserved0= st[3]; + bmp_header.bfReserved1= st[4]; + bmp_header.bfImgoffst= st[5] | (st[6]<<16); + bmp_header.bfImghead.imHeadsize= st[7] | (st[8]<<16); + bmp_header.bfImghead.imBitmapW= st[9] | (st[10]<<16); + bmp_header.bfImghead.imBitmapH= st[11] | (st[12]<<16); + bmp_header.bfImghead.imPlanes= st[13]; + bmp_header.bfImghead.imBitpixel= st[14]; + bmp_header.bfImghead.imCompess= st[15] | (st[16]<<16); + bmp_header.bfImghead.imImgsize= st[17] | (st[18]<<16); + bmp_header.bfImghead.imHres= st[19] | (st[20]<<16); + bmp_header.bfImghead.imVres= st[21] | (st[22]<<16); + bmp_header.bfImghead.imColnum= st[23] | (st[24]<<16); + bmp_header.bfImghead.imImcolnum= st[25] | (st[26]<<16); + + if(bmp_header.bfType != 0x4D42) //"BM" + return BMP_ERR_FORMATE; + + if(bmp_header.bfImghead.imCompess != BI_RGB && + bmp_header.bfImghead.imCompess != BI_BITFIELDS) + return BMP_ERR_NEED_GO_ON; //This funciton now not support... + + bytepixel= bmp_header.bfImghead.imBitpixel >> 3; + if(bytepixel < 2) //byte per pixel >= 2 + return BMP_ERR_NEED_GO_ON; //This funciton now not support... + + *type = bytepixel; + + x= width; + y= height; + sx= bmp_header.bfImghead.imBitmapW; + sy= bmp_header.bfImghead.imBitmapH; + if(x > sx) + x= sx; + if(y > sy) + y= sy; + + //BMP scan from down to up + fpos= (s32)bmp_header.bfImgoffst; + dest= (unsigned char*)buf+(y-1)*x*bytepixel; + for(m= 0; m < y; m++) { + fseek(fp, fpos, SEEK_SET); + fread(dest, 1, x*bytepixel, fp); + fpos += ((sx*bytepixel+3)>>2)<<2; + dest -= x*bytepixel; + } + + fclose(fp); + + return BMP_OK; +} + +/* +* open BMP file +*/ +int openBMP(BMPINFO* bmpInfo, const char* file) +{ + FILE* fp; + unsigned short st[54/2]; + int len; + + bmpInfo->fp = NULL; + + fp = fopen(file, "r"); + if(NULL == fp) + return BMP_ERR_OPENFAILURE; + + len = fread((void*)st, 1, sizeof(BMPHEADER), fp); + if(len < sizeof(BMPHEADER)) { + fclose(fp); + return BMP_ERR_FORMATE; + } + + bmpInfo->bmpHead.bfType= st[0]; + bmpInfo->bmpHead.bfSize= st[1] | (st[2]<<16); + bmpInfo->bmpHead.bfReserved0= st[3]; + bmpInfo->bmpHead.bfReserved1= st[4]; + bmpInfo->bmpHead.bfImgoffst= st[5] | (st[6]<<16); + bmpInfo->bmpHead.bfImghead.imHeadsize= st[7] | (st[8]<<16); + bmpInfo->bmpHead.bfImghead.imBitmapW= st[9] | (st[10]<<16); + bmpInfo->bmpHead.bfImghead.imBitmapH= st[11] | (st[12]<<16); + bmpInfo->bmpHead.bfImghead.imPlanes= st[13]; + bmpInfo->bmpHead.bfImghead.imBitpixel= st[14]; + bmpInfo->bmpHead.bfImghead.imCompess= st[15] | (st[16]<<16); + bmpInfo->bmpHead.bfImghead.imImgsize= st[17] | (st[18]<<16); + bmpInfo->bmpHead.bfImghead.imHres= st[19] | (st[20]<<16); + bmpInfo->bmpHead.bfImghead.imVres= st[21] | (st[22]<<16); + bmpInfo->bmpHead.bfImghead.imColnum= st[23] | (st[24]<<16); + bmpInfo->bmpHead.bfImghead.imImcolnum= st[25] | (st[26]<<16); + + if(bmpInfo->bmpHead.bfType != 0x4D42) //"BM" + { + fclose(fp); + return BMP_ERR_FORMATE; + } + + if(bmpInfo->bmpHead.bfImghead.imCompess != BI_RGB && + bmpInfo->bmpHead.bfImghead.imCompess != BI_BITFIELDS) + { + fclose(fp); + return BMP_ERR_NEED_GO_ON; //This funciton now not support... + } + + bmpInfo->fp = fp; + + return BMP_OK; +} + +/* +* read pixel form BMP file +*/ +int readBMP(BMPINFO* bmpInfo, unsigned int start_x, unsigned int start_y, + unsigned int width, unsigned int height, void* buffer) +{ + unsigned int m, n; + unsigned int bmp_w, bmp_h; + int fpos; + unsigned char* dst; + unsigned int bytepixel; + + bytepixel = bmpInfo->bmpHead.bfImghead.imBitpixel >> 3; + if(bytepixel < 2) //Not support <2 bytes per pixel now + return -1; + + //BMP scan from down to up + bmp_w = bmpInfo->bmpHead.bfImghead.imBitmapW; + bmp_h = bmpInfo->bmpHead.bfImghead.imBitmapH; + if(((start_x +1) > bmp_w) || ((start_y+1) > bmp_h)) return -1; + n = bmp_w - start_x; + if(n > width) n = width; //start_x + width < bmp_w + m = bmp_h - start_y; + if(m > height) m = height; //start_y + height < bmp_h + + fpos = (int)bmpInfo->bmpHead.bfImgoffst; + + fpos += (((bmp_w*bytepixel+3)>>2)<<2)*(bmp_h - start_y -1) + start_x*bytepixel; + dst = (unsigned char*)buffer; + n *= bytepixel; + while(m--) { + fseek(bmpInfo->fp, fpos, SEEK_SET); + fread(dst, 1, n, bmpInfo->fp); + fpos -= ((bmp_w*bytepixel+3)>>2)<<2; + dst += width*bytepixel; + } + + return 0; +} + +/* +* close BMP file +*/ +void closeBMP(BMPINFO* bmpInfo) +{ + if(NULL != bmpInfo->fp) + fclose(bmpInfo->fp); +} + + |