Files
Work/mdiwin/MESHWRP.CPP
2024-08-07 09:16:27 -04:00

296 lines
9.9 KiB
C++

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