mirror of
https://github.com/ShadauxCat/CATSFC.git
synced 2025-04-02 10:41:47 -04:00
204 lines
5.5 KiB
C
204 lines
5.5 KiB
C
/* 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);
|
|
}
|
|
|
|
|