Files
firestorm/Gameleap/code/mw4/Libraries/imagelib/IUtils.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

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();
}