#include "stdafx.h"
#include "SBitmap.h"
IMPLEMENT_SERIAL(CSBitmap,CObject,1)
CSBitmap::CSBitmap(void)
: Width(0)
, Height(0)
, BitSize(0)
, pBitData(NULL)
, BitCount(0)
{
}
CSBitmap::~CSBitmap(void)
{
delete []pBitData;
}
bool CSBitmap::SetAttribute(unsigned mWidth, unsigned int mHeight, unsigned int mBitCount)
{
if(!mWidth)
mWidth=Width;
if(!mHeight)
mHeight=Height;
if(!mBitCount)
mBitCount=BitCount;
delete pBitData;
switch(mBitCount)
{
case 1:
while(mWidth%8)
mWidth++;
this->BitSize=mWidth*mHeight/8;
pBitData=new BYTE[BitSize];
break;
case 4:
while(mWidth%2)
mWidth++;
this->BitSize=mWidth*mHeight/2;
pBitData=new BYTE[BitSize];
break;
case 8:
this->BitSize=mWidth*mHeight;
pBitData=new BYTE[BitSize];
break;
case 12:
this->BitSize=mWidth*mHeight/2*3;
pBitData=new BYTE[BitSize];
break;
case 16:
this->BitSize=mWidth*mHeight*2;
pBitData=new BYTE[BitSize];
break;
case 24:
while(mWidth%4)
mWidth++;
this->BitSize=mWidth*mHeight*3;
pBitData=new BYTE[BitSize];
break;
case 32:
while(mWidth%4)
mWidth++;
this->BitSize=mWidth*mHeight*4;
pBitData=new BYTE[BitSize];
break;
default:
return false;
}
this->Width=mWidth;
this->Height=mHeight;
this->BitCount=mBitCount;
ZeroMemory(this->pBitData,this->BitSize);
return true;
}
bool CSBitmap::ImportBits(BYTE* lpBits, int mBitSize)
{
if(!lpBits)
return false;
if(!mBitSize)
mBitSize=BitSize;
memcpy(pBitData,lpBits,mBitSize);
return true;
}
COLORREF CSBitmap::GetPixel(unsigned int x, unsigned int y)
{
if(!(Width&&Height&&BitCount&&pBitData))
return 0;
COLORREF clr;
unsigned long shift=0;
BYTE base=1;
switch(BitCount)
{
case 1:
shift=((Height-y-1)*Width+x)/8;
for(int i=0;i<7-x%8;i++)
base*=2;
clr=(*(pBitData+shift))%(2*base)/base;
break;
case 4:
shift=((Height-y-1)*Width+x)/2;
if(x%2)
clr=(*(pBitData+shift))/0x10;
else
clr=(*(pBitData+shift))%0x10;
break;
case 8:
shift=(Height-y-1)*Width+x;
clr=*(pBitData+shift);
break;
case 12:
shift=((Height-y-1)*Width+x)/2*3;
if(x%2)
clr=(*(pBitData+shift+1))%0x10*0x100+(*(pBitData+shift+2));
else
clr=(*(pBitData+shift))*0x10+(*(pBitData+shift+1))/0x10;
break;
case 16:
shift=((Height-y-1)*Width+x)*2;
clr=(*(pBitData+shift))%0x100000+(*(pBitData+shift+1));
break;
case 24:
shift=((Height-y-1)*Width+x)*3;
clr=(*(pBitData+shift))*0x10000+(*(pBitData+shift+1))*0x100+(*(pBitData+shift+2));
break;
case 32:
shift=((Height-y-1)*Width+x)*4;
clr=*((COLORREF*)(pBitData+shift));
break;
}
return clr;
}
bool CSBitmap::SetPixel(unsigned int x, unsigned int y, COLORREF clr)
{
if(!(Width&&Height&&BitCount&&pBitData))
return true;
BYTE oldColor=0;
long shift=0;
int base=1;
switch(BitCount)
{
case 1:
shift=((Height-y-1)*Width+x)/8;
for(int i=0;i<7-x%8;i++)
base*=2;
oldColor=(*(pBitData+shift))%(2*base)/base;
(*(pBitData+shift))+=(clr-oldColor)*base;
return true;
case 4:
shift=((Height-y-1)*Width+x)/2;
if(x%2)
{
oldColor=(*(pBitData+shift))/0x10;
(*(pBitData+shift))+=(clr-oldColor)*0x10;
}
else
{
clr=(*(pBitData+shift))%0x10;
(*(pBitData+shift))+=(clr-oldColor);
}
return true;
case 8:
shift=(Height-y-1)*Width+x;
*(pBitData+shift)=clr;
return true;
case 12:
shift=((Height-y-1)*Width+x)/2*3;
if(x%2)
{
oldColor=(*(pBitData+shift+1))%0x10;
(*(pBitData+shift+1))+=(clr/0x100-oldColor);
(*(pBitData+shift+2))=clr%0x100;
}
else
{
(*(pBitData+shift))=(BYTE)(clr/0x10);
oldColor=(*(pBitData+shift+1))/0x10;
(*(pBitData+shift+1))+=(clr%0x10-oldColor)*0x10;
}
return true;
case 16:
shift=((Height-y-1)*(Width)+x)*2;
(*(pBitData+shift))=clr/0x10000;
(*(pBitData+shift+1))=clr%0x10000;
return true;
case 24:
shift=((Height-y-1)*(Width)+x)*3;
(*(pBitData+shift))=clr/0x10000;
(*(pBitData+shift+1))=clr%0x10000/0x100;
(*(pBitData+shift+2))=clr%0x100;
return true;
case 32:
shift=((Height-y-1)*Width+x)*4;
(*(pBitData+shift))=clr;
return true;
}
return false;
}
inline COLORREF GetGradeColor(int x , float span , COLORREF clrStr, COLORREF clrEnd, unsigned int BitCount)
{
COLORREF clr=0;
int StrR=0,StrG=0,StrB=0,EndR=0,EndG=0,EndB=0,AimR=0,AimG=0,AimB=0;
switch(BitCount)
{
case 1:
StrR=clrStr;EndR=clrEnd;
break;
case 12:
StrR=CSBitmap::GetRValue12(clrStr);
StrG=CSBitmap::GetGValue12(clrStr);
StrB=CSBitmap::GetBValue12(clrStr);
EndR=CSBitmap::GetRValue12(clrEnd);
EndG=CSBitmap::GetGValue12(clrEnd);
EndB=CSBitmap::GetBValue12(clrEnd);
break;
case 24:
StrR=GetRValue(clrStr);
StrG=GetGValue(clrStr);
StrB=GetBValue(clrStr);
EndR=GetRValue(clrEnd);
EndG=GetGValue(clrEnd);
EndB=GetBValue(clrEnd);
break;
case 32:
StrR=GetRValue(clrStr);
StrG=GetGValue(clrStr);
StrB=GetBValue(clrStr);
EndR=GetRValue(clrEnd);
EndG=GetGValue(clrEnd);
EndB=GetBValue(clrEnd);
break;
}
AimR=(float)((span-x)*StrR+x*EndR)/span;
AimG=(float)((span-x)*StrG+x*EndG)/span;
AimB=(float)((span-x)*StrB+x*EndB)/span;
switch(BitCount)
{
case 1:
break;
return AimR;
case 12:
return CSBitmap::RGB12(AimR,AimG,AimB);
break;
case 24:
return RGB(AimR,AimG,AimB);
break;
case 32:
return RGB(AimR,AimG,AimB);
break;
}
return 0;
}
bool CSBitmap::StretchDIB(CSBitmap* DestBmp, unsigned int mWidth, unsigned int mHeight, unsigned int mFlag)
{
if(!(Width&&Height&&BitCount&&pBitData&&DestBmp))
return false;
DestBmp->SetAttribute(mWidth,mHeight,this->BitCount);
float xRate=(float)(DestBmp->Width)/(this->Width);
float yRate=(float)(DestBmp->Height)/(this->Height);
COLORREF clr1,clr2,clr3;
switch(mFlag)
{
case 0:
for(int y=0;y<DestBmp->Height;y++)
{
for(int x=0;x<DestBmp->Width;x++)
{
DestBmp->SetPixel(x,y,this->GetPixel((int)(x/xRate),(int)(y/yRate)));
}
}
break;
case 1:
for(int y=0;y<this->Height-1;y++)
{
for(int x=0;x<this->Width-1;x++)
{
float subyInit=(float)y*yRate;
float subxInit=(float)x*xRate;
for(int suby=subyInit;suby<subyInit+yRate;suby++)
{
clr1=GetGradeColor((int)(suby-subyInit),yRate,this->GetPixel(x,y),this->GetPixel(x,y+1),this->BitCount);
clr2=GetGradeColor((int)(suby-subyInit),yRate,this->GetPixel(x+1,y),this->GetPixel(x+1,y+1),this->BitCount);
for(int subx=subxInit;subx<subxInit+xRate;subx++)
{
clr3=GetGradeColor((int)(subx-subxInit),xRate,clr1,clr2,this->BitCount);
DestBmp->SetPixel(subx,suby,clr3);
}
}
}
}
break;
case 2:
int sumR,sumG, sumB,newR,newG,newB;
for(int y=0;y<DestBmp->Height;y++)
{
for(int x=0;x<DestBmp->Width;x++)
{
int subyInit=(float)y/yRate;
int subyEnd=(float)(y+1)/yRate;
int subxInit=(float)x/xRate;
int subxEnd=(float)(x+1)/xRate;
sumR=0;sumG=0;sumB=0;
for(int suby=subyInit;suby<subyEnd;suby++)
{
for(int subx=subxInit;subx<subxEnd;subx++)
{
switch(this->BitCount)
{
case 1:
clr1=this->GetPixel(subx,suby);
sumR+=clr1;
break;
case 12:
clr1=this->GetPixel(subx,suby);
sumR+=CSBitmap::GetRValue12(clr1);
sumG+=CSBitmap::GetGValue12(clr1);
sumB+=CSBitmap::GetBValue12(clr1);
break;
case 24:
clr1=this->GetPixel(subx,suby);
sumR+=GetRValue(clr1);
sumG+=GetGValue(clr1);
sumB+=GetBValue(clr1);
break;
case 32:
clr1=this->GetPixel(subx,suby);
sumR+=GetRValue(clr1);
sumG+=GetGValue(clr1);
sumB+=GetBValue(clr1);
break;
}
}
}
if((subyEnd-subyInit)&&(subxEnd-subxInit))
{
newR=sumR/((subyEnd-subyInit)*(subxEnd