Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1510 lines
29 KiB
C++
1510 lines
29 KiB
C++
#include"Image.h"
|
|
#include"octtree.h"
|
|
#include<string.h>
|
|
|
|
#define IMax(x,y) ((x)>(y)?(x):(y))
|
|
|
|
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Image utilities
|
|
|
|
Point Image::Crop(ImgRGBColor ccl)
|
|
{
|
|
if(!IsData()) GENNFERR("(Crop)Image does not contain data");
|
|
if(itype!=ITYPE_RGB) GENNFERR("(CropByColor)Image type not supported");
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
int xlow,xhigh,ylow,yhigh;
|
|
xlow=xlen*psize; ylow=ylen*Pitch;
|
|
yhigh=xhigh=-1;
|
|
BYTE *dtp=Lock();
|
|
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
if(col!=ccl)
|
|
{
|
|
if(x<xlow) xlow=x;
|
|
if(y<ylow) ylow=y;
|
|
if(x>xhigh) xhigh=x;
|
|
if(y>yhigh) yhigh=y;
|
|
}
|
|
}
|
|
|
|
xlow/=psize;
|
|
xhigh/=psize;
|
|
ylow/=Pitch;
|
|
yhigh/=Pitch;
|
|
|
|
UnLock();
|
|
|
|
Crop(xlow,ylow,xhigh,yhigh);
|
|
return Point(xlow,ylow);
|
|
}
|
|
|
|
|
|
void Image::Crop(int x1,int y1,int x2, int y2)
|
|
{
|
|
if(!IsData()) GENNFERR("(Crop)Image does not contain data");
|
|
if(x1<0) x1=0; if(x2<0) x2=0;
|
|
if(y1<0) y1=0; if(y2<0) y2=0;
|
|
if(x1>=xlen) x1=xlen-1; if(x2>=xlen) x2=xlen-1;
|
|
if(y1>=xlen) y1=ylen-1; if(y2>=ylen) y2=ylen-1;
|
|
if(x1>x2 || y1>y2) GENNFERR("(Crop)Invalid Crop Dimensions");
|
|
|
|
int nxlen,nylen,x,y;
|
|
nxlen=x2-x1+1;
|
|
nylen=y2-y1+1;
|
|
int psize=(Bpp>>3);
|
|
int sx,sy,axl=nxlen*psize;
|
|
int ystop=nylen*nxlen*psize;
|
|
|
|
BYTE *dtp=Lock();
|
|
BYTE *ndt=new BYTE[nxlen*nylen*psize+4]; //+4 for overrun
|
|
|
|
|
|
for(y=0,sy=y1*Pitch;y<ystop;y+=nxlen*psize,sy+=Pitch)
|
|
for(x=0,sx=x1*psize;x<axl;x++,sx++)
|
|
ndt[x+y]=dtp[sx+sy];
|
|
|
|
UnLock();
|
|
xlen=nxlen;
|
|
ylen=nylen;
|
|
xpos+=x1;
|
|
ypos+=y1;
|
|
IAlloc();
|
|
SetData(ndt);
|
|
delete ndt;
|
|
}
|
|
|
|
void Image::ReplaceAlpha(int acutoff,const ImgRGBColor &bcol) //Replaces alpha <= this value with color
|
|
{
|
|
if(!IsData()) GENNFERR("(ReplaceAlpha)Image does not contain data");
|
|
if(Mask.GetABits()<0) GENNFERR("(ReplaceAlpha)Image does not contain Alpha channel");
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
if((signed int)col.a<=acutoff) tptr->Set(bcol,Mask);
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
float Image::GetBrightness()
|
|
{
|
|
if(!IsData()) GENNFERR("(Swap)Image does not contain data");
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
float rsum,gsum,bsum;
|
|
|
|
rsum=gsum=bsum=0.0f;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
rsum+=col.r;
|
|
gsum+=col.g;
|
|
bsum+=col.b;
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
rsum+=pal[*(dtp+x+y)].r;
|
|
gsum+=pal[*(dtp+x+y)].g;
|
|
bsum+=pal[*(dtp+x+y)].b;
|
|
}
|
|
|
|
}
|
|
|
|
UnLock();
|
|
|
|
return (gsum*0.59f+bsum*0.11f+rsum*0.3f)/(255*xlen*ylen);
|
|
|
|
}
|
|
|
|
void Image::BrightenBy(float bght)
|
|
{
|
|
if(!IsData()) GENNFERR("(Swap)Image does not contain data");
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
float rsum,gsum,bsum;
|
|
|
|
rsum=gsum=bsum=0.0f;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
col.BrightenBy(bght);
|
|
tptr->Set(col,Mask);
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
for(int i=0;i<256;i++)
|
|
pal[i].BrightenBy(bght);
|
|
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::ContrastBy(float cont)
|
|
{
|
|
if(!IsData()) GENNFERR("(Swap)Image does not contain data");
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
float rsum,gsum,bsum;
|
|
|
|
rsum=gsum=bsum=0.0f;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
col.ContrastBy(cont);
|
|
tptr->Set(col,Mask);
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
for(int i=0;i<256;i++)
|
|
pal[i].ContrastBy(cont);
|
|
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::FillHistogram(Histogram *hist,RMETHOD rmet)
|
|
{
|
|
if(!IsData()) GENNFERR("(Swap)Image does not contain data");
|
|
hist->Clear();
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
float rsum,gsum,bsum;
|
|
|
|
rsum=gsum=bsum=0.0f;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
col.Bound();
|
|
switch(rmet)
|
|
{
|
|
case RMD_REDC:
|
|
hist->Data[col.r]++;
|
|
break;
|
|
case RMD_GREENC:
|
|
hist->Data[col.g]++;
|
|
break;
|
|
case RMD_BLUEC:
|
|
hist->Data[col.b]++;
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
|
|
}
|
|
hist->Peak=GetWidth()*GetHeight();
|
|
UnLock();
|
|
|
|
}
|
|
|
|
|
|
void Image::FillHistogram(RGBHistogram *hist)
|
|
{
|
|
if(!IsData()) GENNFERR("(Swap)Image does not contain data");
|
|
hist->Clear();
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
col.Bound();
|
|
hist->RHist.Data[col.r]++;
|
|
hist->GHist.Data[col.g]++;
|
|
hist->BHist.Data[col.b]++;
|
|
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
|
|
}
|
|
hist->GHist.Peak=hist->BHist.Peak=hist->RHist.Peak=GetWidth()*GetHeight();
|
|
UnLock();
|
|
|
|
}
|
|
|
|
void Image::AutoAdjust()
|
|
{
|
|
RGBHistogram hist(*this);
|
|
AdjustToRange(hist.GetTop(),hist.GetBottom());
|
|
}
|
|
|
|
void Image::AdjustToRange(ImgRGBColor &maxcol,ImgRGBColor &mincol)
|
|
{
|
|
|
|
if(!IsData()) GENNFERR("(Swap)Image does not contain data");
|
|
|
|
|
|
int min=256,max=0,span=0;
|
|
min=mincol.r<min?mincol.r:min;
|
|
min=mincol.g<min?mincol.g:min;
|
|
min=mincol.b<min?mincol.b:min;
|
|
|
|
max=maxcol.r>max?maxcol.r:max;
|
|
max=maxcol.g>max?maxcol.g:max;
|
|
max=maxcol.b>max?maxcol.b:max;
|
|
span=max-min;
|
|
|
|
|
|
if(span==0) return;
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
col.r=((col.r-min)*256)/span;
|
|
col.g=((col.g-min)*256)/span;
|
|
col.b=((col.b-min)*256)/span;
|
|
col.Bound();
|
|
|
|
tptr->Set(col,Mask);
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
for(int i=0;i<256;i++)
|
|
|
|
{
|
|
pal[i].r=((pal[i].r-min)*256)/span;
|
|
pal[i].g=((pal[i].g-min)*256)/span;
|
|
pal[i].b=((pal[i].b-min)*256)/span;
|
|
pal[i].Bound();
|
|
}
|
|
|
|
}
|
|
|
|
UnLock();
|
|
|
|
}
|
|
|
|
|
|
void Image::Swap(const ImgRGBColor &src,const ImgRGBColor &dst)
|
|
{
|
|
if(!IsData()) GENNFERR("(Swap)Image does not contain data");
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
if(col==src) tptr->Set(dst,Mask);
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
|
|
void Image::MakeBW()
|
|
{
|
|
if(!IsData()) GENNFERR("(MakeBW)Image does not contain data");
|
|
BYTE *dtp=Lock();
|
|
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
col.MakeBW();
|
|
tptr->Set(col,Mask);
|
|
}
|
|
}
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
AllocPal();
|
|
for(int i=0;i<256;i++) pal[i].MakeBW();
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::Invert()
|
|
{
|
|
if(!IsData()) GENNFERR("(Invert)Image does not contain data");
|
|
BYTE *dtp=Lock();
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
col.Invert();
|
|
tptr->Set(col,Mask);
|
|
}
|
|
|
|
}
|
|
else
|
|
{ //8 Bit implementation
|
|
AllocPal();
|
|
for(int i=0;i<256;i++) pal[i].Invert();
|
|
RealizePalette();
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::CreateBlank(int xl,int yl,ITYPE itp,int bpp,RGBMask &msk)
|
|
{
|
|
CreateBlank(xl,yl,itp,bpp);
|
|
Mask=msk;
|
|
}
|
|
|
|
void Image::CreateBlank(int xl,int yl,ITYPE itp,int bpp)
|
|
{
|
|
if(xl<0 || yl<0) GENNFERR("(Create Fade) Invalid dimensions");
|
|
//if(bpp!=24 && bpp!=32 && bpp!=8) GENNFERR("(Create Fade) Invalid depth");
|
|
if(itp!=ITYPE_RGB && itp!=ITYPE_INDEXED) GENNFERR("(Create Fade) Invalid Image Type");
|
|
if(itp==ITYPE_RGB && bpp==8) GENNFERR("(Create Fade) RGB Image cannot be 8-bit");
|
|
if(itp==ITYPE_INDEXED && bpp!=8) GENNFERR("(Create Fade) Indexed Images must be 8-bit");
|
|
|
|
vxlen=xlen=xl; vylen=ylen=yl; itype=itp; Bpp=bpp;
|
|
|
|
if(Bpp==32)
|
|
Mask=RGBMask(0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
|
|
else
|
|
Mask=RGBMask(0x00ff0000,0x0000ff00,0x000000ff);
|
|
|
|
IAlloc();
|
|
|
|
}
|
|
|
|
void Image::CreateFade(int xl,int yl,ImgRGBColor rgb1,ImgRGBColor rgb2,int ort,ITYPE itp,int bpp)
|
|
{
|
|
if(xl<0 || yl<0) GENNFERR("(Create Fade) Invalid dimensions");
|
|
//if(bpp!=24 && bpp!=32 && bpp!=8) GENNFERR("(Create Fade) Invalid depth");
|
|
if(itp!=ITYPE_RGB && itp!=ITYPE_INDEXED) GENNFERR("(Create Fade) Invalid Image Type");
|
|
if(itp==ITYPE_RGB && bpp==8) GENNFERR("(Create Fade) RGB Image cannot be 8-bit");
|
|
if(itp==ITYPE_INDEXED && bpp!=8) GENNFERR("(Create Fade) Indexed Images must be 8-bit");
|
|
|
|
vxlen=xlen=xl; vylen=ylen=yl; itype=itp; Bpp=bpp;
|
|
int x,y,i;
|
|
double r,g,b,dist,rinc,ginc,binc;
|
|
|
|
IAlloc();
|
|
BYTE *dpt=Lock();
|
|
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
|
|
if(ort) dist=xlen; else dist=ylen;
|
|
|
|
|
|
int psize=(Bpp>>3);
|
|
int axl=xlen*psize;
|
|
|
|
switch(Bpp)
|
|
{
|
|
case 32: Mask=RGBMask(0x00ff0000,0x0000ff00,0x000000ff,0xff000000); break;
|
|
case 24: Mask=RGBMask(0x00ff0000,0x0000ff00,0x000000ff,0x00000000); break;
|
|
case 16: Mask=RGBMask(0x7c00,0x3e0,0x1f); break;
|
|
|
|
case 8:
|
|
//calculate pallette range
|
|
rinc=((float)rgb2.r-rgb1.r)/255;
|
|
ginc=((float)rgb2.g-rgb1.g)/255;
|
|
binc=((float)rgb2.b-rgb1.b)/255;
|
|
r=rgb1.r; g=rgb1.g; b=rgb1.b;
|
|
AllocPal();
|
|
for(i=0;i<256;i++)
|
|
{
|
|
pal[i]=ImgRGBColor((int)r,(int)g,(int)b);
|
|
r+=rinc; g+=ginc; b+=binc;
|
|
}
|
|
RealizePalette();
|
|
|
|
for(y=0;y<ylen;y++)
|
|
for(x=0;x<axl;x+=psize)
|
|
dpt[x+y*Pitch]=(BYTE)(ort?(x*256)/xlen:(y*256)/ylen);
|
|
break;
|
|
|
|
} //calculate color range
|
|
|
|
if(Bpp>8)
|
|
{
|
|
rinc=((float)rgb2.r-rgb1.r)/dist;
|
|
ginc=((float)rgb2.g-rgb1.g)/dist;
|
|
binc=((float)rgb2.b-rgb1.b)/dist;
|
|
r=rgb1.r;
|
|
g=rgb1.g;
|
|
b=rgb1.b;
|
|
|
|
if(ort)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
for(y=0;y<ylen;y++)
|
|
{
|
|
tptr=(RGBPixel *)(dpt+x+y*Pitch);
|
|
col.Set((int)r,(int)g,(int)b);
|
|
tptr->Set(col,Mask);
|
|
}
|
|
r+=rinc; g+=ginc; b+=binc;
|
|
}
|
|
else
|
|
for(y=0;y<ylen;y++)
|
|
{
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dpt+x+y*Pitch);
|
|
col.Set((int)r,(int)g,(int)b);
|
|
tptr->Set(col,Mask);
|
|
}
|
|
r+=rinc; g+=ginc; b+=binc;
|
|
}
|
|
}//end of cs
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::CreateSolid(int xl,int yl,ImgRGBColor col,ITYPE itp,int bpp)
|
|
{
|
|
if(xl<0 || yl<0) GENNFERR("(Create Solid) Invalid dimensions");
|
|
//if(bpp!=24 && bpp!=32 && bpp!=8) GENNFERR("(Create Solid) Invalid depth");
|
|
if (itp!=ITYPE_RGB && itp!=ITYPE_INDEXED) GENNFERR("(Create Solid) Invalid Image Type");
|
|
if(itp==ITYPE_RGB && bpp==8) GENNFERR("(Create Solid) RGB Image cannot be 8-bit");
|
|
if(itp==ITYPE_INDEXED && bpp!=8) GENNFERR("(Create Solid) Indexed Images must be 8-bit");
|
|
|
|
|
|
vxlen=xlen=xl; vylen=ylen=yl; itype=itp; Bpp=bpp;
|
|
|
|
if(Bpp==32)
|
|
Mask=RGBMask(0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
|
|
else
|
|
Mask=RGBMask(0x00ff0000,0x0000ff00,0x000000ff);
|
|
|
|
IAlloc();
|
|
FillColor(col);
|
|
}
|
|
|
|
void Image::FillColor(ImgRGBColor fcol)
|
|
{
|
|
int x,y,i;
|
|
|
|
BYTE *dpt=Lock();
|
|
|
|
|
|
int psize=(Bpp>>3);
|
|
int axl=xlen*psize;
|
|
RGBPixel tcl(fcol,Mask);
|
|
int ystop=ylen*Pitch;
|
|
|
|
switch(Bpp)
|
|
{
|
|
case 32:
|
|
case 24:
|
|
case 16:
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
*((RGBPixel *)(dpt+x+y))=tcl;
|
|
break;
|
|
|
|
case 8:
|
|
AllocPal();
|
|
pal[0]=fcol;
|
|
RealizePalette();
|
|
for(i=0;i<ylen*Pitch;i++) dpt[i]=0;
|
|
break;
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
|
|
void Image::CreateGrid(int xdim,int ydim,int gx,int gy,ImgRGBColor bgk,ImgRGBColor frg,ITYPE itp,int bpp)
|
|
{
|
|
if(xdim<0 || ydim<0) GENNFERR("(Create Grid) Invalid dimensions");
|
|
if(bpp!=24 && bpp!=32 && bpp!=8) GENNFERR("(Create Grid) Invalid depth");
|
|
if (itp!=ITYPE_RGB && itp!=ITYPE_INDEXED) GENNFERR("(Create Grid) Invalid Image Type");
|
|
if(itp==ITYPE_RGB && bpp==8) GENNFERR("(Create Grid) RGB Image cannot be 8-bit");
|
|
if(itp==ITYPE_INDEXED && bpp!=8) GENNFERR("(Create Grid) Indexed Images must be 8-bit");
|
|
|
|
vxlen=xlen=xdim; vylen=ylen=ydim;
|
|
itype=itp; Bpp=bpp;
|
|
|
|
int x,y,i;
|
|
IAlloc();
|
|
BYTE *dpt=Lock();
|
|
int psize=(Bpp>>3);
|
|
int axl=xlen*psize;
|
|
double xdiv=(xlen-1)/(float)gx,ydiv=(ylen-1)/(float)gy;
|
|
double xcnt,ycnt;
|
|
xcnt=ycnt=0.0;
|
|
|
|
RGBPixel fpx(frg,Mask);
|
|
RGBPixel bpx(bgk,Mask);
|
|
|
|
switch(Bpp)
|
|
{
|
|
case 32:
|
|
case 24:
|
|
case 16:
|
|
|
|
for(ycnt=0.0,y=0;y<ylen;y++,ycnt-=1.0)
|
|
{
|
|
if(ycnt<.5)
|
|
{
|
|
for(x=0;x<axl;x+=psize)
|
|
((RGBPixel *)(dpt+x+y*Pitch))->Set(frg,Mask);
|
|
ycnt+=ydiv;
|
|
}
|
|
else
|
|
for(xcnt=0.0,x=0;x<axl;x+=psize,xcnt-=1.0)
|
|
if(xcnt<.5)
|
|
{ *((RGBPixel *)(dpt+x+y*Pitch))=fpx; xcnt+=xdiv; }
|
|
else
|
|
*((RGBPixel *)(dpt+x+y*Pitch))=bpx;
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
AllocPal();
|
|
pal[0]=bgk;
|
|
pal[255]=frg;
|
|
RealizePalette();
|
|
for(i=0;i<ylen*Pitch;i++) dpt[i]=0;
|
|
for(ycnt=0.0,y=0;y<ylen;y++,ycnt-=1.0)
|
|
{
|
|
if(ycnt<.5)
|
|
{ for(x=0;x<axl;x+=psize) dpt[x+y*Pitch]=255; ycnt+=ydiv; }
|
|
else
|
|
for(xcnt=0.0,x=0;x<axl;x+=psize,xcnt-=1.0)
|
|
if(xcnt<.5) { dpt[x+y*Pitch]=255; xcnt+=xdiv; }
|
|
}
|
|
break;
|
|
}//end of cs
|
|
|
|
|
|
UnLock();
|
|
}
|
|
|
|
|
|
|
|
|
|
void Image::Difference()
|
|
{
|
|
if(!IsData()) GENNFERR("(Difference)Image does not contain data");
|
|
BYTE *dt=Lock();
|
|
int byte=Bpp>>3;
|
|
|
|
int x,y;
|
|
int ystop=ylen*Pitch;
|
|
if(byte==3)
|
|
{
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=xlen-1;x>=1;x--)
|
|
{
|
|
dt[x*byte+y+0]-=dt[(x-1)*byte+y+0];
|
|
dt[x*byte+y+1]-=dt[(x-1)*byte+y+1];
|
|
dt[x*byte+y+2]-=dt[(x-1)*byte+y+2];
|
|
}
|
|
}
|
|
else
|
|
if(byte==4)
|
|
{
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=xlen-1;x>=1;x--)
|
|
{
|
|
dt[x*byte+y+0]-=dt[(x-1)*byte+y+0];
|
|
dt[x*byte+y+1]-=dt[(x-1)*byte+y+1];
|
|
dt[x*byte+y+2]-=dt[(x-1)*byte+y+2];
|
|
}
|
|
}
|
|
else
|
|
GENNFERR("(Difference)Image Size not supported");
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::UnDifference()
|
|
{
|
|
if(!IsData()) GENNFERR("(UnDifference)Image does not contain data");
|
|
BYTE *dt=Lock();
|
|
int byte=Bpp>>3;
|
|
|
|
int x,y,b,xstop;
|
|
int ystop=ylen*Pitch;
|
|
xstop=xlen*byte;
|
|
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=byte;x<xstop;x+=byte)
|
|
for(b=0;b<byte;b++)
|
|
{
|
|
dt[x+y+b]+=dt[(x-byte)+y+b];
|
|
}
|
|
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::MakeRGB16(RGBMask msk)
|
|
{
|
|
if(!IsData()) GENNFERR("(MakeRGB16)Image does not contain data");
|
|
if(Bpp==16) return;
|
|
//if(Bpp==16) GENNFERR("(MakeRGB16)Image is 16 bit");
|
|
int psize=(Bpp>>3);
|
|
int axl=xlen*psize;
|
|
|
|
BYTE *tndt,*ndt=new BYTE[xlen*ylen*2+4]; //+4 for overrun
|
|
tndt=ndt;
|
|
int x,y;
|
|
BYTE *dt=Lock();
|
|
|
|
switch(itype)
|
|
{
|
|
case ITYPE_INDEXED:
|
|
for(y=0;y<ylen;y++)
|
|
for(x=0;x<xlen;x++,tndt+=2)
|
|
((RGBPixel *)tndt)->Set(pal[dt[x+y*Pitch]],msk);
|
|
break;
|
|
|
|
case ITYPE_RGB:
|
|
{
|
|
ImgRGBColor col;
|
|
RGBPixel *tptr;
|
|
int ystop=ylen*Pitch;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize,tndt+=2)
|
|
{
|
|
tptr=(RGBPixel *)(dt+x+y);
|
|
col.Set(*tptr,Mask);
|
|
((RGBPixel *)tndt)->Set(col,msk);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
Mask=msk;
|
|
Bpp=16;
|
|
UnLock();
|
|
itype=ITYPE_RGB;
|
|
IAlloc();
|
|
SetData(ndt);
|
|
delete ndt;
|
|
|
|
|
|
}
|
|
|
|
void Image::MakeRGB(RGBMask msk)
|
|
{
|
|
if(!IsData()) GENNFERR("(MakeRGB)Image does not contain data");
|
|
|
|
if(itype==ITYPE_INDEXED) MakeRGB24();
|
|
|
|
int opsize,npsize,x,y,axl;
|
|
opsize=Bpp>>3;
|
|
npsize=msk.GetBpp()>>3;
|
|
axl=xlen*opsize;
|
|
|
|
|
|
|
|
BYTE *tndt,*ndt;
|
|
ndt=new unsigned char[xlen*ylen*npsize+4]; //+4 for overrun
|
|
if(ndt==NULL) GENFERR("MemoryAllocation Error");
|
|
tndt=ndt;
|
|
BYTE *dt=Lock();
|
|
|
|
ImgRGBColor col;
|
|
RGBPixel *tptr;
|
|
|
|
int ystop=ylen*Pitch;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=opsize,tndt+=npsize)
|
|
{
|
|
tptr=(RGBPixel *)(dt+x+y);
|
|
col.Set(*tptr,Mask);
|
|
((RGBPixel *)tndt)->Set(col,msk);
|
|
}
|
|
|
|
|
|
UnLock();
|
|
Mask=msk;
|
|
Bpp=msk.GetBpp();
|
|
itype=ITYPE_RGB;
|
|
IAlloc();
|
|
SetData(ndt);
|
|
delete ndt;
|
|
}
|
|
|
|
void Image::MakeRGB24()
|
|
{
|
|
if(!IsData()) GENNFERR("(MakeRGB24)Image does not contain data");
|
|
//if(Bpp==24) GENNFERR("(MakeRGB24)Image is 24 bit");
|
|
|
|
if(itype==ITYPE_INDEXED)
|
|
{
|
|
BYTE *tndt,*ndt=new BYTE[xlen*ylen*3+4]; //+4 for overrun
|
|
tndt=ndt;
|
|
int x,y;
|
|
BYTE *dt=Lock();
|
|
|
|
int ystop=ylen*Pitch;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<xlen;x++,tndt+=3)
|
|
((RGBPixel *)tndt)->Set(pal[dt[x+y]],Mask);
|
|
|
|
UnLock();
|
|
|
|
itype=ITYPE_RGB;
|
|
Bpp=24;
|
|
IAlloc();
|
|
SetData(ndt);
|
|
delete ndt;
|
|
}
|
|
|
|
if(itype==ITYPE_RGB) MakeRGB(RGBMask(0xff0000,0xff00,0xff,0x00));
|
|
|
|
}
|
|
|
|
|
|
void Image::CorrectPitch() //corrects the pitch of loaded image
|
|
{
|
|
int axl=xlen*(Bpp>>3);
|
|
if(Pitch==axl) return;
|
|
if(!IsData()) GENNFERR("(CorrectPitch)Image does not contain data");
|
|
|
|
int x,y;
|
|
BYTE *data=Lock();
|
|
|
|
for(y=ylen-1;y>=0;y--)
|
|
for(x=axl-1;x>=0;x--)
|
|
data[x+Pitch*y]=data[x+axl*y];
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::DePitch(BYTE *ndt) //return depicthed COPY of the data, must be deleted
|
|
{
|
|
BYTE *dat;
|
|
int axl=xlen*(Bpp>>3);
|
|
dat=Lock();
|
|
int x,y;
|
|
|
|
for(y=0;y<ylen;y++)
|
|
for(x=0;x<axl;x++)
|
|
ndt[x+axl*y]=dat[x+y*Pitch];
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::MaskTo(RGBMask &imask) //Remask the data to this mask to correct mask
|
|
{
|
|
if(!IsData()) GENNFERR("(MaskTo)Image does not contain data");
|
|
if(itype!=ITYPE_RGB) GENNFERR("(MaskTo)Cannot Mask a non RGB Image");
|
|
if(!imask.IsValid()) GENNFERR("(MaskTo)Invalid Mask");
|
|
if(imask==Mask) return;
|
|
|
|
BYTE *dtp=Lock();
|
|
RGBPixel *tptr;
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
|
|
ImgRGBColor col;
|
|
int ystop=ylen*Pitch;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
tptr->Set(col,imask);
|
|
}
|
|
Mask=imask;
|
|
UnLock();
|
|
|
|
|
|
}
|
|
|
|
|
|
void Image::MaskFrom(RGBMask &omask) //Remask the data from this mask to correct mask
|
|
{
|
|
if(!IsData()) GENNFERR("(MaskFrom)Image does not contain data");
|
|
if(itype!=ITYPE_RGB) GENNFERR("(MaskFrom)Cannot Mask a non RGB Image");
|
|
if(!omask.IsValid()) GENNFERR("(MaskFrom)Invalid Mask");
|
|
if(omask==Mask) return;
|
|
|
|
BYTE *dtp=Lock();
|
|
RGBPixel *tptr;
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
|
|
ImgRGBColor col;
|
|
int ystop=ylen*Pitch;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,omask);
|
|
tptr->Set(col,Mask);
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
|
|
void Image::DeInterlace() //deinterlaces a 4 interlaced image
|
|
{
|
|
if(!IsData()) GENNFERR("(Deinterlace)Image does not contain data");
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x,y,axl=xlen*psize;
|
|
BYTE *tndt,*ndt=new BYTE[xlen*ylen*psize+4]; //+4 for overrun
|
|
tndt=ndt;
|
|
|
|
if(itype==ITYPE_RGB)
|
|
switch(Bpp)
|
|
{
|
|
case 24:
|
|
case 32:
|
|
break;
|
|
|
|
case 16:
|
|
break;
|
|
} //end of cs
|
|
else
|
|
{ //place 8 Bit implementation here
|
|
int pass,skip,start,tln=0;
|
|
|
|
for(pass=0;pass<4;pass++)
|
|
{
|
|
if(pass) {skip=16/(1<<pass); start=skip>>1; }
|
|
else {skip=8; start=0;}
|
|
|
|
for(y=start;y<ylen;y+=skip,tln++)
|
|
for(x=0;x<axl;x+=psize) ndt[x+y*ylen]=dtp[x+tln*ylen];
|
|
}
|
|
|
|
|
|
}
|
|
|
|
SetData(ndt);
|
|
delete ndt;
|
|
UnLock();
|
|
}
|
|
|
|
void Image::Quantize()
|
|
{
|
|
if(!IsData()) GENNFERR("(Quantize)Image does not contain data");
|
|
if(Bpp<16) GENNFERR("(Quantize)Not Enough Colors");
|
|
|
|
OctQuant tree;
|
|
tree.Quantize(this);
|
|
|
|
}
|
|
|
|
void Image::ReduceTo8Bit(RMETHOD rm)
|
|
{
|
|
if(!IsData()) GENNFERR("(MakeBW)Image does not contain data");
|
|
if(Bpp<=8) GENNFERR("(ReduceTo8Bit)Already 8bit");
|
|
BYTE *dtp=Lock();
|
|
|
|
BYTE *newdata;
|
|
|
|
newdata=new BYTE[GetWidth()*GetHeight()];
|
|
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
int psize=(Bpp>>3);
|
|
int inc=0,x,y,axl=xlen*psize;
|
|
int ystop=ylen*Pitch;
|
|
RGBPixel *tptr;
|
|
ImgRGBColor col;
|
|
|
|
switch(rm)
|
|
{
|
|
case RMD_REDC:
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
newdata[inc++]=(BYTE)col.r;
|
|
tptr->Set(col,Mask);
|
|
}
|
|
break;
|
|
|
|
case RMD_BLUEC:
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
newdata[inc++]=(BYTE)col.b;
|
|
tptr->Set(col,Mask);
|
|
}
|
|
break;
|
|
|
|
case RMD_GREENC:
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
newdata[inc++]=(BYTE)col.g;
|
|
tptr->Set(col,Mask);
|
|
}
|
|
break;
|
|
|
|
case RMD_ALPHAC:
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
newdata[inc++]=(BYTE)col.a;
|
|
tptr->Set(col,Mask);
|
|
}
|
|
break;
|
|
|
|
case RMD_MAX:
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
newdata[inc++]=(BYTE)IMax(IMax(IMax(col.r,col.g),col.b),col.a);
|
|
tptr->Set(col,Mask);
|
|
}
|
|
break;
|
|
|
|
case RMD_BHT:
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr=(RGBPixel *)(dtp+x+y);
|
|
col.Set(*tptr,Mask);
|
|
col.MakeBW();
|
|
newdata[inc++]=(BYTE)col.r;
|
|
tptr->Set(col,Mask);
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
UnLock();
|
|
|
|
Bpp=8;
|
|
itype=ITYPE_INDEXED;
|
|
IAlloc();
|
|
SetData(newdata);
|
|
MakeGrayscalePalette();
|
|
RealizePalette();
|
|
delete newdata;
|
|
|
|
|
|
}
|
|
|
|
void
|
|
Image::CreateDifferentialMap()
|
|
{
|
|
if(!IsData())
|
|
GENNFERR("(MakeBW)Image does not contain data");
|
|
|
|
if(Bpp<=8)
|
|
GENNFERR("(ReduceTo8Bit)Already 8bit");
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
int psize=(Bpp>>3);
|
|
int x, y, axl = (xlen-1)*psize;
|
|
int ystop = (ylen-1)*Pitch;
|
|
RGBPixel *tptr0, *tptr1, *tptr2;
|
|
ImgRGBColor col0, col1, col2;
|
|
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr0 = (RGBPixel *)(dtp+x+y);
|
|
col0.Set(*tptr0,Mask);
|
|
|
|
tptr1 = (RGBPixel *)(dtp+(x+psize)+y);
|
|
col1.Set(*tptr1,Mask);
|
|
|
|
tptr2 = (RGBPixel *)(dtp+x+(y+Pitch));
|
|
col2.Set(*tptr2,Mask);
|
|
|
|
col0.g = (BYTE)abs((int)(((col1.r-col0.r)+(col2.r-col0.r))*0.25f*32));
|
|
|
|
tptr0->Set(col0, Mask);
|
|
}
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr0 = (RGBPixel *)(dtp+x+y);
|
|
col0.Set(*tptr0,Mask);
|
|
|
|
tptr1 = (RGBPixel *)(dtp+(x+psize)+y);
|
|
col1.Set(*tptr1,Mask);
|
|
|
|
tptr2 = (RGBPixel *)(dtp+x+(y+Pitch));
|
|
col2.Set(*tptr2,Mask);
|
|
|
|
col0.b = (BYTE)abs((int)(((col1.g-col0.g)+(col2.g-col0.g))*0.25f*4));
|
|
|
|
tptr0->Set(col0, Mask);
|
|
}
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void
|
|
Image::CreateDifferentialMap(float *im, int xdim)
|
|
{
|
|
if(!IsData())
|
|
GENNFERR("(MakeBW)Image does not contain data");
|
|
|
|
if(Bpp<=8)
|
|
GENNFERR("(ReduceTo8Bit)Already 8bit");
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
if(itype==ITYPE_RGB)
|
|
{
|
|
int psize=(Bpp>>3);
|
|
int i, j, x, y, axl = (xlen-1)*psize;
|
|
int ystop = (ylen-1)*Pitch;
|
|
RGBPixel *tptr0, *tptr1, *tptr2;
|
|
ImgRGBColor col0, col1, col2;
|
|
|
|
for(i=0,y=0;y<ystop;i++,y+=Pitch)
|
|
for(j=0,x=0;x<axl;j++,x+=psize)
|
|
{
|
|
tptr0 = (RGBPixel *)(dtp+x+y);
|
|
|
|
col0.r = static_cast<BYTE>(im[i*xdim+j]);
|
|
col0.g = static_cast<BYTE>(abs((int)(((im[i*xdim+j+1]-im[i*xdim+j])+(im[(i+1)*xdim+j]-im[i*xdim+j]))*0.25f*32)));
|
|
|
|
tptr0->Set(col0, Mask);
|
|
}
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
{
|
|
tptr0 = (RGBPixel *)(dtp+x+y);
|
|
col0.Set(*tptr0,Mask);
|
|
|
|
tptr1 = (RGBPixel *)(dtp+(x+psize)+y);
|
|
col1.Set(*tptr1,Mask);
|
|
|
|
tptr2 = (RGBPixel *)(dtp+x+(y+Pitch));
|
|
col2.Set(*tptr2,Mask);
|
|
|
|
col0.b = static_cast<BYTE>(abs((int)(((col1.g-col0.g)+(col2.g-col0.g))*0.25f*4)));
|
|
|
|
tptr0->Set(col0, Mask);
|
|
}
|
|
}
|
|
|
|
UnLock();
|
|
}
|
|
|
|
bool Image::operator==(Image &img)
|
|
{
|
|
if(itype!=img.itype || Bpp!=img.Bpp || xlen!=img.xlen || ylen!=img.ylen) return false;
|
|
|
|
if(itype!=ITYPE_INDEXED)
|
|
MaskTo(img.Mask);
|
|
|
|
BYTE *ptr1,*ptr2;
|
|
ptr1=(BYTE *)Lock();
|
|
ptr2=(BYTE *)img.Lock();
|
|
|
|
int y,axl=xlen*(Bpp>>3);
|
|
for(y=0;y<ylen;y++)
|
|
{
|
|
if(memcmp(ptr1+y*Pitch,ptr2+y*img.Pitch,axl)!=0) return false;
|
|
}
|
|
|
|
|
|
UnLock();
|
|
img.UnLock();
|
|
return true;
|
|
}
|
|
|
|
|
|
Image &Image::operator=(Image &img)
|
|
{
|
|
int i;
|
|
Flag=img.Flag;
|
|
if(img.pal)
|
|
{
|
|
AllocPal();
|
|
for(i=0;i<256;i++) pal[i]=img.pal[i];
|
|
}
|
|
strcpy(fname,img.fname);
|
|
Mask=img.Mask;
|
|
Bpp=img.Bpp;
|
|
Pitch=img.Pitch;
|
|
xlen=img.xlen;
|
|
ylen=img.ylen;
|
|
itype=img.itype;
|
|
xpos=img.xpos;
|
|
ypos=img.ypos;
|
|
vxlen=img.vxlen;
|
|
vylen=img.vylen;
|
|
IAlloc();
|
|
SetData(img.Data);
|
|
return *this;
|
|
}
|
|
|
|
void Image::Pad(int pixs)
|
|
{
|
|
BYTE *SDat=Lock();
|
|
|
|
int x, y, sx, sy, nxlen=xlen+pixs*2, nylen=ylen+pixs*2;
|
|
int psize=(Bpp>>3);
|
|
|
|
BYTE *DDat=new BYTE[nxlen*nylen*psize];
|
|
|
|
int b;
|
|
|
|
for(y=-pixs;y<ylen+pixs;y++)
|
|
{
|
|
for(x=-pixs;x<xlen+pixs;x++)
|
|
{
|
|
if(x<0)
|
|
{
|
|
sx = 0;
|
|
}
|
|
else
|
|
{
|
|
if(x>=xlen)
|
|
{
|
|
sx = xlen-1;
|
|
}
|
|
else
|
|
{
|
|
sx = x;
|
|
}
|
|
}
|
|
|
|
if(y<0)
|
|
{
|
|
sy=0;
|
|
}
|
|
else
|
|
{
|
|
if(y>=ylen)
|
|
{
|
|
sy = ylen-1;
|
|
}
|
|
else
|
|
{
|
|
sy = y;
|
|
}
|
|
}
|
|
|
|
for(b=0;b<psize;b++)
|
|
{
|
|
DDat[psize*((x+pixs)+(y+pixs)*nxlen) + b] = SDat[psize*(sx+sy*xlen) + b];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
delete Data;
|
|
Data=DDat;
|
|
xlen=nxlen;
|
|
ylen=nylen;
|
|
Pitch=xlen*(Bpp>>3);
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::MakeSlopeMap(float xscale,float yscale,float zscale,ImgRGBColor lowcol,ImgRGBColor highcol)
|
|
{
|
|
if(!IsData())
|
|
GENNFERR("(MakeSlopeMap)Image does not contain data");
|
|
|
|
if(Bpp>8) ReduceTo8Bit(RMD_MAX);
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x, y, axl = (xlen-1)*psize;
|
|
int ystop = (ylen-1)*Pitch;
|
|
float gdist,tdist,ascale;
|
|
int cp;
|
|
|
|
ascale=(float)sqrt(xscale*xscale+yscale*yscale);
|
|
for(y=Pitch;y<ystop-Pitch;y+=Pitch)
|
|
for(x=1;x<axl-1;x+=psize)
|
|
{
|
|
cp=(int)dtp[x+y];
|
|
gdist=(float)atan(fabs((dtp[x+y-1]-cp)*zscale/xscale));
|
|
tdist=(float)atan(fabs((cp-dtp[x+y+1])*zscale/xscale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
tdist=(float)atan(fabs((dtp[x+y-Pitch]-cp)*zscale/yscale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
tdist=(float)atan(fabs((cp-dtp[x+y+Pitch])*zscale/yscale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
/*
|
|
tdist=(float)atan(fabs((dtp[x+y-(Pitch+1)]-cp)*zscale/ascale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
tdist=(float)atan(fabs((cp-dtp[x+y+(Pitch+1)])*zscale/ascale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
tdist=(float)atan(fabs((dtp[x+(y-Pitch)+1]-cp)*zscale/ascale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
tdist=(float)atan(fabs((cp-dtp[x+y+Pitch+1])*zscale/ascale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
*/
|
|
dtp[x+y-(Pitch+1)]=(BYTE)(gdist*256.0f/3.14159265359f);
|
|
|
|
}
|
|
|
|
MakePalette(lowcol,highcol);
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::MakeContourMap(float xscale,float yscale,float zscale,
|
|
int step,
|
|
ImgRGBColor bgcol,
|
|
ImgRGBColor lolinecol,ImgRGBColor highlinecol)
|
|
{
|
|
if(!IsData())
|
|
GENNFERR("(MakeSlopeMap)Image does not contain data");
|
|
|
|
if(Bpp>8) ReduceTo8Bit(RMD_MAX);
|
|
if(xlen<4 || ylen<4) return;
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x, y, axl = (xlen-1)*psize;
|
|
int ystop = (ylen-1)*Pitch;
|
|
int cp;
|
|
int blim=256/step;
|
|
for(y=0;y<ystop;y+=Pitch)
|
|
for(x=0;x<axl;x+=psize)
|
|
dtp[x+y]=(dtp[x+y]/blim)*blim;
|
|
|
|
for(y=Pitch;y<ystop-Pitch;y+=Pitch)
|
|
{
|
|
for(x=1;x<axl-1;x+=psize)
|
|
{
|
|
cp=(int)dtp[x+y];
|
|
if(
|
|
dtp[x+y-1]!=cp ||
|
|
dtp[x+y+1]!=cp ||
|
|
dtp[x+y-Pitch]!=cp ||
|
|
dtp[x+y+Pitch]!=cp ||
|
|
dtp[(x+y-Pitch)-1]!=cp ||
|
|
dtp[(x+y-Pitch)+1]!=cp ||
|
|
dtp[(x+y+Pitch)-1]!=cp ||
|
|
dtp[(x+y+Pitch)+1]!=cp
|
|
)
|
|
dtp[x+y-(Pitch+1)]=cp;
|
|
else
|
|
dtp[x+y-(Pitch+1)]=0;
|
|
}
|
|
}
|
|
MakePalette(lolinecol,highlinecol);
|
|
pal[0]=bgcol;
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::ShowSlopeLimit(float xscale,float yscale,float zscale,float limit,ImgRGBColor lowcol,ImgRGBColor highcol)
|
|
{
|
|
if(!IsData())
|
|
GENNFERR("(MakeSlopeMap)Image does not contain data");
|
|
|
|
if(Bpp>8) ReduceTo8Bit(RMD_MAX);
|
|
|
|
BYTE *dtp=Lock();
|
|
|
|
int psize=(Bpp>>3);
|
|
int x, y, axl = (xlen-1)*psize;
|
|
int ystop = (ylen-1)*Pitch;
|
|
float gdist,tdist,ascale;
|
|
int cp;
|
|
|
|
ascale=(float)sqrt(xscale*xscale+yscale*yscale);
|
|
for(y=Pitch;y<ystop-Pitch;y+=Pitch)
|
|
for(x=1;x<axl-1;x+=psize)
|
|
{
|
|
cp=(int)dtp[x+y];
|
|
gdist=(float)atan(fabs((dtp[x+y-1]-cp)*zscale/xscale));
|
|
tdist=(float)atan(fabs((cp-dtp[x+y+1])*zscale/xscale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
tdist=(float)atan(fabs((dtp[x+y-Pitch]-cp)*zscale/yscale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
tdist=(float)atan(fabs((cp-dtp[x+y+Pitch])*zscale/yscale));
|
|
gdist=tdist>gdist?tdist:gdist;
|
|
|
|
gdist=gdist*(180.0f/3.14159265359f);
|
|
dtp[x+y-(Pitch+1)]=(BYTE)(gdist*256.0f/3.14159265359f);
|
|
|
|
if(gdist>limit)
|
|
dtp[x+y-(Pitch+1)]=255;
|
|
else
|
|
dtp[x+y-(Pitch+1)]=0;
|
|
}
|
|
|
|
MakePalette(lowcol,highcol);
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::MakePalette(ImgRGBColor low,ImgRGBColor high)
|
|
{
|
|
|
|
AllocPal();
|
|
int i;
|
|
|
|
float cr,cg,cb;
|
|
float dr,dg,db;
|
|
cr=(float)low.r;
|
|
cg=(float)low.g;
|
|
cb=(float)low.b;
|
|
|
|
dr=(high.r-low.r)/256.0f;
|
|
dg=(high.g-low.g)/256.0f;
|
|
db=(high.b-low.b)/256.0f;
|
|
|
|
|
|
for(i=0;i<256;i++)
|
|
{
|
|
pal[i]=ImgRGBColor((int)cr,(int)cg,(int)cb);
|
|
cr+=dr;
|
|
cb+=db;
|
|
cg+=dg;
|
|
}
|
|
|
|
RealizePalette();
|
|
}
|