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

178 lines
6.4 KiB
C++

#include <mdiwin/dissolve.hpp>
#include <mdiwin/bitmap.hpp>
#include <mdiwin/qsort.hpp>
WORD CrossDissolve::crossDissolve(Block<String> &srcImage,Block<String> &dstImage)
{
Block<Schedule> dissolveSchedule;
size_t srcSize((int)srcImage.size());
if(!srcSize)return FALSE;
Schedule::createSchedule(dissolveSchedule,srcSize);
for(int i=0;i<srcSize;i++)
crossImage(srcImage[i],dstImage[i],(LONG)(dissolveSchedule[i].srcWeight()*100),(LONG)(dissolveSchedule[i].dstWeight()*100));
return TRUE;
}
WORD CrossDissolve::crossDissolve(String &srcImage,String &dstImage,WORD nFrames)
{
Block<Schedule> dissolveSchedule;
if(!nFrames)return FALSE;
Schedule::createSchedule(dissolveSchedule,nFrames);
for(int i=0;i<nFrames;i++)
crossImage(srcImage,dstImage,(LONG)(dissolveSchedule[i].srcWeight()*100),(LONG)(dissolveSchedule[i].dstWeight()*100));
return TRUE;
}
WORD CrossDissolve::crossDissolve(Block<String> &sourceBlock,Block<String> &destBlock,Block<Schedule> &dissolveSchedule)
{
size_t size((int)sourceBlock.size());
if(!size)return FALSE;
if(size!=destBlock.size())return FALSE;
if(size!=dissolveSchedule.size())return FALSE;
for(int i=0;i<size;i++)crossImage(sourceBlock[i],destBlock[i],(LONG)(dissolveSchedule[i].srcWeight()*100),(LONG)(dissolveSchedule[i].dstWeight()*100));
return TRUE;
}
WORD CrossDissolve::crossImage(String &srcImageString,String &dstImageString,LONG srcWeight,LONG dstWeight)
{
Bitmap *lpSrcBitmap;
Bitmap *lpDstBitmap;
HGLOBAL hGlobalHistogram;
HGLOBAL hGlobalSrcImageData;
HGLOBAL hGlobalDstImageData;
HGLOBAL hGlobalSrcBitmapInfo;
HGLOBAL hGlobalDstBitmapInfo;
HPALETTE hPalette;
UHUGE *lpSrcImageData;
UHUGE *lpDstImageData;
LHUGE *lpHistogram;
BITMAPINFO FAR *lpSrcBitmapInfo;
BITMAPINFO FAR *lpDstBitmapInfo;
WORD returnCode(FALSE);
LONG sizeImage;
RGBQUAD *srcRGB;
RGBQUAD *dstRGB;
RGBLONG outRGB;
lpSrcBitmap=new Bitmap(srcImageString);
lpDstBitmap=new Bitmap(dstImageString);
if(!lpSrcBitmap->isOkay()||!lpDstBitmap->isOkay())
{
delete lpSrcBitmap;
delete lpDstBitmap;
return returnCode;
}
hGlobalSrcImageData=lpSrcBitmap->lockedImageData();
hGlobalDstImageData=lpDstBitmap->lockedImageData();
hGlobalSrcBitmapInfo=lpSrcBitmap->lockedBitmapInfo();
hGlobalDstBitmapInfo=lpDstBitmap->lockedBitmapInfo();
lpSrcImageData=(UHUGE*)::GlobalLock(hGlobalSrcImageData);
lpDstImageData=(UHUGE*)::GlobalLock(hGlobalDstImageData);
lpSrcBitmapInfo=(BITMAPINFO FAR *)::GlobalLock(hGlobalSrcBitmapInfo);
lpDstBitmapInfo=(BITMAPINFO FAR *)::GlobalLock(hGlobalDstBitmapInfo);
if(lpSrcBitmapInfo->bmiHeader.biWidth==lpDstBitmapInfo->bmiHeader.biWidth&&
lpSrcBitmapInfo->bmiHeader.biHeight==lpDstBitmapInfo->bmiHeader.biHeight&&
((8==lpSrcBitmapInfo->bmiHeader.biBitCount)&&(8==lpDstBitmapInfo->bmiHeader.biBitCount)))
{
sizeImage=(LONG)lpSrcBitmapInfo->bmiHeader.biWidth*(LONG)lpSrcBitmapInfo->bmiHeader.biHeight;
hGlobalHistogram=::GlobalAlloc(GMEM_FIXED,sizeImage*(LONG)sizeof(LONG));
lpHistogram=(LHUGE*)::GlobalLock(hGlobalHistogram);
for(LONG imageOffset=0;imageOffset<sizeImage;imageOffset++)
{
srcRGB=&lpSrcBitmapInfo->bmiColors[*(lpSrcImageData+imageOffset)];
dstRGB=&lpDstBitmapInfo->bmiColors[*(lpDstImageData+imageOffset)];
outRGB.rgbRed=srcRGB->rgbRed*srcWeight+dstRGB->rgbRed*dstWeight;
outRGB.rgbGreen=srcRGB->rgbGreen*srcWeight+dstRGB->rgbGreen*dstWeight;
outRGB.rgbBlue=srcRGB->rgbBlue*srcWeight+dstRGB->rgbBlue*dstWeight;
*(lpHistogram+imageOffset)=RGB((BYTE)(outRGB.rgbRed/100L),(BYTE)(outRGB.rgbGreen/100L),(BYTE)(outRGB.rgbBlue/100L));
}
delete lpDstBitmap;
hPalette=createBlendedPalette(lpHistogram,sizeImage);
for(imageOffset=0;imageOffset<sizeImage;imageOffset++)
*(lpSrcImageData+imageOffset)=::GetNearestPaletteIndex(hPalette,*(lpHistogram+imageOffset));
::GlobalUnlock(hGlobalHistogram);
::GlobalFree(hGlobalHistogram);
}
::unlink(srcImageString);
Bitmap outputImage(srcImageString,hGlobalSrcImageData,hGlobalSrcBitmapInfo);
outputImage.setPalette(hPalette);
if(outputImage.isOkay())outputImage.saveBitmap();
delete lpSrcBitmap;
::DeleteObject(hPalette);
return returnCode;
}
HPALETTE CrossDissolve::createBlendedPalette(LHUGE *lpImageData,LONG sizeImage)
{
QuickSort<BIT32> sortedBIT32;
QuickSort<ColorCount> sortedColorCount;
Block<ColorCount> blockedColors;
Vector<BIT32> vectoredColors;
Vector<ColorCount> vectoredColorCount;
vectoredColors.size(sizeImage);
for(LONG i=0;i<sizeImage;i++)vectoredColors[i]=*(lpImageData+i);
sortedBIT32.sortItems((BIT32*)&vectoredColors[0],sizeImage-1);
condenseBlock(vectoredColors,blockedColors);
vectoredColors.size(0);
vectoredColorCount=blockedColors;
sortedColorCount.sortItems((ColorCount*)&vectoredColorCount[0],vectoredColorCount.size()-1,SortOptions::Descending);
blockedColors=vectoredColorCount;
return createPalette(blockedColors);
}
void CrossDissolve::condenseBlock(Vector<BIT32> &vectoredColors,Block<ColorCount> &blockedColors)
{
BIT32 prevColor;
LONG equalColors;
LONG sizeImage(vectoredColors.size());
for(LONG i=0;i<sizeImage;i++)
{
if(!i){prevColor=vectoredColors[i];equalColors=1;}
else
{
if(!(prevColor==vectoredColors[i]))
{
blockedColors.insert(&ColorCount(vectoredColors[i].value(),equalColors));
prevColor=vectoredColors[i];
equalColors=1;
}
else equalColors++;
}
}
blockedColors.insert(&ColorCount(vectoredColors[i-1].value(),equalColors));
}
HPALETTE CrossDissolve::createPalette(Block<ColorCount> &blockedColors)
{
PALETTEENTRY FAR *lpPaletteEntry;
LOGPALETTE FAR *lpLogPalette;
HGLOBAL hGlobalPalette;
HPALETTE hPalette;
size_t paletteSize((int)blockedColors.size());
while((paletteSize=(int)blockedColors.size())<Bitmap::MaxColors)blockedColors.insert(&ColorCount(0,0));
paletteSize=Bitmap::MaxColors;
hGlobalPalette=::GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE,sizeof(LOGPALETTE)+(paletteSize*sizeof(PALETTEENTRY)));
lpLogPalette=(LOGPALETTE FAR *)::GlobalLock(hGlobalPalette);
lpLogPalette->palNumEntries=paletteSize;
lpLogPalette->palVersion=0x300;
for(int i=0;i<paletteSize;i++)
{
lpPaletteEntry=(PALETTEENTRY FAR *)&lpLogPalette->palPalEntry[i];
lpPaletteEntry->peRed=GetRValue(blockedColors[i].color());
lpPaletteEntry->peGreen=GetGValue(blockedColors[i].color());
lpPaletteEntry->peBlue=GetBValue(blockedColors[i].color());
lpPaletteEntry->peFlags=0;
}
hPalette=::CreatePalette((LOGPALETTE FAR *)lpLogPalette);
::GlobalUnlock(hGlobalPalette);
::GlobalFree(hGlobalPalette);
return hPalette;
}