Files
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

1383 lines
32 KiB
C++

#include "image.h"
#include<stdio.h>
#include<math.h>
#include<string.h>
#define Round(x) floor((x)+.5f);
// >>>>>>>>>>>>>>>>>>>> Histogram Members
Histogram::Histogram()
{
}
void Histogram::Clear()
{
for(int i=0;i<256;i++) Data[i]=0;
Peak=0;
}
Histogram::Histogram(Image &img,RMETHOD rmet)
{
Histogram();
img.FillHistogram(this,rmet);
}
int Histogram::GetBottom(float per)
{
int lowcut=(int)(per*.01*Peak);
int i;
for(i=0;i<256;i++) if (Data[i]>lowcut) return i;
STOP(("Invalid Histogram"));
return 0;
}
int Histogram::GetTop(float per)
{
int lowcut=(int)(per*.01*Peak);
for(int i=255;i>=0;i--) if (Data[i]>lowcut) return i;
STOP(("Invalid Histogram"));
return 255;
}
Histogram::~Histogram()
{
}
RGBHistogram::RGBHistogram(Image &img)
{
img.FillHistogram(this);
}
void RGBHistogram::Clear()
{
RHist.Clear();
GHist.Clear();
BHist.Clear();
}
ImgRGBColor RGBHistogram::GetBottom(float per)
{
ImgRGBColor col;
col.r=RHist.GetBottom(per);
col.g=GHist.GetBottom(per);
col.b=BHist.GetBottom(per);
col.a=0;
return col;
}
ImgRGBColor RGBHistogram::GetTop(float per)
{
ImgRGBColor col;
col.r=RHist.GetTop(per);
col.g=GHist.GetTop(per);
col.b=BHist.GetTop(per);
col.a=255;
return col;
}
// >>>>>>>>>>>>>>>>>>>> Image Members
Image::Image(char *Str)
{
Init();
Load(Str);
}
Image::Image(Image &img)
{
Init();
*this=img;
}
void Image::Init()
{
strcpy(fname,"");
Data=NULL;
xpos=ypos=vxlen=vylen=LockStack=Pitch=Bpp=xlen=ylen=0;
itype=ITYPE_RGB;
pal=NULL;
Mask.Set(0x00ff0000,0x0000ff00,0x000000ff,0) ;
}
Image::Image() { Init(); }
Image::Image(int xl,int yl)
{
Init();
CreateBlank(xl,yl);
}
Image::Image(int xl,int yl,ImgRGBColor col)
{
Init();
CreateSolid(xl,yl,col);
}
Image::~Image() { Delete(); }
ImgRGBColor Image::GetColor(Point &p)
{
if(p.x>=xlen || p.y>=ylen) return ImgRGBColor(0,0,0);
ImgRGBColor trgb;
RGBPixel *tptr;
BYTE *bp=Lock();
tptr=(RGBPixel *)(bp+ ((p.x+p.y*xlen)*(Bpp>>3)));
trgb.Set(*tptr,Mask);
UnLock();
return trgb;
}
// >>>>>>>>>>>>>>>>>>>>>>>> Internals
void Image::IAlloc()
{
if(IsData()) IFree();
Pitch=xlen*(Bpp>>3);
BYTE *dt=new BYTE[ylen*Pitch+4];
if(dt==NULL)
GENFERR("Not Enough Memory to Create Image");
Data=dt;
Flag|=IMG_ISDATA;
}
void Image::SetData(BYTE *dt)
{
int y,axl=xlen*(Bpp>>3);
int yval1,yval2;
if(!IsData()) IAlloc();
BYTE *dat=Lock();
for(yval1=yval2=y=0;y<ylen;y++,yval1+=Pitch,yval2+=axl)
memcpy(dat+yval1,dt+yval2,axl);
// for(x=0;x<axl;x++) dat[x+yval1]=dt[x+yval2]; //Revised for Performance
UnLock();
}
void Image::IFree()
{
if(IsData()) delete Data;
Mask(Flag,IMG_ISDATA);
Data=0;
}
void Image::Delete()
{
IFree();
fname[0]=0;
xpos=ypos=vxlen=vylen=Bpp=xlen=ylen=0;
itype=ITYPE_RGB;
if(pal) delete pal;
// for(int i=0;i<256;i++) pal[i].r=pal[i].g=pal[i].b=0;
}
int Image::IsData() {return Flag&IMG_ISDATA;}
BYTE *Image::Lock()
{
if(Flag&IMG_LOCKED) UnLock();
Flag|=IMG_LOCKED;
return Data;
}
void Image::UnLock() { if(Flag&IMG_LOCKED) Mask(Flag,IMG_LOCKED); }
//>>>>>>>>>>>>>>>>>> Palletteing
void Image::RealizePalette() //here for overloading
{ }
void Image::SetPaletteEntry(int idx,int r,int g ,int b)
{
AllocPal();
SetPaletteEntry(idx,ImgRGBColor(r,g,b));
}
void Image::SetPaletteEntry(int idx,float r,float g,float b)
{
AllocPal();
SetPaletteEntry(idx,ImgRGBColor(r,g,b));
}
void Image::SetPaletteEntry(int idx,const ImgRGBColor &rgb)
{
AllocPal();
if (idx>255 ||idx <0) return;
pal[idx]=rgb;
RealizePalette();
}
void Image::MakeGrayscalePalette()
{
AllocPal();
int i;
for(i=0;i<256;i++)
{
pal[i]=i;
}
RealizePalette();
}
ImgRGBColor Image::GetPaletteEntry(int idx)
{ return pal[idx]; }
//>>>>>>>>>>>>>>>>>> Loading Helpers
void Image::Load(char *str)
{
FILE *fl=fopen(str,"rb");
if(!fl)
{
char tfn[MAX_PATH*2];
strcpy(tfn,"Cannot open file for reading:");
strcat(tfn,str);
GENNFERR(tfn);
}
strcpy(fname,str);
Load(fl);
fclose(fl);
}
void Image::Load(FILE *fl)
{
if(IsTiff(fl))
LoadTiff(fl);
else
if(IsGif(fl))
LoadGif(fl);
else
if(IsPng(fl))
LoadPng(fl);
else
if(IsTga())
LoadTga(fl);
else
STOP(("Unknown format for General Load"));
// if(IsTga()) LoadTga(fl);
// if(IsPng()) LoadPng(fl);
}
void Image::Load()
{
Load(fname);
}
void Image::Blt(Image &img,FRect dst)
{
dst.left*=vxlen; dst.right*=vxlen;
dst.top*=vylen; dst.bottom*=vylen;
Blt(img,(RECT)TRect(dst));
}
void Image::Blt(Image &img,FRect dst,FRect src)
{
dst.left*=vxlen; dst.right*=vxlen;
dst.top*=vylen; dst.bottom*=vylen;
src.left*=img.vxlen; src.right*=img.vxlen;
src.top*=img.vylen; src.bottom*=img.vylen;
Blt(img,TRect(dst),TRect(src));
}
void Image::Blt(Image &img,int x,int y,FRect src)
{
src.left*=img.vxlen; src.right*=img.vxlen;
src.top*=img.vylen; src.bottom*=img.vylen;
Blt(img,x,y,TRect(src));
}
void Image::Blt(Image &img,RECT &dst)
{
Blt(img,dst,TRect(0,0,img.vxlen,img.vylen));
}
void Image::Blt(Image &img,int x,int y)
{
Blt(img,x,y,TRect(0,0,img.vxlen,img.vylen));
}
/*
void Image::Blt(Image &img,RECT dst,RECT &src)
{
int dr,db;
int xd,yd;
int ddx,ddy;
float MyFact;
MyFact=((float)(src.right-src.left))/(dst.right-dst.left);
src.top+=(int)(MyFact/2);
src.bottom+=(int)(MyFact/2);
src.left+=(int)(MyFact/2);
src.right+=(int)(MyFact/2);
ddx=dst.right-dst.left;
ddy=dst.bottom-dst.top;
xd=src.right-src.left;
yd=src.bottom-src.top;
dst.right-=xpos;
dst.left-=xpos;
dst.bottom-=ypos;
dst.top-=ypos;
if(src.left>=(img.xpos+img.xlen) || src.top>=(img.ypos+img.ylen) ||
src.right<=img.xpos || src.bottom<img.ypos ) return;
//left clip
if(src.left<=img.xpos) //fix source move dest.
{ dst.left+=(img.xpos-src.left)*ddx/xd; src.left=0;}
else //fix destination move source
src.left-=img.xpos;
if(src.top<=img.ypos) //fix source move dest.
{ dst.top+=(img.ypos-src.top)*ddy/yd; src.top=0; }
else //fix destination move source
src.top-=img.ypos;
//right clip
if(src.right>(img.xpos+img.xlen))
{
dst.right-=(src.right-(img.xpos+img.xlen))*ddx/xd;
src.right=img.xlen;
}
else
src.right=img.xlen-((img.xlen+img.xpos)-src.right);
if(src.bottom>(img.ypos+img.ylen))
{
dst.bottom-=(src.bottom-(img.ypos+img.ylen))*ddy/yd;
src.bottom=img.ylen;
}
else
src.bottom=img.ylen-((img.ylen+img.ypos)-src.bottom);
if(dst.left<0) { src.left-=dst.left*img.xlen/ddx; dst.left=0; }
if(dst.top<0) { src.top-=dst.top*img.ylen/ddy; dst.top=0; }
if(dst.right>xlen) { src.right=src.left+(xlen-dst.left)*xd/ddx; dr=xlen;}
else {dr=dst.right; }
if(dst.bottom>ylen){ src.bottom=src.top+(ylen-dst.top)*yd/ddy; db=ylen; }
else {db=dst.bottom; }
dst.right=dr;
dst.bottom=db;
if(src.right<=0 || src.bottom<=0 ||
src.left>=img.xlen || src.top>=img.ylen) return;
//ret=Surface->Blt(&dst,img.Surface,&src,flag,&bfx);
BYTE *dptS=img.Lock(),*dptD=Lock();
if((dst.right-dst.left)<=(src.right-src.left)) //Downsample X
{
if((dst.bottom-dst.top)<=(src.bottom-src.top)) //Downsample Y
{
int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
int x,y;
float prx=(float)(src.right-src.left)/(2*(dst.right-dst.left));
float pry=(float)(src.bottom-src.top)/(2*(dst.bottom-dst.top));
float csx,csy;
ImgRGBColor col,colsum;
RGBPixel *tptr;
ImageOperator Opt;
Opt.CreateGaussian((int)(pry*2),(int)(prx*2));
int r,c,cpx,cpy,idx;
float fr,fg,fb,fa,sum,w;
BYTE *tdp;
int rs,re,cs,ce;
re=Opt.GetRows()>>1;
rs=-re;
ce=Opt.GetCols()>>1;
cs=-ce;
for(csy=(float)src.top,y=dst.top;y<dst.bottom;y++,csy+=pry*2)
for(csx=(float)src.left,x=dst.left;x<dst.right;x++,csx+=prx*2)
{
cpx=(int)Round(csx+cs);
cpy=(int)Round(csy+rs);
tdp=dptS+(cpx+cpy*img.xlen)*psizeS;
fr=fg=fb=fa=sum=0.0f;
for(r=rs;r<=re;r++,tdp+=img.Pitch)
for(idx=0,c=cs;c<=ce;c++,idx+=psizeS)
{
cpx=(int)(csx+c); cpy=(int)(csy+r);
if(cpx>=0 && cpy>=0 && cpx<img.xlen && cpy<img.ylen)
{
tptr=(RGBPixel *)(tdp+idx);
col.Set(*tptr,img.Mask);
w=Opt.GetWeight(r+re,c+ce);
fr+=col.r*w;
fg+=col.g*w;
fb+=col.b*w;
fa+=col.a*w;
sum+=w;
}
}
fr/=sum; fg/=sum; fb/=sum; fa/=sum;
colsum.r=(int)floor(fr+0.05f);
colsum.g=(int)floor(fg+0.05f);
colsum.b=(int)floor(fb+0.05f);
colsum.a=(int)floor(fa+0.05f);
tptr=(RGBPixel *)(dptD+((int)x+((int)y)*xlen)*psizeD);
tptr->Set(colsum,Mask);
}
}
else //UpSample Y
{
GENFERR("Upsampling not supported(yet)");
}
}
else //UpSample X
{
if((dst.bottom-dst.top)<=(src.bottom-src.top)) //Downsample Y
{
GENFERR("Upsampling not supported(yet)");
}
else //UpSample Y
{
GENFERR("Upsampling not supported(yet)");
}
}
UnLock();
img.UnLock();
}
*/
void Image::Blt(Image &img,RECT dst,RECT &src)
{
int dr,db;
int xd,yd;
int ddx,ddy;
ddx=dst.right-dst.left;
ddy=dst.bottom-dst.top;
xd=src.right-src.left;
yd=src.bottom-src.top;
dst.right-=xpos;
dst.left-=xpos;
dst.bottom-=ypos;
dst.top-=ypos;
if(src.left>=(img.xpos+img.xlen) || src.top>=(img.ypos+img.ylen) ||
src.right<=img.xpos || src.bottom<img.ypos ) return;
//left clip
if(src.left<=img.xpos) //fix source move dest.
{ dst.left+=(img.xpos-src.left)*ddx/xd; src.left=0;}
else //fix destination move source
src.left-=img.xpos;
if(src.top<=img.ypos) //fix source move dest.
{ dst.top+=(img.ypos-src.top)*ddy/yd; src.top=0; }
else //fix destination move source
src.top-=img.ypos;
//right clip
if(src.right>(img.xpos+img.xlen))
{
dst.right-=(src.right-(img.xpos+img.xlen))*ddx/xd;
src.right=img.xlen;
}
else
src.right=img.xlen-((img.xlen+img.xpos)-src.right);
if(src.bottom>(img.ypos+img.ylen))
{
dst.bottom-=(src.bottom-(img.ypos+img.ylen))*ddy/yd;
src.bottom=img.ylen;
}
else
src.bottom=img.ylen-((img.ylen+img.ypos)-src.bottom);
if(dst.left<0) { src.left-=dst.left*img.xlen/ddx; dst.left=0; }
if(dst.top<0) { src.top-=dst.top*img.ylen/ddy; dst.top=0; }
if(dst.right>xlen) { src.right=src.left+(xlen-dst.left)*xd/ddx; dr=xlen;}
else {dr=dst.right; }
if(dst.bottom>ylen){ src.bottom=src.top+(ylen-dst.top)*yd/ddy; db=ylen; }
else {db=dst.bottom; }
dst.right=dr;
dst.bottom=db;
if(src.right<=0 || src.bottom<=0 ||
src.left>=img.xlen || src.top>=img.ylen) return;
//ret=Surface->Blt(&dst,img.Surface,&src,flag,&bfx);
enum STYPE {ST_DOWN,ST_UP,ST_COPY};
STYPE xdec,ydec;
if((dst.right-dst.left)==(src.right-src.left))
xdec=ST_COPY;
else
if((dst.right-dst.left)<(src.right-src.left))
xdec=ST_DOWN;
else
xdec=ST_UP;
if((dst.bottom-dst.top)==(src.bottom-src.top))
ydec=ST_COPY;
else
if((dst.bottom-dst.top)<(src.bottom-src.top))
ydec=ST_DOWN;
else
ydec=ST_UP;
BYTE *dptS=img.Lock(),*dptD=Lock();
bool fastcopy;
if(Bpp==img.Bpp && Mask==img.Mask) fastcopy=true; else fastcopy=false;
if(xdec==ST_COPY && ydec==ST_COPY)
{//Pure Copy
int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
int sp=img.GetPitch()-(src.right-src.left)*psizeS,dp=GetPitch()-(dst.right-dst.left)*psizeD;
int x,y;
ImgRGBColor col;
RGBPixel *tptr;
BYTE *tdptS=dptS+(src.left+src.top*img.GetWidth())*psizeS,*tdptD=dptD+(dst.left+dst.top*GetWidth())*psizeD;
if(fastcopy)
{
int scanllen=(dst.right-dst.left)*psizeD;
for(y=dst.top;y<dst.bottom;y++,tdptS+=img.GetPitch(), tdptD+=GetPitch())
CopyMemory(tdptD,tdptS,scanllen);
}
else
{
for(y=dst.top;y<dst.bottom;y++,tdptS+=sp,tdptD+=dp)
for(x=dst.left;x<dst.right;x++,tdptS+=psizeS,tdptD+=psizeD)
{
tptr=(RGBPixel *)(tdptS);
col.Set(*tptr,img.Mask);
tptr=(RGBPixel *)(tdptD);
tptr->Set(col,Mask);
}
}
}
if((xdec==ST_DOWN && ydec==ST_DOWN) ||
(xdec==ST_DOWN && ydec==ST_COPY) ||
(xdec==ST_COPY && ydec==ST_DOWN))
{
int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
int x,y;
float prx=(float)(src.right-src.left)/(2*(dst.right-dst.left));
float pry=(float)(src.bottom-src.top)/(2*(dst.bottom-dst.top));
float csx,csy,xslp,yslp;
int coldiv;
ImgRGBColor col,colsum;
RGBPixel *tptr;
int ixslp,iyslp;
for(csy=(float)src.top+pry,y=dst.top;y<dst.bottom;y++,csy+=pry*2)
for(csx=(float)src.left+prx,x=dst.left;x<dst.right;x++,csx+=prx*2)
{
colsum.r=colsum.g=colsum.b=colsum.a=0;
coldiv=0;
for(yslp=csy-pry;yslp<csy+pry;yslp+=1.0f)
for(xslp=csx-prx;xslp<csx+prx;xslp+=1.0f)
{
ixslp=(int)xslp;
iyslp=(int)yslp;
if(ixslp>=0 && iyslp>=0 && ixslp<img.xlen && iyslp<img.ylen)
{
tptr=(RGBPixel *)(dptS+(ixslp+iyslp*img.xlen)*psizeS);
col.Set(*tptr,img.Mask);
colsum.r+=col.r;
colsum.g+=col.g;
colsum.b+=col.b;
colsum.a+=col.a;
coldiv++;
}
}
if(coldiv==0) coldiv=1;
colsum.r/=coldiv;
colsum.g/=coldiv;
colsum.b/=coldiv;
colsum.a/=coldiv;
tptr=(RGBPixel *)(dptD+((int)x+((int)y)*xlen)*psizeD);
tptr->Set(colsum,Mask);
}
}
if((xdec==ST_UP && ydec==ST_UP) ||
(xdec==ST_UP && ydec==ST_COPY) ||
(xdec==ST_COPY && ydec==ST_UP))
{
int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
int x,y;
float prx=(float)(src.right-src.left)/(dst.right-dst.left);
float pry=(float)(src.bottom-src.top)/(dst.bottom-dst.top);
float yacc,xacc;
ImgRGBColor lhcol,nhcol,lvcol,nvcol,col;
RGBPixel *tptr;
int ixacc,iyacc;
yacc=0.0f;
for(y=dst.top;y<dst.bottom;y++)
{
xacc=0.0f;
iyacc=(int)yacc;
for(x=dst.left;x<dst.right;x++)
{
ixacc=(int)xacc;
tptr=(RGBPixel *)(dptS+(ixacc+iyacc*img.xlen)*psizeS);
col.Set(*tptr,img.Mask);
tptr=(RGBPixel *)(dptD+(x+y*xlen)*psizeD);
tptr->Set(col,Mask);
xacc+=prx;
}
yacc+=pry;
}
}
if((xdec==ST_DOWN && ydec==ST_UP) ||
(xdec==ST_UP && ydec==ST_DOWN) )
{
Image tmpim;
RECT tmpdrct;
tmpdrct.left=tmpdrct.top=0;
tmpdrct.right=dst.right-dst.left;
tmpdrct.bottom=src.bottom-src.top;
tmpim.CreateBlank(tmpdrct.right,tmpdrct.bottom,itype,Bpp);
tmpim.Blt(img,tmpdrct,src);
Blt(tmpim,dst,tmpdrct);
}
UnLock();
img.UnLock();
}
void Image::Blt(Image &img,int x,int y,RECT &src)
{
int xd,yd;
xd=src.right-src.left;
yd=src.bottom-src.top;
x+=img.xpos-xpos;
y+=img.ypos-ypos;
if((x+xd)>xlen) src.right-=(x+xd)-xlen;
if((y+yd)>ylen) src.bottom-=(y+yd)-ylen;
if(x<0) {src.left-=x; x=0;}
if(y<0) {src.top-=y; y=0;}
if(src.right<=0 || src.bottom<=0 ||
src.left>=img.xlen || src.top>=img.ylen) return;
RECT dst={x,y,x+img.xlen,y+img.ylen};
if(dst.bottom>ylen) dst.bottom=ylen;
if(dst.right>xlen) dst.right=xlen;
//ret=Surface->Blt(&dst,img.Surface,NULL,flag,&bfx);
int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
int xc,yc,axlS=img.Pitch,axlD=Pitch;
RGBPixel *tptr;
ImgRGBColor col;
BYTE *dptS=img.Lock(),*dptD=Lock();
int SVoff,DVoff;
int SHoff,DHoff;
for(SVoff=src.top*axlS,DVoff=dst.top*axlD,yc=dst.top;
yc<dst.bottom;
yc++,SVoff+=axlS,DVoff+=axlD)
for(SHoff=src.left*psizeS,DHoff=dst.left*psizeD,xc=dst.left;
xc<dst.right;
xc++,SHoff+=psizeS,DHoff+=psizeD)
{
tptr=(RGBPixel *)(dptS+SHoff+SVoff);
col.Set(*tptr,Mask);
tptr=(RGBPixel *)(dptD+DHoff+DVoff);
tptr->Set(col,img.Mask);
}
UnLock();
img.UnLock();
}
void Image::MeanBlur(int xs,int ys)
{
ImageOperator Fil;
Fil.CreateMean(xs,ys);
ApplyOperator(Fil);
}
void Image::GaussianBlur(float pix)
{
ImageOperator Fil;
Fil.CreateGaussian(pix);
ApplyOperator(Fil);
}
void Image::ApplyOperator(ImageOperator &Opt)
{
if(itype!=ITYPE_RGB)
GENNFERR("(ApplyOperator)Image is not RGB");
Image tmpimg;
tmpimg.CreateBlank(xlen,ylen,itype,Bpp);
tmpimg.Mask=Mask;
int x,y,r,c,cpx,cpy;
float fr,fg,fb,fa,sum,w;
int rs,re,cs,ce,psize=Bpp>>3;
re=Opt.GetRows()>>1;
rs=-re;
ce=Opt.GetCols()>>1;
cs=-ce;
BYTE *dpt=Lock();
BYTE *dd=tmpimg.Lock();
RGBPixel *tptr;
ImgRGBColor col;
int idx;
BYTE *tdp;
for(y=0;y<ylen;y++)
for(x=0;x<xlen;x++)
{
tdp=(BYTE *)(dpt+((x+cs)+(y+rs)*xlen)*psize);
sum=fr=fg=fb=fa=0.0f; //Zero out Accumulators
BYTE *tdp=(BYTE *)(dpt+((x+cs)+(y+rs)*xlen)*psize);
if( (x+cs)<0 || (x+ce)>=xlen ||
(y+rs)<0 || (y+re)>=ylen ) //This is an edge
{
for(r=rs;r<=re;r++,tdp+=Pitch)
for(idx=0,c=cs;c<=ce;c++,idx+=psize)
{
cpx=x+c; cpy=y+r;
if(cpx>=0 && cpy>=0 && cpx<xlen && cpy<ylen)
{
tptr=(RGBPixel *)(tdp+idx);
col.Set(*tptr,Mask);
w=Opt.GetWeight(r+re,c+ce);
fr+=col.r*w;
fg+=col.g*w;
fb+=col.b*w;
fa+=col.a*w;
sum+=w;
}
}
}
else
{
for(r=rs;r<=re;r++,tdp+=Pitch)
for(idx=0,c=cs;c<=ce;c++,idx+=psize)
{
tptr=(RGBPixel *)(tdp+idx);
col.Set(*tptr,Mask);
w=Opt.GetWeight(r+re,c+ce);
fr+=col.r*w;
fg+=col.g*w;
fb+=col.b*w;
fa+=col.a*w;
}
sum=Opt.GetTotal();
}
fr/=sum; fg/=sum; fb/=sum; fa/=sum;
col.r=(int)floor(fr+0.5f);
col.g=(int)floor(fg+0.5f);
col.b=(int)floor(fb+0.5f);
col.a=(int)floor(fa+0.5f);
tptr=(RGBPixel *)(dd);
tptr->Set(col,tmpimg.Mask);
dd+=psize;
}
tmpimg.UnLock();
UnLock();
*this=tmpimg;
}
void Image::BltBlend(Image &img,float efact,RECT &src,float tfact,float rfact,float bfact,float lfact)
{
RECT dst;
dst.top=dst.left=0;
dst.right=GetWidth();
dst.bottom=GetHeight();
float MyFact;
MyFact=((float)(src.right-src.left))/(dst.right-dst.left);
if(tfact<MyFact) tfact=MyFact;
if(bfact<MyFact) bfact=MyFact;
if(rfact<MyFact) rfact=MyFact;
if(lfact<MyFact) lfact=MyFact;
src.top+=(int)(MyFact/2);
src.bottom+=(int)(MyFact/2);
src.left+=(int)(MyFact/2);
src.right+=(int)(MyFact/2);
/*
int dr,db;
int xd,yd;
int ddx,ddy;
ddx=dst.right-dst.left;
ddy=dst.bottom-dst.top;
xd=src.right-src.left;
yd=src.bottom-src.top;
dst.right-=xpos;
dst.left-=xpos;
dst.bottom-=ypos;
dst.top-=ypos;
if(src.left>=(img.xpos+img.xlen) || src.top>=(img.ypos+img.ylen) ||
src.right<=img.xpos || src.bottom<img.ypos ) return;
//left clip
if(src.left<=img.xpos) //fix source move dest.
{ dst.left+=(img.xpos-src.left)*ddx/xd; src.left=0;}
else //fix destination move source
src.left-=img.xpos;
if(src.top<=img.ypos) //fix source move dest.
{ dst.top+=(img.ypos-src.top)*ddy/yd; src.top=0; }
else //fix destination move source
src.top-=img.ypos;
//right clip
if(src.right>(img.xpos+img.xlen+1))
{
dst.right-=(src.right-(img.xpos+img.xlen))*ddx/xd;
src.right=img.xlen;
}
else
src.right=img.xlen-((img.xlen+img.xpos)-src.right);
if(src.bottom>(img.ypos+img.ylen+1))
{
dst.bottom-=(src.bottom-(img.ypos+img.ylen))*ddy/yd;
src.bottom=img.ylen;
}
else
src.bottom=img.ylen-((img.ylen+img.ypos)-src.bottom);
if(dst.left<0) { src.left-=dst.left*img.xlen/ddx; dst.left=0; }
if(dst.top<0) { src.top-=dst.top*img.ylen/ddy; dst.top=0; }
if(dst.right>xlen) { src.right=src.left+(xlen-dst.left)*xd/ddx; dr=xlen;}
else {dr=dst.right; }
if(dst.bottom>ylen){ src.bottom=src.top+(ylen-dst.top)*yd/ddy; db=ylen; }
else {db=dst.bottom; }
dst.right=dr;
dst.bottom=db;
if(src.right<=0 || src.bottom<=0 ||
src.left>=img.xlen || src.top>=img.ylen) return;
//ret=Surface->Blt(&dst,img.Surface,&src,flag,&bfx);
*/
BYTE *dptS=img.Lock(),*dptD=Lock();
if((dst.right-dst.left)<=(src.right-src.left)) //Downsample X
{
if((dst.bottom-dst.top)<=(src.bottom-src.top)) //Downsample Y
{
int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
int x,y;
float prx=(float)(src.right-src.left)/(2*(dst.right-dst.left));
float pry=(float)(src.bottom-src.top)/(2*(dst.bottom-dst.top));
float csx,csy;
ImgRGBColor col,colsum;
RGBPixel *tptr;
ImageOperator Opt;
int r,c,cpx,cpy,idx;
float fr,fg,fb,fa,sum,w;
float CurFact;
BYTE *tdp;
int rs,re,cs,ce;
Opt.CreateGaussian((int)MyFact,(int)MyFact);
re=Opt.GetRows()>>1;
rs=-re;
ce=Opt.GetCols()>>1;
cs=-ce;
float tr,br,lr,rr,mr;
float invefact=1/efact;
for(csy=(float)src.top,y=dst.top;y<dst.bottom;y++,csy+=pry*2)
for(csx=(float)src.left,x=dst.left;x<dst.right;x++,csx+=prx*2)
{
tr=1.0f-((float)(y*invefact)/(ylen));
if(tr<0) tr=0.0f;
br=((float)(( (y+1) - (ylen-(ylen*efact)) )*invefact)/(ylen));
if(br<0) br=0.0f;
lr=1.0f-((float)(x*invefact)/(xlen));
if(lr<0) lr=0.0f;
rr=((float)(( (x+1) - (xlen-(xlen*efact)) )*invefact)/(xlen));
if(rr<0) rr=0.0f;
mr=1.0f-(tr+br+lr+rr);
if(mr<0) mr=0.0f;
CurFact=MyFact;
CurFact=(tfact*tr)>CurFact?tfact*tr:CurFact;
CurFact=(bfact*br)>CurFact?bfact*br:CurFact;
CurFact=(lfact*lr)>CurFact?lfact*lr:CurFact;
CurFact=(rfact*rr)>CurFact?rfact*rr:CurFact;
/*
CurFact=
(MyFact*mr+
tfact*tr+
bfact*br+
lfact*lr+
rfact*rr)/( tr+br+lr+rr+mr );
*/
CurFact=(float)floor(CurFact+0.5f);
Opt.CreateGaussian((int)CurFact,(int)CurFact);
re=Opt.GetRows()>>1;
rs=-re;
ce=Opt.GetCols()>>1;
cs=-ce;
cpx=(int)Round(csx+cs);
cpy=(int)Round(csy+rs);
tdp=dptS+(cpx+cpy*img.xlen)*psizeS;
fr=fg=fb=fa=sum=0.0f;
for(r=rs;r<=re;r++,tdp+=img.Pitch)
for(idx=0,c=cs;c<=ce;c++,idx+=psizeS)
{
cpx=(int)(csx+c); cpy=(int)(csy+r);
// cpx=(int)Round(csx+c); cpy=(int)Round(csy+r);
if(cpx>=0 && cpy>=0 && cpx<img.xlen && cpy<img.ylen)
{
tptr=(RGBPixel *)(tdp+idx);
col.Set(*tptr,img.Mask);
w=Opt.GetWeight(r+re,c+ce);
fr+=col.r*w;
fg+=col.g*w;
fb+=col.b*w;
fa+=col.a*w;
sum+=w;
}
}
fr/=sum; fg/=sum; fb/=sum; fa/=sum;
colsum.r=(int)Round(fr);
colsum.g=(int)Round(fg);
colsum.b=(int)Round(fb);
colsum.a=(int)Round(fa);
tptr=(RGBPixel *)(dptD+(x+y*xlen)*psizeD);
tptr->Set(colsum,Mask);
}
}
else //UpSample Y
{
GENFERR("Upsampling not supported(yet)");
}
}
else //UpSample X
{
if((dst.bottom-dst.top)<=(src.bottom-src.top)) //Downsample Y
{
GENFERR("Upsampling not supported(yet)");
}
else //UpSample Y
{
GENFERR("Upsampling not supported(yet)");
}
}
UnLock();
img.UnLock();
}
//
// Added by SMJ on 6/4/99
//
void Image::Rotate180()
{
int pixelSize = Bpp / 8;
int dataSize = Pitch * ylen;
BYTE* back = Data + dataSize - pixelSize;
BYTE* newData = new BYTE [dataSize];
BYTE* front = newData;
while (back > Data)
{
memcpy(front,back,pixelSize);
front += pixelSize;
back -= pixelSize;
}
delete Data;
Data = newData;
}
void Image::BltDominantColor(Image &img,RECT dst,RECT &src)
{
int dr,db;
int xd,yd;
int ddx,ddy;
ddx=dst.right-dst.left;
ddy=dst.bottom-dst.top;
xd=src.right-src.left;
yd=src.bottom-src.top;
dst.right-=xpos;
dst.left-=xpos;
dst.bottom-=ypos;
dst.top-=ypos;
if(src.left>=(img.xpos+img.xlen) || src.top>=(img.ypos+img.ylen) ||
src.right<=img.xpos || src.bottom<img.ypos ) return;
//left clip
if(src.left<=img.xpos) //fix source move dest.
{ dst.left+=(img.xpos-src.left)*ddx/xd; src.left=0;}
else //fix destination move source
src.left-=img.xpos;
if(src.top<=img.ypos) //fix source move dest.
{ dst.top+=(img.ypos-src.top)*ddy/yd; src.top=0; }
else //fix destination move source
src.top-=img.ypos;
//right clip
if(src.right>(img.xpos+img.xlen))
{
dst.right-=(src.right-(img.xpos+img.xlen))*ddx/xd;
src.right=img.xlen;
}
else
src.right=img.xlen-((img.xlen+img.xpos)-src.right);
if(src.bottom>(img.ypos+img.ylen))
{
dst.bottom-=(src.bottom-(img.ypos+img.ylen))*ddy/yd;
src.bottom=img.ylen;
}
else
src.bottom=img.ylen-((img.ylen+img.ypos)-src.bottom);
if(dst.left<0) { src.left-=dst.left*img.xlen/ddx; dst.left=0; }
if(dst.top<0) { src.top-=dst.top*img.ylen/ddy; dst.top=0; }
if(dst.right>xlen) { src.right=src.left+(xlen-dst.left)*xd/ddx; dr=xlen;}
else {dr=dst.right; }
if(dst.bottom>ylen){ src.bottom=src.top+(ylen-dst.top)*yd/ddy; db=ylen; }
else {db=dst.bottom; }
dst.right=dr;
dst.bottom=db;
if(src.right<=0 || src.bottom<=0 ||
src.left>=img.xlen || src.top>=img.ylen) return;
//ret=Surface->Blt(&dst,img.Surface,&src,flag,&bfx);
enum STYPE {ST_DOWN,ST_UP,ST_COPY};
STYPE xdec,ydec;
if((dst.right-dst.left)==(src.right-src.left))
xdec=ST_COPY;
else
if((dst.right-dst.left)<(src.right-src.left))
xdec=ST_DOWN;
else
xdec=ST_UP;
if((dst.bottom-dst.top)==(src.bottom-src.top))
ydec=ST_COPY;
else
if((dst.bottom-dst.top)<(src.bottom-src.top))
ydec=ST_DOWN;
else
ydec=ST_UP;
if(ydec==ST_UP || xdec==ST_UP )
STOP(("Upsampling Not Supported"));
BYTE *dptS=img.Lock(),*dptD=Lock();
bool fastcopy;
if(Bpp==img.Bpp && Mask==img.Mask) fastcopy=true; else fastcopy=false;
if(xdec==ST_COPY && ydec==ST_COPY)
{//Pure Copy
int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
int sp=img.GetPitch()-(src.right-src.left)*psizeS,dp=GetPitch()-(dst.right-dst.left)*psizeD;
int x,y;
ImgRGBColor col;
RGBPixel *tptr;
BYTE *tdptS=dptS+(src.left+src.top*img.GetWidth())*psizeS,*tdptD=dptD+(dst.left+dst.top*GetWidth())*psizeD;
if(fastcopy)
{
int scanllen=(dst.right-dst.left)*psizeD;
for(y=dst.top;y<dst.bottom;y++,tdptS+=img.GetPitch(), tdptD+=GetPitch())
CopyMemory(tdptD,tdptS,scanllen);
}
else
{
for(y=dst.top;y<dst.bottom;y++,tdptS+=sp,tdptD+=dp)
for(x=dst.left;x<dst.right;x++,tdptS+=psizeS,tdptD+=psizeD)
{
tptr=(RGBPixel *)(tdptS);
col.Set(*tptr,img.Mask);
tptr=(RGBPixel *)(tdptD);
tptr->Set(col,Mask);
}
}
}
if((xdec==ST_DOWN && ydec==ST_DOWN) ||
(xdec==ST_DOWN && ydec==ST_COPY) ||
(xdec==ST_COPY && ydec==ST_DOWN))
{
int psizeS=(img.Bpp>>3),psizeD=(Bpp>>3);
int x,y;
float prx=(float)(src.right-src.left)/(2*(dst.right-dst.left));
float pry=(float)(src.bottom-src.top)/(2*(dst.bottom-dst.top));
float csx,csy,xslp,yslp;
int colmax,idx;
ImgRGBColor col;
RGBPixel *tptr;
colmax=(int)ceil(prx*2)*(int)ceil(pry*2);
int *ColorCount=new int[colmax];
ImgRGBColor *ColorList=new ImgRGBColor[colmax];
int colortotal;
for(csy=(float)src.top+pry,y=dst.top;y<dst.bottom;y++,csy+=pry*2)
for(csx=(float)src.left+prx,x=dst.left;x<dst.right;x++,csx+=prx*2)
{
colortotal=0;
for(yslp=csy-pry;yslp<csy+pry;yslp+=1.0f)
for(xslp=csx-prx;xslp<csx+prx;xslp+=1.0f)
if(((int)xslp)>=0 && ((int)yslp)>=0 && ((int)xslp)<img.xlen && ((int)yslp)<img.ylen)
{
tptr=(RGBPixel *)(dptS+((int)xslp+((int)yslp)*img.xlen)*psizeS);
col.Set(*tptr,img.Mask);
for(idx=0;idx<colortotal && ColorList[idx]!=col;idx++);
if(idx<colortotal)
{
ColorCount[idx]++;
}
else
{
ColorCount[colortotal]=1;
ColorList[colortotal]=col;
colortotal++;
}
}
int maxnum,maxval;
maxval=0;
for(idx=0;idx<colortotal;idx++)
{
if(ColorCount[idx]>maxval)
{
maxnum=idx;
maxval=ColorCount[idx];
}
}
tptr=(RGBPixel *)(dptD+((int)x+((int)y)*xlen)*psizeD);
tptr->Set(ColorList[maxnum],Mask);
}
delete ColorCount;
delete ColorList;
}
UnLock();
img.UnLock();
}
// Image Operator
void ImageOperator::Create(int sr,int sc)
{
Destroy();
Rows=sr;
Cols=sc;
Rows|=1; Cols|=1; //Always make odd No even filters have unpredicatable results
dat=new float *[Rows];
int i,j;
for(i=0;i<Rows;i++)
{
dat[i]=new float[Cols];
for(j=0;j<Cols;j++)
dat[i][j]=0.0f;
}
Sum=0.0f;
}
void ImageOperator::Destroy()
{
int i;
for(i=0;i<Rows;i++)
delete dat[i];
delete dat;
}
void ImageOperator::CreateGaussian(float pix)
{
//Implement This
//Create a Square Gaussian Matrix Based on a pixel radius
CreateMean((int)pix,(int)pix);
}
void ImageOperator::CreateGaussian(int sx,int sy)
{
Create(sx,sy);
Sum=0.0f;
int i,j;
for(i=0;i<Rows;i++)
for(j=0;j<Cols;j++)
{
dat[i][j]=(float)(exp((float)-(j*j/sx*sx))*exp((float)-(i*i/sy*sy)));
Sum+=dat[i][j];
}
}
void ImageOperator::CreateMean(int sx,int sy)
{
Create(sx,sy);
int i,j;
for(i=0;i<Rows;i++)
for(j=0;j<Cols;j++)
{
dat[i][j]=1.0f;
}
Sum=(float)Rows*Cols;
}
void ImageOperator::CalculateSum()
{
Sum=0.0f;
int i,j;
for(i=0;i<Rows;i++)
for(j=0;j<Cols;j++)
{
Sum+=dat[i][j];
}
}