296 lines
9.9 KiB
Plaintext
296 lines
9.9 KiB
Plaintext
#include <stdio.h>
|
|
#include <mdiwin/types.hpp>
|
|
#include <mdiwin/main.hpp>
|
|
#include <mdiwin/point.hpp>
|
|
#include <mdiwin/meshwrp.hpp>
|
|
|
|
MeshWarp::MeshWarp(HPALETTE hPalette,UHUGE *hpImage,WORD width,WORD height)
|
|
: mhPalette(hPalette), mhpImage(hpImage), mWidth(width), mHeight(height),
|
|
mhGlobalIntermediate(0), mhpIntermediate(0), mhGlobalImage(0), mhpGlobalImage(0),
|
|
mhGlobalSource(0), mDstWidth(0), mDstHeight(0)
|
|
{
|
|
loadPaletteEntries();
|
|
}
|
|
|
|
MeshWarp::~MeshWarp()
|
|
{
|
|
}
|
|
|
|
HGLOBAL MeshWarp::performWarp(Vector<Point> &sourceMesh,Vector<Point> &destMesh,int meshColRows,int &newWidth,int &newHeight)
|
|
{
|
|
size_t size;
|
|
|
|
if((size=(int)sourceMesh.size())!=destMesh.size())return (HGLOBAL)0;
|
|
mSrcPairs.size(sourceMesh.size());
|
|
mDstPairs.size(destMesh.size());
|
|
for(int i=0;i<size;i++)
|
|
{
|
|
mSrcPairs[i].column(sourceMesh[i].xPoint());
|
|
mSrcPairs[i].row(sourceMesh[i].yPoint());
|
|
mDstPairs[i].column(destMesh[i].xPoint());
|
|
mDstPairs[i].row(destMesh[i].yPoint());
|
|
}
|
|
return performWarp(newWidth,newHeight,meshColRows);
|
|
}
|
|
|
|
HGLOBAL MeshWarp::performWarp(Vector<FloatPairs> &sourceMesh,Vector<FloatPairs> &destMesh,int meshColRows,int &newWidth,int &newHeight)
|
|
{
|
|
if(sourceMesh.size()!=destMesh.size())return (HGLOBAL)0;
|
|
mSrcPairs=sourceMesh;
|
|
mDstPairs=destMesh;
|
|
return performWarp(newWidth,newHeight,meshColRows);
|
|
}
|
|
|
|
HGLOBAL MeshWarp::performWarp(int &newWidth,int &newHeight,int meshColRows)
|
|
{
|
|
initializeSplineColumns(mVerticalSplineSrcData,meshColRows);
|
|
initializeSplineColumns(mVerticalSplineDstData,meshColRows);
|
|
initializeSplineColumns(mHorizontalSplineSrcData,meshColRows);
|
|
initializeSplineColumns(mHorizontalSplineDstData,meshColRows);
|
|
assert(0!=(mhGlobalSource=Main::upsideDown(mWidth,mHeight,mhpImage)));
|
|
mhpImage=(UHUGE *)::GlobalLock(mhGlobalSource);
|
|
firstPassPhaseOne(meshColRows);
|
|
firstPassPhaseTwo();
|
|
secondPassPhaseOne(meshColRows);
|
|
secondPassPhaseTwo();
|
|
newWidth=(mVerticalSplineSrcData[mVerticalSplineSrcData.size()-1])[mVerticalSplineSrcData[0].size()-1].column();
|
|
newHeight=(mVerticalSplineSrcData[0])[mVerticalSplineSrcData[0].size()-1].row();
|
|
return mhGlobalImage;
|
|
}
|
|
|
|
void MeshWarp::firstPassPhaseOne(int columnData)
|
|
{
|
|
Vector<FloatPairs> resampleSrcPairs;
|
|
Vector<FloatPairs> resampleDstPairs;
|
|
Vector<FloatPairs> tempSrcPairs;
|
|
Vector<FloatPairs> tempDstPairs;
|
|
CatmullRom catmullRom;
|
|
size_t resampleSize;
|
|
|
|
for(int i=0;i<columnData;i++)
|
|
{
|
|
resampleSize=(int)resampleDstPairs.size(resampleSrcPairs.size(mDstPairs[((i*columnData)+columnData)-1].row()));
|
|
for(int j=0;j<resampleSize;j++)
|
|
{
|
|
resampleDstPairs[j].column(j);
|
|
resampleSrcPairs[j].column(j);
|
|
}
|
|
tempDstPairs.size(columnData);
|
|
tempSrcPairs.size(columnData);
|
|
for(j=0;j<columnData;j++)
|
|
{
|
|
tempDstPairs[j].column(mDstPairs[(i*columnData)+j].row());
|
|
tempDstPairs[j].row(mDstPairs[(i*columnData)+j].column());
|
|
tempSrcPairs[j].column(mSrcPairs[(i*columnData)+j].row());
|
|
tempSrcPairs[j].row(mSrcPairs[(i*columnData)+j].column());
|
|
}
|
|
catmullRom.performSpline(tempDstPairs,resampleDstPairs);
|
|
catmullRom.performSpline(tempSrcPairs,resampleSrcPairs);
|
|
tempDstPairs.size(tempSrcPairs.size(resampleSize));
|
|
for(j=0;j<resampleSize;j++)
|
|
{
|
|
tempDstPairs[j].column(resampleDstPairs[j].row());
|
|
tempDstPairs[j].row(resampleDstPairs[j].column());
|
|
tempSrcPairs[j].column(resampleSrcPairs[j].row());
|
|
tempSrcPairs[j].row(resampleSrcPairs[j].column());
|
|
}
|
|
mVerticalSplineDstData[i]=tempDstPairs;
|
|
mVerticalSplineSrcData[i]=tempSrcPairs;
|
|
}
|
|
}
|
|
|
|
void MeshWarp::firstPassPhaseTwo(void)
|
|
{
|
|
Vector<FloatPairs> resamplePairs;
|
|
Vector<FloatPairs> tempPairs;
|
|
size_t meshRows((int)mVerticalSplineSrcData[0].size());
|
|
size_t meshCols((int)mVerticalSplineSrcData.size());
|
|
UHUGE *hpSrcScanline(0);
|
|
UHUGE *hpDstScanline(0);
|
|
CatmullRom catmullRom;
|
|
|
|
mDstWidth=(mVerticalSplineSrcData[meshCols-1])[meshRows-1].column();
|
|
mDstHeight=(mVerticalSplineSrcData[0])[meshRows-1].row();
|
|
assert(0!=(mhGlobalIntermediate=::GlobalAlloc(GMEM_FIXED,(LONG)mDstWidth*(LONG)mDstHeight)));
|
|
mhpIntermediate=(UHUGE*)::GlobalLock(mhGlobalIntermediate);
|
|
resamplePairs.size(mDstWidth);
|
|
tempPairs.size(meshCols);
|
|
for(int j=0;j<mDstWidth;j++)resamplePairs[j].column(j);
|
|
for(int i=0;i<mDstHeight;i++)
|
|
{
|
|
for(int x=0;x<meshCols;x++)
|
|
{
|
|
tempPairs[x].column((mVerticalSplineSrcData[x])[i].column());
|
|
tempPairs[x].row((mVerticalSplineDstData[x])[i].column());
|
|
}
|
|
catmullRom.performSpline(tempPairs,resamplePairs);
|
|
hpSrcScanline=(mhpImage+((long)mWidth*(long)i));
|
|
hpDstScanline=(mhpIntermediate+((long)mDstWidth*(long)i));
|
|
resampleGenerate(resamplePairs,hpSrcScanline,hpDstScanline,mDstWidth);
|
|
}
|
|
::GlobalUnlock(mhGlobalSource);
|
|
::GlobalFree(mhGlobalSource);
|
|
}
|
|
|
|
void MeshWarp::secondPassPhaseOne(int columnData)
|
|
{
|
|
Vector<FloatPairs> resampleSrcPairs;
|
|
Vector<FloatPairs> resampleDstPairs;
|
|
Vector<FloatPairs> tempSrcPairs;
|
|
Vector<FloatPairs> tempDstPairs;
|
|
size_t resampleSize(mDstPairs[mDstPairs.size()-1].column());
|
|
CatmullRom catmullRom;
|
|
|
|
resampleDstPairs.size(resampleSrcPairs.size(resampleSize));
|
|
for(int j=0;j<resampleSize;j++)
|
|
{
|
|
resampleDstPairs[j].column(j);
|
|
resampleSrcPairs[j].column(j);
|
|
}
|
|
tempDstPairs.size(tempSrcPairs.size(columnData));
|
|
for(int i=0;i<columnData;i++)
|
|
{
|
|
for(j=0;j<columnData;j++)
|
|
{
|
|
tempDstPairs[j].column(mDstPairs[(j*columnData)+i].column());
|
|
tempDstPairs[j].row(mDstPairs[(j*columnData)+i].row());
|
|
tempSrcPairs[j].column(mSrcPairs[(j*columnData)+i].column());
|
|
tempSrcPairs[j].row(mSrcPairs[(j*columnData)+i].row());
|
|
}
|
|
catmullRom.performSpline(tempSrcPairs,resampleSrcPairs);
|
|
catmullRom.performSpline(tempDstPairs,resampleDstPairs);
|
|
mHorizontalSplineSrcData[i]=resampleSrcPairs;
|
|
mHorizontalSplineDstData[i]=resampleDstPairs;
|
|
}
|
|
}
|
|
|
|
void MeshWarp::secondPassPhaseTwo(void)
|
|
{
|
|
size_t meshRows((int)mHorizontalSplineSrcData.size());
|
|
Vector<FloatPairs> tempPairs;
|
|
Vector<FloatPairs> resamplePairs;
|
|
HGLOBAL hGlobalTempOutput;
|
|
HGLOBAL hGlobalTempIntermediate;
|
|
HGLOBAL hGlobalOutput;
|
|
UHUGE *hpOutputImage;
|
|
UHUGE *hpSrcScanline;
|
|
UHUGE *hpDstScanline;
|
|
CatmullRom catmullRom;
|
|
|
|
assert(0!=(hGlobalOutput=::GlobalAlloc(GMEM_FIXED,(LONG)mDstWidth*(LONG)mDstHeight)));
|
|
hpOutputImage=(UHUGE*)::GlobalLock(hGlobalOutput);
|
|
hGlobalTempOutput=Main::rotateLeft(hpOutputImage,mDstWidth,mDstHeight);
|
|
::GlobalUnlock(hGlobalOutput);
|
|
::GlobalFree(hGlobalOutput);
|
|
hGlobalOutput=hGlobalTempOutput;
|
|
hpOutputImage=(UHUGE*)::GlobalLock(hGlobalOutput);
|
|
hGlobalTempIntermediate=Main::rotateLeft(mhpIntermediate,mDstWidth,mDstHeight);
|
|
::GlobalUnlock(mhGlobalIntermediate);
|
|
::GlobalFree(mhGlobalIntermediate);
|
|
mhGlobalIntermediate=hGlobalTempIntermediate;
|
|
mhpIntermediate=(UHUGE*)::GlobalLock(mhGlobalIntermediate);
|
|
resamplePairs.size(mDstHeight);
|
|
tempPairs.size(meshRows);
|
|
for(int i=0;i<mDstHeight;i++)resamplePairs[i].column(i);
|
|
for(i=0;i<mDstWidth;i++)
|
|
{
|
|
for(int j=0;j<meshRows;j++)
|
|
{
|
|
tempPairs[j].column((mHorizontalSplineSrcData[j])[i].row());
|
|
tempPairs[j].row((mHorizontalSplineDstData[j])[i].row());
|
|
}
|
|
catmullRom.performSpline(tempPairs,resamplePairs);
|
|
hpSrcScanline=(mhpIntermediate+((LONG)(mDstWidth-i-1)*(LONG)mDstHeight));
|
|
hpDstScanline=(hpOutputImage+((LONG)(mDstWidth-i-1)*(LONG)mDstHeight));
|
|
resampleGenerate(resamplePairs,hpSrcScanline,hpDstScanline,mDstHeight);
|
|
}
|
|
::GlobalUnlock(mhGlobalIntermediate);
|
|
::GlobalFree(mhGlobalIntermediate);
|
|
hGlobalTempOutput=Main::rotateRight(hpOutputImage,mDstHeight,mDstWidth);
|
|
::GlobalUnlock(hGlobalOutput);
|
|
::GlobalFree(hGlobalOutput);
|
|
hpOutputImage=(UHUGE*)::GlobalLock(hGlobalTempOutput);
|
|
mhGlobalImage=Main::upsideDown(mDstWidth,mDstHeight,hpOutputImage);
|
|
::GlobalUnlock(hGlobalTempOutput);
|
|
::GlobalFree(hGlobalTempOutput);
|
|
}
|
|
|
|
void MeshWarp::resampleGenerate(Vector<FloatPairs> &mappingPoints,UHUGE *lpSrcScanline,UHUGE *lpDstScanline,int outLen)
|
|
{
|
|
int u,x;
|
|
float redAccumulator(0);
|
|
float greenAccumulator(0);
|
|
float blueAccumulator(0);
|
|
float redIntensity;
|
|
float greenIntensity;
|
|
float blueIntensity;
|
|
float inverseFactor;
|
|
float inSegment;
|
|
float outSegment;
|
|
float inputPos[MaxLineWidth+1];
|
|
|
|
// precompute input index for each output pixel
|
|
::memset(inputPos,0,sizeof(inputPos));
|
|
for(u=x=0;x<outLen;x++)
|
|
{
|
|
while(u+1<outLen&&mappingPoints[u+1].row()<x)u++;
|
|
if(u+1>=outLen)u--;
|
|
inputPos[x]=u+(double)(x-mappingPoints[u].row())/
|
|
(mappingPoints[u+1].row()-mappingPoints[u].row());
|
|
}
|
|
inSegment=1.0;
|
|
outSegment=inputPos[1];
|
|
inverseFactor=outSegment;
|
|
for(x=u=0;x<outLen;)
|
|
{
|
|
redIntensity=inSegment*mPaletteData[*(lpSrcScanline+u)].peRed+
|
|
(1-inSegment)*mPaletteData[*(lpSrcScanline+(u+1))].peRed;
|
|
greenIntensity=inSegment*mPaletteData[*(lpSrcScanline+u)].peGreen+
|
|
(1-inSegment)*mPaletteData[*(lpSrcScanline+(u+1))].peGreen;
|
|
blueIntensity=inSegment*mPaletteData[*(lpSrcScanline+u)].peBlue+
|
|
(1-inSegment)*mPaletteData[*(lpSrcScanline+(u+1))].peBlue;
|
|
if(inSegment<outSegment)
|
|
{
|
|
redAccumulator+=(redIntensity*inSegment);
|
|
greenAccumulator+=(greenIntensity*inSegment);
|
|
blueAccumulator+=(blueIntensity*inSegment);
|
|
outSegment-=inSegment;
|
|
inSegment=1.0;
|
|
u++;
|
|
}
|
|
else
|
|
{
|
|
redAccumulator+=(redIntensity*outSegment);
|
|
greenAccumulator+=(greenIntensity*outSegment);
|
|
blueAccumulator+=(blueIntensity*outSegment);
|
|
*(lpDstScanline+x)=::GetNearestPaletteIndex(mhPalette,RGB(
|
|
(BYTE)(redAccumulator/inverseFactor),
|
|
(BYTE)(greenAccumulator/inverseFactor),
|
|
(BYTE)(blueAccumulator/inverseFactor)));
|
|
redAccumulator=greenAccumulator=blueAccumulator=0;
|
|
inSegment-=outSegment;
|
|
x++;
|
|
inverseFactor=inputPos[x+1]-inputPos[x];
|
|
outSegment=inverseFactor;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MeshWarp::initializeSplineColumns(Vector<VectoredPairs> &splineData,int columnData)
|
|
{
|
|
splineData.size(columnData);
|
|
}
|
|
|
|
void MeshWarp::dumpMesh(Vector<FloatPairs> &sourceMesh,Vector<FloatPairs> &destMesh,String &fileName)
|
|
{
|
|
FILE *fp;
|
|
size_t size;
|
|
|
|
size=(int)sourceMesh.size();
|
|
fp=::fopen(fileName,"wb");
|
|
for(int i=0;i<size;i++)
|
|
::fprintf(fp,"Source:[%3d]x:%6.2lf; y:%6.2lf Dest:x:%6.2lf; y:%6.2lf;\r\n",
|
|
i,sourceMesh[i].column(),sourceMesh[i].row(),destMesh[i].column(),destMesh[i].row());
|
|
::fclose(fp);
|
|
}
|