/******************************************************************
* memBMP.cpp
*
* Written by: Shuhua Lai
* Modified by: Fuhua (Frank) Cheng
*
* Permission to use, copy, modify, and distribute this file for
* commercial usage is prohibited without prior permission of the
* author.
*
* THE MATERIAL EMBODIED ON THIS PROGRAM IS PROVIDED TO YOU "AS-IS"
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE.
*******************************************************************/
#include "memBMP.h"
memBitmap::~memBitmap() {
if(bData)
delete bData;
}
memBitmap::memBitmap() {
bitData = NULL;
bData = NULL;
}
memBitmap::memBitmap(int ImageWidth,int ImageHeight) {
bitData = NULL;
bData = NULL;
CreateDirect(ImageWidth, ImageHeight);
}
int memBitmap::HugeRead(int fd,void* buf, int len) {
int tem=0;
int offset=0;
while((tem=read(fd,(char*)buf+offset,len-offset))>0)
{
offset+=tem;
}
return offset;
}
int memBitmap::HugeWrite(int fd, void* buf, int len) {
int tem = 0;
int offset =0;
while((tem = write( fd, (char*)buf+offset, len-offset)) >0)
offset +=tem;
return offset;
}
BOOL memBitmap::CreateDirect(int ImageWidth,int ImageHeight) {
Release();
BytesPerLine=ImageWidth*3;
if(BytesPerLine%4!=0)BytesPerLine=(BytesPerLine/4+1)*4;
lenth=long(ImageHeight)*BytesPerLine;
bData=new BYTE[lenth+54L];
if(!bData)
{
AfxMessageBox("Failed in malloc");
return FALSE;
}
biWidth=ImageWidth;
biHeight=ImageHeight;
biSize=40;
WORD bmptemp=(WORD)'M';
bmptemp<<=8;
bmptemp|=(BYTE)'B';
bfType=bmptemp;
bfOffBits=54;
bfReserved1=0;
bfReserved2=0;
biPlanes=1;
biBitCount=24;
biCompression=0;
biXPelsPerMeter=0;
biYPelsPerMeter=0;
biClrUsed=0;
biClrImportant=0;
bitData=bData+54;
biSizeImage=lenth;
bfSize=lenth+54;
return TRUE;
}
void memBitmap::SetInfo() {
BYTE *temp;
temp = (BYTE *)&bfType;
SETWV(temp,bData);
temp = (BYTE *)&bfSize;
SETLV(temp,bData+2);
temp = (BYTE *)&bfReserved1;
SETWV(temp,bData+6);
temp = (BYTE *)&bfReserved2;
SETWV(temp,bData+8);
temp = (BYTE *)&bfOffBits;
SETLV(temp,bData+10);
temp = (BYTE *)&biSize;
SETLV(temp,bData+14);
temp = (BYTE *)&biWidth;
SETLV(temp,bData+18);
temp = (BYTE *)&biHeight;
SETLV(temp,bData+22);
temp = (BYTE *)&biPlanes;
SETWV(temp,bData+26);
temp = (BYTE *)&biBitCount;
SETWV(temp,bData+28);
temp = (BYTE *)&biCompression;
SETLV(temp,bData+30);
temp = (BYTE *)&biSizeImage;
SETLV(temp,bData+34);
temp = (BYTE *)&biXPelsPerMeter;
SETLV(temp,bData+38);
temp = (BYTE *)&biYPelsPerMeter;
SETLV(temp,bData+42);
temp = (BYTE *)&biClrUsed;
SETLV(temp,bData+46);
temp = (BYTE *)&biClrImportant;
SETLV(temp,bData+50);
}
BOOL memBitmap::Load(LPCTSTR filename) {
char str[256];
char temp;
int numchar;
strcpy(str,filename);
if(strstr(str,".bmp") != NULL)
{
int fd;
if((fd = open(str,FILEMODE)) ==-1)
{
AfxMessageBox("Cannot open file");
return FALSE;
}
unsigned long int FileLenth = 0;
BYTE *FileData;
// lseek(fd,0L,SEEK_END);
while ((numchar = read(fd, &temp, sizeof(unsigned char)*100)) > 0)
{
FileLenth += numchar;
}
// printf ("FileLenth = %d", FileLenth);
// FileLenth=907254;
// FileLenth=tell(fd);
lseek(fd,0L,SEEK_SET);
lenth=FileLenth;
FileData=new BYTE[lenth];
bData=FileData;
if(!FileData)
{
AfxMessageBox("Failed in malloc");
return FALSE;
}
if(!HugeRead(fd,FileData,FileLenth))
{
AfxMessageBox("Error in reading file");
return FALSE;
}
SetInfo();
bitData=bData+54;
if(((unsigned char)bfType!='B')||
((unsigned char)(bfType>>8)!='M') )
{
AfxMessageBox("Not a correct Bmp file");
return FALSE;
}
close(fd);
if(biCompression!=0)
{
AfxMessageBox("No support for compresion file");
return FALSE;
}
BytesPerLine=biWidth*(biBitCount/8);
if(BytesPerLine%4!=0)BytesPerLine=(BytesPerLine/4+1)*4;
if(biBitCount==24)return TRUE;
else if(biBitCount==8)
{
BYTE Palette[256][3];
BYTE *ImageData=bData+bfOffBits;
int i,j;
for(i=0;i<256;i++)
{
for(j=0;j<3;j++)
{
Palette[i][j]=*(bitData+i*4+j);
}
}
int width=biWidth;
int height=biHeight;
int OldBytes=BytesPerLine;
CreateDirect(width,height);
for(j=0;j>=4;
Index&=0xf;
}
BYTE b=Palette[Index][0];
BYTE g=Palette[Index][1];
BYTE r=Palette[Index][2];
SetPixel(i,height-j-1,RGB(r,g,b));
}
}
delete FileData;
return TRUE;
}
else if(biBitCount==1)
{
BYTE Palette[2][3];
BYTE *ImageData=bData+bfOffBits;
int i,j;
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
Palette[i][j]=*(bitData+i*4+j);
}
}
int width=biWidth;
int height=biHeight;
int OldBytes=(width+1)/8;
if(OldBytes%4!=0)OldBytes=(OldBytes/4+1)*4;
CreateDirect(width,height);
for(j=0;j>=(7-i%8);
Index&=1;
BYTE b=Palette[Index][0];
BYTE g=Palette[Index][1];
BYTE r=Palette[Index][2];
SetPixel(i,height-j-1,RGB(r,g,b));
}
}
delete FileData;
return TRUE;
}
else
{
AfxMessageBox("Illegal color number");
return FALSE;
}
}
else
{
AfxMessageBox("Not a supported file formate");
return FALSE;
}
}
BOOL memBitmap::Save(LPCTSTR filename) {
char str[256];
strcpy(str,filename);
int fd;
if((fd = open(str,FILEMODE|O_CREAT)) ==-1)
{
AfxMessageBox("Cannot open file");
return FALSE;
}
lseek(fd,0L,SEEK_SET);
HugeWrite(fd,bData,lenth);
close(fd);
return TRUE;
}
void memBitmap::Display(int x,int y) {
int wid = GetWidth();
int hei = GetHeight();
int j=0;
int offset=0;
BYTE * temp = new BYTE[hei*BytesPerLine];
glRasterPos2i(x,y);
for(int i=0;i=biWidth)||
(y<0)||(y>=biHeight) )
{
AfxMessageBox("Overflow of image rang");
return RGB(0,0,0);
}
y=biHeight-y-1;
unsigned long temp=(long)y*(long)BytesPerLine+(long)x*3;
if(temp>=lenth)
{
AfxMessageBox("Overflow of file length");
return RGB(0,0,0);
}
unsigned r,g,b;
b=*(bitData+temp);
g=*(bitData+temp+1);
r=*(bitData+temp+2);
return RGB(r,g,b);
}
void memBitmap::SetPixel(int x,int y,COLORREF color) {
if((x<0)||(x>=biWidth)||
(y<0)||(y>=biHeight) )
{
AfxMessageBox("Overflow of image rang");
return;
}
y=biHeight-y-1;
unsigned long temp=(long)y*(long)BytesPerLine+(long)x*3;
if(temp>=lenth)
{
AfxMessageBox("Overflow of file length");
return;
}
*(bitData+temp)=GetBValue(color);
*(bitData+temp+1)=GetGValue(color);
*(bitData+temp+2)=GetRValue(color);
}
BOOL memBitmap::ChangeSize(int cx,int cy) {
int width=GetWidth();
int height=GetHeight();
if( (cx==width)&&(cy==height))return FALSE;
double sx,sy;
sx=double(cx)/(double)width;
sy=double(cy)/(double)height;
int i,j;
int newBytesPerLine = cx*3;
if(newBytesPerLine%4!=0)newBytesPerLine=(newBytesPerLine/4+1)*4;
unsigned char* newdata=new BYTE[long(cy)*newBytesPerLine+54L];
if(!newdata)
{
AfxMessageBox("Failed in malloc");
return FALSE;
}
memset(newdata,0,long(cy)*newBytesPerLine+54L);
unsigned char* buftemp = newdata + 54;
for(i=0;i=width-1)x=width-1;
if(y<=0)y=0;
if(y>=height-1)y=height-1;
if( ((int)x==0)||((int)x==width-1)||((int)y==0)||((int)y==height-1) )
{
COLORREF color=GetPixel((int)x,(int)y);
//SetPixel(i,j,color);
int xx=i;
int yy=cy-j-1;
unsigned long temp=(long)yy*(long)newBytesPerLine+(long)xx*3;
buftemp[temp]=GetBValue(color);
buftemp[temp+1]=GetBValue(color);
buftemp[temp+2]=GetBValue(color);
}
else
{
double r1,r2,r3,r4;
double g1,g2,g3,g4;
double b1,b2,b3,b4;
COLORREF c1,c2,c3,c4;
c1=GetPixel((int)x,(int)y);
c2=GetPixel((int)x+1,(int)y);
c3=GetPixel((int)x,(int)y+1);
c4=GetPixel((int)x+1,(int)y+1);
double dis1=x-(int)x;
double dis2=1-x+(int)x;
double dis3=y-(int)y;
double dis4=1-y+(int)y;
r1=GetRValue(c1);
g1=GetGValue(c1);
b1=GetBValue(c1);
r2=GetRValue(c2);
g2=GetGValue(c2);
b2=GetBValue(c2);
r3=GetRValue(c3);
g3=GetGValue(c3);
b3=GetBValue(c3);
r4=GetRValue(c4);
g4=GetGValue(c4);
b4=GetBValue(c4);
int r=int(dis4*(r1*dis2+r2*dis1)+dis3*(r3*dis2+r4*dis1));
if(r>255)r=255;
int g=int(dis4*(g1*dis2+g2*dis1)+dis3*(g3*dis2+g4*dis1));
if(g>255)g=255;
int b=int(dis4*(b1*dis2+b2*dis1)+dis3*(b3*dis2+b4*dis1));
if(b>255)b=255;
//SetPixel(i,j,RGB((BYTE)r,(BYTE)g,(BYTE)b));
int xx=i;
int yy=cy-j-1;
unsigned long temp=(long)yy*(long)newBytesPerLine+(long)xx*3;
buftemp[temp]=b;
buftemp[temp+1]=g;
buftemp[temp+2]=r;
}
}
}
int offset=0;
BytesPerLine=newBytesPerLine;
lenth=long(cy)*BytesPerLine;
CopyMemory(newdata,bData,54);
free(bData);
bData = newdata;
SetInfo();
biWidth=cx;
biHeight=cy;
bitData=bData+54;
biSizeImage=lenth;
bfSize=lenth+54;
return TRUE;
}
void memBitmap::Release() {
if(bData)
delete bData;
}
void memBitmap::DoScale(float sw,float sh) {
ChangeSize((int)(sw*GetWidth()),(int)(sh*GetHeight()));
}
void memBitmap::DoRotate(int jd1) {
double jd;
jd=(double)jd1/180;
jd*=3.14;
// float scale=m_mBmp.GetScale();
int width=GetWidth();
int height=GetHeight();
int OldDjx=int(sqrt(width*width+height*height)+0.5);//Length of diagonal
double OldDjxJd=atan((double)height/(double)width); //angle of diagonal and vertical
double NewDjxJd=OldDjxJd+jd;
double NewDjxJd1=OldDjxJd-jd;
int NewWidth=(int)fabs((double)OldDjx*cos(NewDjxJd));
int NewHeight=(int)fabs((double)OldDjx*sin(NewDjxJd));
int NewWidth1=(int)fabs((double)OldDjx*cos(NewDjxJd1));
int NewHeight1=(int)fabs((double)OldDjx*sin(NewDjxJd1));
NewWidth=MAX(NewWidth,NewWidth1);
NewHeight=MAX(NewHeight,NewHeight1);
memBitmap bmp1;
bmp1.CreateDirect(NewWidth,NewHeight);
int i,j;
double RotateMatrixElement[4];
RotateMatrixElement[0]=cos(jd);
RotateMatrixElement[1]=-sin(jd);
RotateMatrixElement[2]=sin(jd);
RotateMatrixElement[3]=cos(jd);
int temp=int((double)width*sin(jd));
for(i=0;i=0) && (x=0) && (y=width-1)x=width-1;
if(y<=0)y=0;
if(y>=height-1)y=height-1;
if( ((int)x==0)||((int)x==width-1)||((int)y==0)||((int)y==height-1) )
{
COLORREF color=GetPixel((int)x,(int)y);
bmp1.SetPixel(i,j,color);
}
else
{
double r1,r2,r3,r4;
double g1,g2,g3,g4;
double b1,b2,b3,b4;
COLORREF c1,c2,c3,c4;
c1=GetPixel((int)x,(int)y);
c2=GetPixel((int)x+1,(int)y);
c3=GetPixel((int)x,(int)y+1);
c4=GetPixel((int)x+1,(int)y+1);
double dis1=x-(int)x;
double dis2=1-x+(int)x;
double dis3=y-(int)y;
double dis4=1-y+(int)y;
r1=GetRValue(c1);
g1=GetGValue(c1);
b1=GetBValue(c1);
r2=GetRValue(c2);
g2=GetGValue(c2);
b2=GetBValue(c2);
r3=GetRValue(c3);
g3=GetGValue(c3);
b3=GetBValue(c3);
r4=GetRValue(c4);
g4=GetGValue(c4);
b4=GetBValue(c4);
int r=int(dis4*(r1*dis2+r2*dis1)+dis3*(r3*dis2+r4*dis1));
if(r>255)r=255;
int g=int(dis4*(g1*dis2+g2*dis1)+dis3*(g3*dis2+g4*dis1));
if(g>255)g=255;
int b=int(dis4*(b1*dis2+b2*dis1)+dis3*(b3*dis2+b4*dis1));
if(b>255)b=255;
bmp1.SetPixel(i,j,RGB((BYTE)r,(BYTE)g,(BYTE)b));
}
// COLORREF color=m_mBmp.GetPixel(x+width/2,y+height/2);
// bmp1.SetPixel(i,j,color);
}
else
{
bmp1.SetPixel(i,j,RGB(255,255,255));
}
}
}
bmp1.Display(0,0);
// bmp1.Release();
}