178 lines
6.4 KiB
C++
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;
|
|
}
|
|
|