Files
core/ASCImageStudio3/Common/ImagePaintEffects.h

3111 lines
99 KiB
C++

#pragma once
#include <ImageCaching.h>
namespace ImageStudio
{
namespace Paint
{
namespace Effects
{
namespace Constants
{
const int c_nArtefactsCount = 8;
const int c_arArtefactsWidth[8] = { 4, 14, 13, 11, 17, 12, 6, 15};
const int c_arArtefactsHeight[8] = {20, 19, 16, 17, 15, 14, 10, 16};
// çàãîòîâêà äëÿ àðòåôàêòà
//const BYTE c_arArtefact[20][20] = {
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
//};
const BYTE c_arArtefact1[20][4] = {
0, 1, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 0, 1,
0, 0, 0, 1,
0, 0, 1, 1,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 0, 1, 0,
0, 1, 1, 0,
0, 1, 0, 0,
0, 1, 0, 1,
0, 0, 1, 1
};
const BYTE c_arArtefact2[19][14] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
};
const BYTE c_arArtefact3[16][13] = {
0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
};
const BYTE c_arArtefact4[17][11] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
};
const BYTE c_arArtefact5[15][17] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
};
const BYTE c_arArtefact6[14][12] = {
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,
0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
const BYTE c_arArtefact7[10][6] = {
0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 0, 0,
};
const BYTE c_arArtefact8[16][15] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
};
}
class Cinema : public ImageStudio::Caching::CCacheItemPointer
{
protected:
enum EArtefactCounts
{
c_nCountFibers = 14,
c_nCountSpots = 5,
c_nCountDirts = 1
};
DWORD m_dwStartRnd;
double m_dGrayFactor;
double m_dNoiseFactor;
Gdiplus::Rect m_arrFibers[c_nCountFibers];
Gdiplus::Rect m_arrSpots[c_nCountSpots];
Gdiplus::Rect m_arrDirts[c_nCountDirts];
(Gdiplus::Bitmap*) m_arpArtefactImage[Constants::c_nArtefactsCount];
int m_nShiftBaseRnd;
//double m_dShiftPeriod;
double m_dShiftOffsetX;
double m_dShiftOffsetY;
double m_dShiftFactorX;
double m_dShiftFactorY;
double m_dLastShiftX; // ýòè äâå ïåðåìåííûå íóæíû äëÿ òîãî ÷òîáû íå áûëî
double m_dLastShiftY; // ýôôåêòà ðåçêîãî äåðãàíüÿ, ÷òîáû îíî áûëî ïëàâíûì
int m_nMaxArtefactsShow;
int m_nMinArtefactsShow;
int m_nMinLinesShow;
int m_nMaxLinesShow;
int m_arLinesX[50];
int m_arLinesCurLife[50];
int m_nLinesCurCount;
int m_nMaxFramesLineShow;
public:
//Cinema( CString sFileWithArtefacts )
//{
// LARGE_INTEGER liTime;
//
// if( ::QueryPerformanceCounter( &liTime ))
// m_dwStartRnd = liTime.LowPart;
// else
// m_dwStartRnd = DWORD(::rand());
// //m_dwStartRnd *= 317539;
// m_dGrayFactor = 0.1;
// m_dNoiseFactor = 0.2;
// m_pArtefactsImage = NULL;
// // çàãðóçêà àðòåôàêòîâ
// _bstr_t bsFile = sFileWithArtefacts.AllocSysString();
// Gdiplus::Bitmap oSrcImage( bsFile );
// SysFreeString( bsFile );
// if( Gdiplus::Ok == oSrcImage.GetLastStatus() )
// {
// int nWidth = oSrcImage.GetWidth();
// int nHeight = oSrcImage.GetHeight();
// if( nWidth >= 256 && nHeight >= 320 )
// {
// m_pArtefactsImage = oSrcImage.Clone( 0, 0, nWidth, nHeight, PixelFormat32bppARGB );
// if( m_pArtefactsImage )
// {
// m_arrFibers[0] = Gdiplus::Rect( 66, 2, 60, 60 );
// m_arrFibers[1] = Gdiplus::Rect( 130, 2, 60, 60 );
// m_arrFibers[2] = Gdiplus::Rect( 2, 66, 60, 60 );
// m_arrFibers[3] = Gdiplus::Rect( 66, 66, 60, 60 );
// m_arrFibers[4] = Gdiplus::Rect( 130, 66, 60, 60 );
// m_arrFibers[5] = Gdiplus::Rect( 194, 66, 60, 60 );
// m_arrFibers[6] = Gdiplus::Rect( 2, 130, 60, 60 );
// m_arrFibers[7] = Gdiplus::Rect( 66, 130, 60, 60 );
// m_arrFibers[8] = Gdiplus::Rect( 130, 130, 60, 60 );
// m_arrFibers[9] = Gdiplus::Rect( 194, 130, 60, 60 );
// m_arrFibers[10] = Gdiplus::Rect( 2, 194, 60, 60 );
// m_arrFibers[11] = Gdiplus::Rect( 66, 194, 60, 60 );
// m_arrFibers[12] = Gdiplus::Rect( 130, 194, 60, 60 );
// m_arrFibers[13] = Gdiplus::Rect( 194, 194, 60, 60 );
// m_arrSpots[0] = Gdiplus::Rect( 2, 2, 60, 60 );
// m_arrSpots[1] = Gdiplus::Rect( 194, 2, 60, 60 );
// m_arrSpots[2] = Gdiplus::Rect( 2, 258, 60, 60 );
// m_arrSpots[3] = Gdiplus::Rect( 130, 258, 60, 60 );
// m_arrSpots[4] = Gdiplus::Rect( 194, 258, 60, 60 );
// m_arrDirts[0] = Gdiplus::Rect( 66, 258, 60, 60 );
//
// // äåëàåì íóæíóþ àëüôó â êàðòèíêå
// Gdiplus::BitmapData oImageData;
// m_pArtefactsImage->LockBits( NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat32bppARGB, &oImageData );
// if( oImageData.Scan0 )
// {
// BYTE* pRow = LPBYTE(oImageData.Scan0);
// for( int nRow = 0; nRow < nHeight; ++nRow, pRow += oImageData.Stride )
// {
// BYTE* pPixel = pRow;
// for( int nPos = 0; nPos < nWidth; ++nPos, pPixel += 4 )
// {
// pPixel[3] = pPixel[0];
// }
// }
//
// m_pArtefactsImage->UnlockBits( &oImageData );
// }
// }
// }
// }
//}
Cinema( )
{
LARGE_INTEGER liTime;
if( ::QueryPerformanceCounter( &liTime ))
m_dwStartRnd = liTime.LowPart;
else
m_dwStartRnd = DWORD(::rand());
//m_dwStartRnd *= 317539;
m_dGrayFactor = 0.1;
m_dNoiseFactor = 0.2;
m_nLinesCurCount = 0;
// çàãðóçêà àðòåôàêòîâ
for (int nCurArt = 0; nCurArt < Constants::c_nArtefactsCount; nCurArt++)
{
Gdiplus::Bitmap* pCurImage;
const int nHeight = Constants::c_arArtefactsHeight[nCurArt];
const int nWidth = Constants::c_arArtefactsWidth[nCurArt];
BYTE* pResult = new BYTE[(nWidth + 4) * (nHeight + 4)];
BYTE* pBuffer = new BYTE[(nWidth + 8) * (nHeight + 8)];
ZeroMemory(pBuffer, (nWidth + 8) * (nHeight + 8));
BYTE *pArtefact = new BYTE[nHeight * nWidth];
switch (nCurArt)
{
case 0:
{
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
pArtefact[nXIndex + nYIndex * nWidth] = Constants::c_arArtefact1[nYIndex][nXIndex];
break;
}
case 1:
{
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
pArtefact[nXIndex + nYIndex * nWidth] = Constants::c_arArtefact2[nYIndex][nXIndex];
break;
}
case 2:
{
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
pArtefact[nXIndex + nYIndex * nWidth] = Constants::c_arArtefact3[nYIndex][nXIndex];
break;
}
case 3:
{
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
pArtefact[nXIndex + nYIndex * nWidth] = Constants::c_arArtefact4[nYIndex][nXIndex];
break;
}
case 4:
{
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
pArtefact[nXIndex + nYIndex * nWidth] = Constants::c_arArtefact5[nYIndex][nXIndex];
break;
}
case 5:
{
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
pArtefact[nXIndex + nYIndex * nWidth] = Constants::c_arArtefact6[nYIndex][nXIndex];
break;
}
case 6:
{
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
pArtefact[nXIndex + nYIndex * nWidth] = Constants::c_arArtefact7[nYIndex][nXIndex];
break;
}
case 7:
{
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
pArtefact[nXIndex + nYIndex * nWidth] = Constants::c_arArtefact8[nYIndex][nXIndex];
break;
}
};
int nIndex = (4 * (nWidth + 8) + 4);
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++, nIndex += 8 )
for (int nXIndex = 0; nXIndex < nWidth; nXIndex++, nIndex ++ )
pBuffer[nIndex] = 255 * pArtefact[nXIndex + nYIndex * nWidth];
IppiSize roiSize = {nWidth + 4, nHeight + 4};
ippiFilterGauss_8u_C1R( pBuffer + (2 + 2 * (nWidth + 8)), nWidth + 8, pResult, nWidth + 4, roiSize, ippMskSize5x5 );
pCurImage = new Gdiplus::Bitmap(nWidth + 4, nHeight + 4, PixelFormat32bppARGB);
// êîïèðóåì äàííûå â êàðòèíêó
Gdiplus::BitmapData oImageData;
pCurImage->LockBits( NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat32bppARGB, &oImageData );
if( oImageData.Scan0 )
{
int nIndex = (nHeight + 4 - 1) * (nWidth + 4);
BYTE* pRow = LPBYTE(oImageData.Scan0);
for( int nRow = 0; nRow < nHeight + 4; ++nRow, pRow += oImageData.Stride, nIndex -= 2 * (nWidth + 4))
{
BYTE* pPixel = pRow;
for( int nPos = 0; nPos < nWidth + 4; ++nPos, pPixel += 4, nIndex ++ )
{
pPixel[0] = (pResult[nIndex] > 0? 255 : 0);
pPixel[1] = (pResult[nIndex] > 0? 255 : 0);
pPixel[2] = (pResult[nIndex] > 0? 255 : 0);
if ( nRow >= 2 && nRow < nHeight + 2 && nPos >= 2 && nPos < nWidth + 2 && 1 == pArtefact[nWidth * (nHeight - (nRow - 2) - 1) + nPos - 2] )
pPixel[3] = 255;
else
pPixel[3] = pResult[nIndex];
}
}
pCurImage->UnlockBits( &oImageData );
}
delete []pBuffer;
delete []pResult;
m_arpArtefactImage[nCurArt] = pCurImage;
}
}
virtual ~Cinema()
{
for ( int nIndex = 0 ; nIndex < Constants::c_nArtefactsCount; nIndex++ )
if ( m_arpArtefactImage[nIndex] )
delete m_arpArtefactImage[nIndex];
}
void Create( ImageStudio::Serialize::Effects::EffectCinema& pEffect )
{
::srand(GetTickCount());
m_nShiftBaseRnd = ::rand();
// m_dShiftPeriod = max( 0, pEffect.m_dShiftTimePeriod );
m_dShiftOffsetX = max( 0, min(10, pEffect.m_dShiftMaxOffsetX));
m_dShiftOffsetY = max( 0, min(10, pEffect.m_dShiftMaxOffsetY));
m_dShiftFactorX = max( 0, min(10, pEffect.m_dShiftFactorOffsetX));
m_dShiftFactorY = max( 0, min(10, pEffect.m_dShiftFactorOffsetY));
m_dLastShiftX = 1.0;
m_dLastShiftY = 1.0;
m_nMaxArtefactsShow = max(0 , min( 49, pEffect.m_nMaxShowArtifacts));
m_nMinArtefactsShow = max(0 , min( 49, pEffect.m_nMinShowArtifacts));
m_nMinLinesShow = max(0 , min( 49, pEffect.m_nMinShowLines));
m_nMaxLinesShow = max(0 , min( 49, pEffect.m_nMaxShowLines));
m_nMaxFramesLineShow = max(1, min(100, pEffect.m_nNumFramesForShowLines));
}
BOOL Draw( BYTE* pBGRA, int nWidth, int nHeight, int nStride, double dTime, double dCompleteness )
{
CBuffer<BYTE> oBuffer(nWidth*nHeight*4);
if( oBuffer.IsEmpty() )
return FALSE;
BYTE* pBuffer = oBuffer.GetPtr();
// "òðÿñ¸ì" èçîáðàæåíèå
//TransformImage( pBGRA, pBuffer, nWidth, nHeight, dTime, dCompleteness );
// ñîçäà¸ì ðåíäåð äëÿ îòðèñîâêè àðòåôàêòîâ
if( true )
{
Gdiplus::Bitmap oImage( nWidth, nHeight, nWidth*4, PixelFormat32bppARGB, pBuffer );
if( Gdiplus::Ok != oImage.GetLastStatus() )
return FALSE;
Gdiplus::Graphics oRender( &oImage );
if( Gdiplus::Ok != oRender.GetLastStatus() )
return FALSE;
oRender.SetInterpolationMode( InterpolationModeBilinear );
oRender.SetSmoothingMode( SmoothingModeAntiAlias );
TransformImage( pBGRA, oRender, nWidth, nHeight, dTime, dCompleteness );
AddSmallArtefacts( oRender, nWidth, nHeight, dCompleteness );
AddVerticalLines( oRender, nWidth, nHeight, dCompleteness );
}
// ïåðåâîäèì â ñåðûé öâåò
//ToGray( pBuffer, nWidth, nHeight, dCompleteness );
GrayscaleImage( pBuffer, nWidth, nHeight, dCompleteness, dTime );
// äîáàâëÿåì "ãðàíóëèðîâàíèå"
AddNoise( pBuffer, nWidth, nHeight, dCompleteness );
memcpy( pBGRA, pBuffer, nWidth*nHeight*4 );
return TRUE;
}
protected:
BOOL TransformImage( BYTE* pBGRASource, Gdiplus::Graphics& oRender, int nWidth, int nHeight, double dTime, double dCompleteness )
{
//if( m_dShiftPeriod < 0.001 )
//{
// memcpy( pBGRAResult, pBGRASource, nWidth * nHeight * 4 );
// return TRUE;
//}
Gdiplus::Bitmap oSourceImage( nWidth, nHeight, nWidth*4, PixelFormat32bppARGB, pBGRASource );
if( Gdiplus::Ok != oSourceImage.GetLastStatus() )
return FALSE;
double dOffsetX = dCompleteness * m_dShiftOffsetX * nWidth / 640.0;
double dOffsetY = dCompleteness * m_dShiftOffsetY * nHeight / 480.0;
double dShiftFactorX = m_dShiftFactorX * nWidth / 640.0;
double dShiftFactorY = m_dShiftFactorY * nHeight / 480.0;
float fX;
if ( 0 < m_dLastShiftX )
fX = float( -fabs( (rand() % 1000) / 1000.0 * dOffsetX ) );
else
{
double dCurX = (rand() % 1000) / 1000.0 * (2 * dShiftFactorX ) - dShiftFactorX; // îòêëîíåíèå îò ïðåäûäóùåãî ïîëîæåíèÿ íå áîëüøå ÷åì íà dShiftFactorX ïèêñåëÿ
fX = float ( m_dLastShiftX + dCurX );
fX = float( (fX > 0 ? 0 : fX) );
fX = float( (fX < -dOffsetX ? -dOffsetX : fX) );
}
float fY;
if ( 0 < m_dLastShiftY )
fY = float( -fabs( (rand() % 1000) / 1000.0 * dOffsetY ) );
else
{
double dCurY = (rand() % 1000) /1000.0 * (2 * dShiftFactorY) - dShiftFactorY; // îòêëîíåíèå îò ïðåäûäóùåãî ïîëîæåíèÿ íå áîëüøå ÷åì íà dShiftFactorY ïèêñåëÿ
fY = float ( m_dLastShiftY + dCurY );
fY = float( (fY > 0 ? 0 : fY) );
fY = float( (fY < -dOffsetY ? -dOffsetY : fY) );
}
float fHeight = float(nHeight + dOffsetY);
float fWidth = float(nWidth + dOffsetX);
oRender.DrawImage(&oSourceImage, fX, fY, fWidth, fHeight);
m_dLastShiftX = fX;
m_dLastShiftY = fY;
//if( m_dShiftPeriod < 0.001 )
//{
// memcpy( pBGRAResult, pBGRASource, nWidth * nHeight * 4 );
// return TRUE;
//}
//CBuffer<Ipp32f> oMapX(nWidth*nHeight);
//CBuffer<Ipp32f> oMapY(nWidth*nHeight);
//if( oMapX.IsEmpty() || oMapY.IsEmpty() )
//{
// memcpy( pBGRAResult, pBGRASource, nWidth * nHeight * 4 );
// return TRUE /*FALSE*/;
//}
//CRandom oRnd( DWORD(int(dTime / m_dShiftPeriod) + m_nShiftBaseRnd) );
//double dOffsetX = dCompleteness * m_dShiftOffsetX;
//double dOffsetY = dCompleteness * m_dShiftOffsetY;
//double dSinX = oRnd.RandF();
//double dSinY = oRnd.RandF();
//double dX = dOffsetX * (1 + (2 * dSinX - 1) * dSinX);
//double dY = dOffsetY * (1 + (2 * dSinY - 1) * dSinY);
//double dScaleX = (nWidth - dOffsetX*2) / nWidth;
//double dScaleY = (nHeight - dOffsetY*2) / nHeight;
//Ipp32f* pxMap = oMapX.GetPtr();
//Ipp32f* pyMap = oMapY.GetPtr();
//for( int nRow = 0; nRow < nHeight; ++nRow )
//{
// for( int nPos = 0; nPos < nWidth; ++nPos, ++pxMap, ++pyMap )
// {
// *pxMap = float(dX + nPos * dScaleX);
// *pyMap = float(dY + nRow * dScaleY);
// }
//}
//IppiSize SrcSize = {nWidth, nHeight};
//IppiRect SrcRect = {0, 0, nWidth, nHeight};
//ippiRemap_8u_C4R(
// pBGRASource, SrcSize, nWidth*4, SrcRect,
// oMapX.GetPtr(), nWidth * sizeof(Ipp32f),
// oMapY.GetPtr(), nWidth * sizeof(Ipp32f),
// pBGRAResult, nWidth*4, SrcSize, IPPI_INTER_LINEAR);
return TRUE;
}
BOOL GrayscaleImage( BYTE* pBGRASource, int nWidth, int nHeight, double dCompleteness, double dTime )
{
IppiSize ImageSize = {nWidth, nHeight};
Ipp8u* pIntensity = new Ipp8u[nWidth*nHeight];
Ipp8u* pBuffer = new Ipp8u[nWidth*nHeight*4];
Ipp32f coeffs[3];
Ipp8u* pSrc[4];
if (pBuffer && pIntensity)
{
coeffs[0] = 0.11f;
coeffs[1] = 0.59f;
coeffs[2] = 0.3f;
ippiColorToGray_8u_AC4C1R( pBGRASource , 4*nWidth, pIntensity, nWidth, ImageSize, coeffs);
// noise
if( true )
{
unsigned int nSeed = GetTickCount();
Ipp16s* psChanel = new Ipp16s[nWidth*nHeight];
ippiConvert_8u16s_C1R(pIntensity, nWidth, psChanel, sizeof(Ipp16s)*nWidth, ImageSize);
ippiAddRandUniform_Direct_16s_C1IR(psChanel, sizeof(Ipp16s)*nWidth, ImageSize, 0, Ipp16s(4 * dCompleteness), &nSeed);
ippiConvert_16s8u_C1R(psChanel, sizeof(Ipp16s)*nWidth, pIntensity, nWidth, ImageSize);
delete [] psChanel;
}
// ìåëêèå àðòåôàêòû
int count = rand() % 7 - 2;
for( int i = 0; i < count; i++)
{
int rnd = rand() % 6;
int size = 1 + rnd*rnd/4;
int x = rand() % (nWidth - size);
int y = rand() % (nHeight - size);
IppiSize CellSize = {size, size};
BYTE c = 0;
if( rand() % 2 )
{
ippiMin_8u_C1R( pIntensity + y * nWidth + x, nWidth, CellSize, &c);
c += 20;
}
else
{
ippiMax_8u_C1R( pIntensity + y * nWidth + x, nWidth, CellSize, &c);
c -= 20;
}
for( int j = size*size/2; j > 0; --j )
{
int xx = rand() % size;
int yy = rand() % size;
pIntensity[(y + yy)*nWidth + (x + xx)] = c;
}
}
// êðóïíûå àðòåôàêòû
// ñâåç¸ííàÿ ïîëîñà
if( !(rand() % 300) )
{
int nCountRows = 20 + rand() % 10;
int nRow = rand() % (nHeight - nCountRows - 1);
BYTE* pBaseRow = pIntensity + (nRow + nCountRows)*nWidth;
BYTE* pCurRow = pBaseRow - nWidth;
// âåðõíÿÿ ãðàíèöà ïîëîñû
int nPos = 0;
for( nPos = 0; nPos < nWidth; nPos++ )
{
int rnd = rand() % 10;
if( rnd < 4 )
{
pCurRow[nPos] = pBaseRow[nPos] - 20;
pCurRow[nPos-nWidth] = pBaseRow[nPos];
}
else if( rnd < 6 )
{
pCurRow[nPos-nWidth] = pBaseRow[nPos];
}
}
// ñàìà ïîëîñà
pCurRow -= nWidth*2;
for( ; nCountRows > 4; --nCountRows, pCurRow -= nWidth )
{
memcpy( pCurRow, pBaseRow, nWidth );
}
// íèæíÿÿ ãðàíèöà ïîëîñû
for( nPos = 0; nPos < nWidth; nPos++ )
{
int rnd = rand() % 10;
if( rnd < 4 )
{
pCurRow[nPos] = pBaseRow[nPos] - 20;
pCurRow[nPos-nWidth] = pBaseRow[nPos];
}
else if( rnd < 6 )
{
pCurRow[nPos-nWidth] = pBaseRow[nPos];
}
}
}
// íèòè
//if( !(rand() % 50) )
//{
// int x = rand() % (nWidth - Constants::c_nWidthFiber1);
// int y = rand() % (nHeight - Constants::c_nHeightFiber1);
// for( int j = 0; j < Constants::c_nHeightFiber1; j++ )
// {
// for( int i = 0; i < Constants::c_nWidthFiber1; i++ )
// {
// if( Constants::c_arFiber1[j][i] )
// {
// pIntensity[(y+j)*nWidth + (x + i)] = 220;
// }
// }
// }
//}
// âåðòèêàëüíûå ïîëîñêè
//if( true )
//{
// int dx = rand() % 5 - 2;
// int t = int(dTime / 7) * 7;
// ::srand( DWORD(t + m_dwStartRnd ));
// ::rand();
// if( !(rand() % 100) )
// {
// int nCount = rand() % 3 + 1;
//
// while( nCount-- > 0 )
// {
// int x = rand() % (nWidth - 5) + 2 + dx;
// int y1 = 0;
// int y2 = nHeight;
// for( int y = y1; y < y2; ++y )
// {
// int c = pIntensity[y*nWidth + x] * 13 / 16;
//
// pIntensity[y*nWidth + x] = BYTE(c);
// }
// }
// }
//}
// áëþð
if( true )
{
Ipp8u* pGauss = new Ipp8u[nWidth*nHeight];
IppiSize GaussSize = {nWidth - 4, nHeight - 4};
Ipp8u* pTempPtr = pIntensity + nWidth*2 + 2;
ippiFilterGauss_8u_C1R( pTempPtr, nWidth, pGauss, nWidth, GaussSize, ippMskSize5x5 );
ippiCopy_8u_C1R( pGauss, nWidth, pTempPtr, nWidth, GaussSize );
delete [] pGauss;
}
// êîïèðîâàíèå ÷¸ðíî-áåëîãî èçîáðàæåíèÿ
pSrc[0] = pIntensity;
pSrc[1] = pIntensity;
pSrc[2] = pIntensity;
pSrc[3] = pIntensity;
ippiCopy_8u_P4C4R(pSrc, nWidth, pBuffer, 4*nWidth, ImageSize);
int alpha = int((1 - dCompleteness) * 255);
if( alpha > 255 ) alpha = 255;
if( alpha < 0 ) alpha = 0;
ippiAlphaCompC_8u_AC4R( pBGRASource, 4*nWidth, Ipp8u(alpha), pBuffer, 4*nWidth, 255, pBGRASource, 4*nWidth, ImageSize, ippAlphaOver);
}
if (pBuffer)
delete[] pBuffer;
if (pIntensity)
delete[] pIntensity;
return TRUE;
}
BOOL ToGray( BYTE* pBGRASrcDst, int nWidth, int nHeight, double dCompleteness )
{
if( 0 == m_dGrayFactor )
return TRUE;
Ipp8u* pBuffer = new Ipp8u[nWidth*nHeight*4];
if( !pBuffer )
return FALSE;
Ipp8u* pGrayscale = new Ipp8u[nWidth*nHeight];
if( !pGrayscale )
{
delete [] pBuffer;
return FALSE;
}
IppiSize ImageSize = {nWidth, nHeight};
ippiRGBToGray_8u_AC4C1R( pBGRASrcDst , 4*nWidth, pGrayscale, nWidth, ImageSize );
Ipp8u* pSrcPlanes[4] = {
pGrayscale,
pGrayscale,
pGrayscale,
pGrayscale
};
ippiCopy_8u_P4C4R( pSrcPlanes, nWidth, pBuffer, 4*nWidth, ImageSize );
int nSrcAlpha = int((1 - dCompleteness * m_dGrayFactor) * 255);
if( nSrcAlpha > 255 ) nSrcAlpha = 255;
if( nSrcAlpha < 0 ) nSrcAlpha = 0;
ippiAlphaCompC_8u_AC4R( pBGRASrcDst, 4*nWidth, nSrcAlpha, pBuffer, 4*nWidth, 255, pBGRASrcDst, 4*nWidth, ImageSize, ippAlphaOver);
delete [] pGrayscale;
delete [] pBuffer;
return TRUE;
}
BOOL AddNoise( BYTE* pBGRASrcDst, int nWidth, int nHeight, double dCompleteness )
{
if( nWidth < 3 && nHeight < 3 )
return TRUE;
Ipp8u* pNoisePlane = new Ipp8u[nWidth*nHeight];
if( !pNoisePlane )
return FALSE;
Ipp8u* pAlphaPlane = new Ipp8u[nWidth*nHeight];
if( !pAlphaPlane )
{
delete [] pNoisePlane;
return FALSE;
}
unsigned int nSeed = GetTickCount();
IppiSize ImageSize = {nWidth, nHeight};
int nNoiseLevel = int((1 - m_dNoiseFactor * dCompleteness) * 254);
if( nNoiseLevel > 254 ) nNoiseLevel = 254;
if( nNoiseLevel < 0 ) nNoiseLevel = 0;
// ñîçäà¸ì ðàíäîìíîå çàòåìíåíèå
ZeroMemory( pNoisePlane, nWidth*nHeight );
ippiAddRandUniform_Direct_8u_C1IR( pNoisePlane, nWidth, ImageSize, Ipp8u(nNoiseLevel), 255, &nSeed );
IppiSize GaussSize = {nWidth - 4, nHeight - 4};
Ipp8u* pSrcGauss = pNoisePlane + 2*nWidth + 2;
Ipp8u* pDstGauss = pAlphaPlane + 2*nWidth + 2;
ippiFilterLowpass_8u_C1R( pSrcGauss, nWidth, pDstGauss, nWidth, GaussSize, ippMskSize5x5 );
ippiCopyReplicateBorder_8u_C1R( pSrcGauss, nWidth, GaussSize, pAlphaPlane, nWidth, ImageSize, 2, 2 );
ippiFilterLowpass_8u_C1R( pDstGauss, nWidth, pSrcGauss, nWidth, GaussSize, ippMskSize5x5 );
//ippiCopy_8u_C1R( pAlphaPlane, nWidth, pGaussPtr, nWidth, GaussSize );
// ñîõðàíÿåì àëüôó
ippiCopy_8u_C4C1R( pBGRASrcDst + 3, nWidth*4, pAlphaPlane, nWidth, ImageSize);
// êîïèðóåì çàòåìíåíèå â àëüôó èçîáðàæåíèÿ
ippiCopy_8u_C1C4R( pNoisePlane, nWidth, pBGRASrcDst + 3, nWidth*4, ImageSize);
// "çàòåìíÿåì" ïèêñåëû
ippiAlphaPremul_8u_AC4IR( pBGRASrcDst, nWidth*4, ImageSize );
// âîçâðàùàåì ñòàðóþ àëüôó
ippiCopy_8u_C1C4R( pAlphaPlane, nWidth, pBGRASrcDst + 3, nWidth*4, ImageSize);
delete [] pAlphaPlane;
delete [] pNoisePlane;
return TRUE;
}
BOOL AddSmallArtefacts( Gdiplus::Graphics& oRender, int nWidth, int nHeight, double dCompleteness )
{
Gdiplus::ImageAttributes oImageAttr;
Gdiplus::ColorMatrix oColorMatrix = {
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1
};
if( m_arpArtefactImage )
{
int nCountArtefactsShow = 0;
if ( m_nMaxArtefactsShow > m_nMinArtefactsShow )
nCountArtefactsShow = rand() % (m_nMaxArtefactsShow - m_nMinArtefactsShow) + m_nMinArtefactsShow;
else
nCountArtefactsShow = m_nMinArtefactsShow;
for (int nIndex = 0; nIndex < nCountArtefactsShow; nIndex++)
{
int nCurArtefact = rand() % Constants::c_nArtefactsCount;
int nSrcX = 0;
int nSrcY = 0;
int nSrcW = Constants::c_arArtefactsWidth[nCurArtefact] + 4;
int nSrcH = Constants::c_arArtefactsHeight[nCurArtefact] + 4;
int nDstX = rand() % nWidth;
int nDstY = nHeight - rand() % nHeight;
int nDstW = rand() % (nSrcW / 2) + 3;
int nDstH = rand() % (nSrcH / 2) + 3;
oColorMatrix.m[3][3] = float((rand() % 50 + 200)*dCompleteness/255);
if ( rand() % 2)
{
oColorMatrix.m[0][0] = 0;
oColorMatrix.m[1][1] = 0;
oColorMatrix.m[2][2] = 0;
}
oImageAttr.SetColorMatrix( &oColorMatrix );
oRender.DrawImage( m_arpArtefactImage[nCurArtefact], Gdiplus::Rect(nDstX, nDstY, nDstW, nDstH), nSrcX, nSrcY, nSrcW, nSrcH, Gdiplus::UnitPixel, &oImageAttr );
}
//while( nCountSpots-- > 0 )
//{
// int nSpot = rand() % Constants::c_nArtefactsCount;
// //int nSrcX = m_arrSpots[nSpot].X;
// //int nSrcY = m_arrSpots[nSpot].Y;
// //int nSrcW = m_arrSpots[nSpot].Width;
// //int nSrcH = m_arrSpots[nSpot].Height;
// int nSrcX = 0;
// int nSrcY = 0;
// int nSrcW = Constants::c_arArtefactsWidth[nSpot] + 4;
// int nSrcH = Constants::c_arArtefactsHeight[nSpot] + 4;
// //int nDstX = rand() % nWidth;
// //int nDstY = rand() % nHeight;
// //int nDstW = rand() % (nSrcW / 2) + 3;
// //int nDstH = rand() % (nSrcH / 2) + 3;
// int nDstX = 100;
// int nDstY = 100;
// int nDstW = 200;
// int nDstH = 200;
// oColorMatrix.m[3][3] = float((rand() % 50 + 200)*dCompleteness/255);
// oImageAttr.SetColorMatrix( &oColorMatrix );
// oRender.DrawImage( m_arpArtefactImage[7], 100, 100/*Gdiplus::Rect(nDstX, nDstY, nDstW, nDstH), nSrcX, nSrcY, nSrcW, nSrcH, Gdiplus::UnitPixel, &oImageAttr */);
//}
}
return TRUE;
}
BOOL AddVerticalLines( Gdiplus::Graphics& oRender, int nWidth, int nHeight, double dCompleteness )
{
if ( m_nLinesCurCount < m_nMaxLinesShow )
{
int nCountLinesShow = 0;
if ( m_nMaxLinesShow > m_nMinLinesShow )
nCountLinesShow = rand() % (m_nMaxLinesShow - m_nMinLinesShow) + m_nMinLinesShow;
else
nCountLinesShow = m_nMinLinesShow;
for ( int nIndex = m_nLinesCurCount; nIndex < min(49, nCountLinesShow); nIndex++ )
{
m_arLinesX[nIndex] = rand() % nWidth;
m_arLinesCurLife[nIndex] = rand() % m_nMaxFramesLineShow + 1;
if ( rand() % 100 ) // çäåñü ôàêòîð ïîÿâëÿåíèÿ ëèíèè
m_arLinesCurLife[nIndex] = 0;
}
m_nLinesCurCount = ( m_nLinesCurCount > nCountLinesShow ? m_nLinesCurCount : nCountLinesShow);
}
for (int nIndex = 0; nIndex < m_nLinesCurCount; nIndex++)
{
int nDstX = rand() % nWidth;
if ( 0 != m_arLinesCurLife[nIndex] )
{
Gdiplus::Pen oPen(Gdiplus::Color(BYTE( (rand() % 100 + 100) * dCompleteness ) % 255, 0, 0, 0), 1);
oRender.DrawLine(&oPen, float(m_arLinesX[nIndex]), float(-1.0), float(m_arLinesX[nIndex]), float(nHeight + 1.0) );
m_arLinesCurLife[nIndex] -= 1;
}
}
for (int nIndex = 0; nIndex < m_nLinesCurCount; nIndex++)
{
if ( 0 == m_arLinesCurLife[nIndex] )
{
for ( int nShiftIndex = nIndex; nShiftIndex < m_nLinesCurCount - 1; nShiftIndex++)
{
m_arLinesCurLife[nShiftIndex] = m_arLinesCurLife[nShiftIndex + 1];
m_arLinesX[nShiftIndex] = m_arLinesX[nShiftIndex + 1];
}
m_nLinesCurCount--;
}
}
return TRUE;
}
};
class TVSimulator : public ImageStudio::Caching::CCacheItemPointer
{
protected:
struct TSinus
{
float phase;
float offset;
float ampl;
TSinus() : phase( 0 ), offset( 0 ), ampl( 0 ) {}
};
protected:
double m_dSpeedVer;
int m_nSpeedFactorVer;
double m_dOffsetVer;
double m_dInterframeSize;
double m_dInterframeXSize;
int m_nInterline;
static const int c_nCountSinus = 5;
double m_dAmplOffset;
double m_dAmplFactor;
double m_dPhaseSpeed;
TSinus m_aSinus[c_nCountSinus];
public:
TVSimulator()
{
m_dSpeedVer = 0;
m_nSpeedFactorVer = 0;
m_dOffsetVer = 0;
m_nInterline = 0;
m_dAmplOffset = 0;
m_dAmplFactor = 1;
m_dPhaseSpeed = 0;
}
void Create( const ImageStudio::Serialize::Effects::EffectTVSimulation& pEffect, double dMetricX, double dMetricY )
{
::srand( ::GetTickCount() );
m_dSpeedVer = pEffect.dSpeedSynVer * dMetricY;
m_nSpeedFactorVer = pEffect.nSpeedFactorVer;
m_dOffsetVer = pEffect.dOffsetSynVer * dMetricY;
m_dInterframeSize = max(pEffect.dInterframeSize * dMetricY, 0);
m_dInterframeXSize = max(pEffect.dInterframeXSize * dMetricX, 0);
m_nInterline = pEffect.nInterline;
m_dAmplOffset = 0;
double ampl = max(0, min(0.5, pEffect.dAmplitudeSynHor));
double offset = pEffect.dOffsetSynHor * IPP_PI2;
for( int i = 0; i < c_nCountSinus; i++ )
{
m_aSinus[i].phase = float(IPP_2PI * ((i + 1) * 2));
m_aSinus[i].offset = float(offset);
m_aSinus[i].ampl = float(ampl / ((i + 1) * 2));
m_dAmplOffset += m_aSinus[i].ampl;
}
m_dAmplOffset *= max(-100, min(100, pEffect.nAmplOffset)) / 101.0 * 5;
m_dAmplFactor = max(-100, min(100, pEffect.nAmplFactor)) / 101.0 + 1;
m_dPhaseSpeed = max(-100, min(100, pEffect.nPhaseSpeed)) / 100.0 * IPP_PI;
}
BOOL Draw( BYTE* pPixels, int nWidth, int nHeight, int nStride, double dTime, double dCompleteness )
{
CBuffer<BYTE> oBuffer( nWidth*nHeight*4 );
CBuffer<float> oMapX( nWidth * nHeight );
CBuffer<float> oMapY( nWidth * nHeight );
if( oBuffer.IsEmpty() || oMapX.IsEmpty() || oMapY.IsEmpty() )
return FALSE;
// ñîçäà¸ì êàðòó ïîìåõ
float* pMapX = oMapX.GetPtr();
float* pMapY = oMapY.GetPtr();
int nBaseInterline = 0;
if( m_nInterline != 0 )
nBaseInterline = (::rand() % 2) * 2 - 1;
double dFactor = dCompleteness * nWidth;
double dPhaseFactor = 1.0 / nHeight;
for( int nRow = 0; nRow < nHeight; ++nRow )
{
double dy = nRow + ((m_dOffsetVer + (nBaseInterline + nRow) % (m_nInterline + 1)) + m_nSpeedFactorVer * m_dSpeedVer * dTime/1000) * dCompleteness;
dy -= int(dy / (nHeight + m_dInterframeSize)) * (nHeight + m_dInterframeSize);
if( dy < 0 )
dy += nHeight;
// âåðòèêàëüíûå âîëíû
double dx = 0;
for( int i = 0; i < c_nCountSinus; i++ )
{
dx += abs(dFactor * m_aSinus[i].ampl * ::sin( m_aSinus[i].phase * nRow * dPhaseFactor + m_aSinus[i].offset * dTime * m_dPhaseSpeed ));
}
if( dx > 0 )
dx = -::pow( dx, m_dAmplFactor );
dx -= dFactor * m_dAmplOffset;
for( int nPos = 0; nPos < nWidth; ++nPos, ++pMapX, ++pMapY )
{
dx += 1;
while( dx < 0 )
{
dx += (nWidth - 1) + m_dInterframeXSize;
}
while( dx > nWidth - 1 )
{
dx -= nWidth - 1 + m_dInterframeXSize;
}
*pMapX = float(dx);
*pMapY = float(dy);
}
}
// çàêðàøèâàåì ôîíîâûì öâåòîì
BYTE* pBuffer = oBuffer.GetPtr();
IppiRect SrcRect = {0, 0, nWidth, nHeight};
IppiSize SrcSize = {nWidth, nHeight};
Ipp8u Colors[4] = {0, 0, 0, 255};
ippiSet_8u_C4R( Colors, pBuffer, nWidth*4, SrcSize );
// ðåìåïèì
ippiRemap_8u_C4R( pPixels, SrcSize, nWidth*4, SrcRect,
oMapX.GetPtr(), sizeof(float)*nWidth,
oMapY.GetPtr(), sizeof(float)*nWidth,
pBuffer, nWidth*4, SrcSize, IPPI_INTER_LINEAR);
// îòðèñîâêà ïðèìèòèâîâ gdi+
//Gdiplus::Bitmap oImage( nWidth, nHeight, nWidth*4, PixelFormat32bppARGB, pBuffer );
//if( Gdiplus::Ok == oImage.GetLastStatus() )
//{
// Gdiplus::Graphics oRender( &oImage );
// if( Gdiplus::Ok == oRender.GetLastStatus() )
// {
// int alpha = int(dCompleteness * 64 + 0.5);
// Gdiplus::Pen oPenRed ( Gdiplus::Color(alpha, 250, 50, 50), 2);
// Gdiplus::Pen oPenGreen( Gdiplus::Color(alpha, 50, 250, 50), 2);
// Gdiplus::Pen oPenBlue ( Gdiplus::Color(alpha, 0, 0, 250), 2);
// Gdiplus::Pen* aPens[3] = {&oPenRed, &oPenGreen, &oPenBlue};
//
// for( int nRow = 0; nRow < nHeight; nRow++ )
// {
// for( int nPos = 0; nPos < nWidth; nPos++ )
// {
// if( (::rand() % 25) > 0 )
// continue;
// Gdiplus::Color color;
//
// int nClr = ::rand() % 3;
// int nLen = ::rand() % 3 + 5;
// oRender.DrawLine( aPens[nClr], nPos, nRow, nPos + nLen, nRow );
// }
// }
// }
//}
// êîïèðóåì áóôåð îáðàòíî
ippiCopy_8u_C4R( pBuffer, nWidth*4, pPixels, nWidth*4, SrcSize );
return TRUE;
}
};
class Snow : public ImageStudio::Caching::CCacheItemPointer
{
protected:
struct TSnowFlake
{
float fTimePeriod;
float fTimeOffset;
DWORD nBaseRandom;
};
CBuffer<TSnowFlake> m_aoSnowFlakes; // ìàññèâ ñ èñõîäíûìè äàííûìè î ñíåæèíêàõ
int m_nCountSnowFlakes; // êîëè÷åñòâî ñíåæèíîê
float m_fSizeSnowFlake; // ðàçìåð ñíåæèíîê â ïèêñåëÿõ
float m_fOffsetLeft; // ìàêñèìàëüíîå ñìåùåíèå âëåâî
float m_fOffsetRight; // ìàêñèìàëüíîå ñìåùåíèå âïðàâî
BYTE* m_pSnowRawImage_32x32; // image 64x64
int m_nQuality;
Gdiplus::Color m_oColor; // öâåò ñíåæèíîê
double *m_adSnowDrift; // ãðàíèöà ñóãðîáà
int m_nSnowDriftWidth; //
int m_nBorder;
Gdiplus::PointF* m_arrPoints;
double dSnowDriftSpeedFactor; // êîýôôèöèåíò ñêîðîñòè ðîñòà ñóãðîáà
double m_dOldTime; // äëÿ àâòîìàòè÷åñêîãî ñáðàñûâàíèÿ ñóãðîáà ïðè ïðîèãðûâàíèè ñ íà÷àëà
public:
Snow()
{
m_nCountSnowFlakes = 0;
m_fSizeSnowFlake = 0;
m_fOffsetLeft = 0;
m_fOffsetRight = 0;
m_adSnowDrift = 0;
m_nSnowDriftWidth = -1;
m_arrPoints = 0;
m_nBorder = -1;
m_dOldTime = 0;
m_pSnowRawImage_32x32 = NULL;
m_nQuality = 0;
}
virtual ~Snow()
{
if(m_adSnowDrift)
delete []m_adSnowDrift;
if (m_arrPoints)
delete []m_arrPoints;
}
void Create( const ImageStudio::Serialize::Effects::EffectSnow& pEffect )
{
m_nCountSnowFlakes = min(1000, max(0, pEffect.nCount));
m_fSizeSnowFlake = float(min(100, max(0, pEffect.nSize)) / 100.0 * 50);
m_nBorder = int(6 * m_fSizeSnowFlake);
int nAngleDir = min( 45, max(-45, pEffect.nAngleDir));
int nAngleOffset = min( 45, max( 0, pEffect.nAngleOffset));
m_fOffsetLeft = float(::tan( IPP_PI180 * max(-45, nAngleDir - nAngleOffset)));
m_fOffsetRight = float(::tan( IPP_PI180 * min( 45, nAngleDir + nAngleOffset)));
float fMinDropTime = float(pEffect.dMinTime < 1 ? 1 : pEffect.dMinTime);
float fMaxDropTime = float(pEffect.dMaxTime < 1 ? 1 : pEffect.dMaxTime);
TSnowFlake* pSnowFlake = m_aoSnowFlakes.Create( m_nCountSnowFlakes );
if( !pSnowFlake )
return;
for( int i = m_nCountSnowFlakes; i > 0; --i, ++pSnowFlake )
{
pSnowFlake->fTimePeriod = Random( fMinDropTime, fMaxDropTime );
pSnowFlake->fTimeOffset = pSnowFlake->fTimePeriod * Random();
pSnowFlake->nBaseRandom = ::rand();
}
SetSnowColor( pEffect.nColor, pEffect.nAlpha );
LoadSnowImage( pEffect.nType );
m_nQuality = pEffect.nQuality;
}
BOOL Draw( BYTE* pPixels, int nWidth, int nHeight, int nStride, double dTime, double dCompleteness, BOOL bSnowDrift, double dSnowDriftSpeedFactorIn )
{
int nSnowDriftWidth = nWidth + 2 * m_nBorder;
// îáíóëÿåì âåðõíþþ ãðàíèöó ñóãðîáà
if( (dTime + 0.25) < m_dOldTime )
{
if( m_adSnowDrift )
{
delete [] m_adSnowDrift;
m_adSnowDrift = NULL;
}
}
m_dOldTime = dTime;
double dSnowDriftSpeedFactor = min( 10, max(0.2, dSnowDriftSpeedFactorIn));
if ( !m_adSnowDrift || m_nSnowDriftWidth != nSnowDriftWidth && bSnowDrift)
{
if ( m_adSnowDrift )
delete []m_adSnowDrift;
m_adSnowDrift = new double[nSnowDriftWidth];
m_nSnowDriftWidth = nSnowDriftWidth;
for (int nIndex = 0; nIndex < m_nSnowDriftWidth; nIndex++)
m_adSnowDrift[nIndex] = 0;
}
// ðàáîòàåì ñî ñíåæèíêàìè
TSnowFlake* pSnowFlake = m_aoSnowFlakes.GetPtr();
if( !pSnowFlake )
return FALSE;
if( nStride < 0 )
pPixels -= (nHeight - 1) * nStride;
Gdiplus::Bitmap oImage( nWidth, nHeight, nStride, PixelFormat32bppARGB, pPixels );
if( Gdiplus::Ok != oImage.GetLastStatus() )
return FALSE;
Gdiplus::Graphics oRender( &oImage );
if( Gdiplus::Ok != oRender.GetLastStatus() )
return FALSE;
InterpolationMode mode;
switch( m_nQuality )
{
case 1: mode = Gdiplus::InterpolationModeBicubic; break;
case 2: mode = Gdiplus::InterpolationModeHighQualityBilinear; break;
case 3: mode = Gdiplus::InterpolationModeHighQualityBicubic; break;
default: mode = Gdiplus::InterpolationModeBilinear;
}
oRender.SetInterpolationMode( mode );
//oRender.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
Gdiplus::SolidBrush oBrush( Gdiplus::Color( int(dCompleteness * m_oColor.GetAlpha() + 0.5), m_oColor.GetRed(), m_oColor.GetGreen(), m_oColor.GetBlue() ));
Gdiplus::Bitmap* pSnowImage = CreateSnowImage( m_oColor, dCompleteness );
for( int i = 0; i < m_nCountSnowFlakes; ++i, ++pSnowFlake )
{
double time = dTime + pSnowFlake->fTimeOffset;
int period = int(time / pSnowFlake->fTimePeriod);
CRandom oRnd( DWORD(period + pSnowFlake->nBaseRandom) );
time -= period * pSnowFlake->fTimePeriod;
double dSpeedX = oRnd.RandF( m_fOffsetLeft, m_fOffsetRight ) * nHeight / pSnowFlake->fTimePeriod;
double dSpeedY = (nHeight + m_fSizeSnowFlake) / pSnowFlake->fTimePeriod;
double dPosX = dSpeedX * time + oRnd.RandF( 0, float(nWidth) );
double dPosY = dSpeedY * time - m_fSizeSnowFlake;
double dAngle = oRnd.RandF( -1000.0, 1000.0 ) * time / pSnowFlake->fTimePeriod;
// ïðîâåðÿåì ïîïàëàëà ëè ñíåæèíêà â ñóãðîá
// åñëè ïîïàëà åå íå ðèñóåì, à ó ñóãðîáà óâåëè÷èâàåì ãðàíèöó â äàííîì ìåñòå
// todo: 1. íàäî â ñòðóêòóðå ñíåæèíêè ââåñòè áóëåâñêóþ ïåðåìåííóþ ïîïàäàíèÿ â ñóãðîá
// 2. óëó÷øèòü ïðîâåðêó íà ïîïàäàíèå ñíåæèíêè â ñóãðîá
BOOL bDrawFlake = TRUE;
if ( bSnowDrift )
{
int nSize = int(m_fSizeSnowFlake);
double dCenterX = dPosX - nSize;
double dCenterY = dPosY + nSize;
double dRevSize = (0.5 / nSize) * (0.5 / nSize);
int nCurX = int(dPosX);
if ( nCurX >= - m_nBorder && nCurX < nWidth + m_nBorder )
{
int nCurIndex = nCurX + m_nBorder;
if ( dPosY <= nHeight - m_adSnowDrift[nCurIndex] && dPosY > nHeight - ( m_adSnowDrift[nCurIndex] + 1 ) )
{
double dCurVal = 0.5 * dSnowDriftSpeedFactor;
m_adSnowDrift[nCurIndex] += dCurVal;
for(int nX = nCurIndex; nX < min(nSnowDriftWidth - 1, nCurIndex + nSize); nX++)
{
dCurVal += -dRevSize;
m_adSnowDrift[nX] += dCurVal; // ýïèöåíòð ïàäåíèÿ
if( m_adSnowDrift[nX] > m_adSnowDrift[nCurIndex]) // åñëè ñîñåäíÿÿ òî÷êà ãðàíèöû áîëüøå çíà÷åíèÿ â ýïèöåíòðå,
m_adSnowDrift[nX] -= dCurVal / 2; // òîãäà åå çíà÷åíèå ìåíüøå óâåëè÷èâàåì
}
dCurVal = 1.0;
for(int nX = nCurIndex; nX > max(0, nCurIndex - nSize); nX --)
{
dCurVal += -dRevSize;
m_adSnowDrift[nX] += dCurVal;
if( m_adSnowDrift[nX] > m_adSnowDrift[nCurIndex])
m_adSnowDrift[nX] -= dCurVal / 2;
}
}
if ( dPosY > nHeight - (m_adSnowDrift[nCurIndex] + 1))
bDrawFlake = FALSE;
}
}
if( bDrawFlake )
{
if( !DrawSnow( oRender, pSnowImage, float(dPosX), float(dPosY), m_fSizeSnowFlake, float(dAngle) ) )
{
oRender.FillEllipse( &oBrush, float(dPosX), float(dPosY), m_fSizeSnowFlake, m_fSizeSnowFlake );
}
}
}
if( pSnowImage )
delete pSnowImage;
oRender.SetInterpolationMode( Gdiplus::InterpolationModeBilinear );
oRender.SetSmoothingMode( Gdiplus::SmoothingModeAntiAlias );
if ( bSnowDrift )
{
double dFirst = m_adSnowDrift[0];
double dSecond = m_adSnowDrift[1];
for(int nIndex = 2; nIndex < nSnowDriftWidth - 2; nIndex++)
{
// èíòåðïîëÿöèÿ ïî 5 òî÷êàì, äëÿ ñãëàæèâàíèÿ
double dCurVal = (dFirst + dSecond + m_adSnowDrift[nIndex] + m_adSnowDrift[nIndex + 1] + m_adSnowDrift[nIndex + 2]) / 5;
dFirst = dSecond;
dSecond = m_adSnowDrift[nIndex];
m_adSnowDrift[nIndex] = dCurVal;
}
if (m_arrPoints)
delete []m_arrPoints;
m_arrPoints = new Gdiplus::PointF[nSnowDriftWidth + 2];
for(int nIndex = 0; nIndex < nSnowDriftWidth; nIndex++)
{
m_arrPoints[nIndex].X = float(nIndex) - m_nBorder;
m_arrPoints[nIndex].Y = float(nHeight - m_adSnowDrift[nIndex]);
}
m_arrPoints[nSnowDriftWidth].X = float(nWidth + 1);
m_arrPoints[nSnowDriftWidth].Y = float(nHeight + 1);
m_arrPoints[nSnowDriftWidth + 1].X = float(-10.0);
m_arrPoints[nSnowDriftWidth + 1].Y = float(nHeight + 1);
oRender.FillPolygon( &oBrush, m_arrPoints, nSnowDriftWidth + 2);
}
return TRUE;
}
protected:
void SetSnowColor( int color, int alpha )
{
m_oColor = Gdiplus::Color( min(255, max(0, alpha)), GetRValue(color), GetGValue(color), GetBValue(color));
}
BOOL LoadSnowImage( int nType )
{
static const LPCTSTR szNames[5] = { _T("#208"), _T("#209"), _T("#210"), _T("#211"), _T("#212") };
if( nType < 0 || nType > 4 )
{
nType = 0;
}
HMODULE hModule = ::GetModuleHandle( _T("AVSImageStudio3.dll") );
HRSRC hResHandle = ::FindResource( hModule, szNames[nType], _T("RawImage") );
if( !hResHandle )
return FALSE;
HGLOBAL hResMem = ::LoadResource( hModule, hResHandle );
if( !hResMem )
return FALSE;
m_pSnowRawImage_32x32 = (BYTE*)::LockResource( hResMem );
return m_pSnowRawImage_32x32 != NULL;
}
Gdiplus::Bitmap* CreateSnowImage( Gdiplus::Color color, double dCompleteness ) const
{
if( !m_pSnowRawImage_32x32 )
return NULL;
const int nWidth = 32;
const int nHeight = 32;
Gdiplus::Bitmap* pResult = new Gdiplus::Bitmap( nWidth, nHeight );
if( !pResult || pResult->GetLastStatus() != Gdiplus::Ok )
{
return NULL;
}
Gdiplus::BitmapData oData;
if( Gdiplus::Ok != pResult->LockBits( NULL, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &oData ) )
{
delete pResult;
return NULL;
}
DWORD clr[4] = {
DWORD(color.GetBlue()) * 0x8081,
DWORD(color.GetGreen()) * 0x8081,
DWORD(color.GetRed()) * 0x8081,
DWORD(color.GetAlpha() * dCompleteness + 0.5) * 0x8081,
};
int nDstStride = oData.Stride - nWidth * 4;
BYTE* pDst = (BYTE*)oData.Scan0;
BYTE* pSrc = m_pSnowRawImage_32x32;
for( int nY = 0; nY < nHeight; ++nY, pDst += nDstStride )
{
for( int nX = 0; nX < nWidth; ++nX, pSrc += 4, pDst += 4 )
{
for( int i = 0; i < 4; i++ )
{
pDst[i] = BYTE((pSrc[i] * clr[i] + 128 * 0x8081) >> 23 /*/ 255*/);
}
}
}
pResult->UnlockBits( &oData );
return pResult;
}
BOOL DrawSnow( Gdiplus::Graphics& render, Gdiplus::Bitmap* pSnowImage, float x, float y, float size, float angle ) const
{
if( !pSnowImage )
return FALSE;
Gdiplus::RectF rect( x - size / 2, y - size / 2, size, size );
Gdiplus::Matrix matrix1;
Gdiplus::Matrix matrix2;
matrix2.RotateAt( angle, Gdiplus::PointF( x, y ), Gdiplus::MatrixOrderAppend );
render.GetTransform( &matrix1 );
render.SetTransform( &matrix2 );
Gdiplus::Status status = render.DrawImage( pSnowImage, rect );
render.SetTransform( &matrix1 );
return Gdiplus::Ok == status;
}
};
class Puzzle : public ImageStudio::Caching::CCacheItemPointer
{
protected:
int m_nFigureType;
// ïàðàìåòðû äëÿ ïàçëà è ïëèòêè
int *m_pHorizontalFactor;
int *m_pVerticalFactor;
int m_nRow;
int m_nCol;
// ïàðàìåòðû äëÿ îñòàëüíûõ ñëó÷àåâ
double m_dSide;
int m_nXCount;
int m_nYCount;
int m_nCount;
double m_dBigRadius;
double m_dShiftY; // âñïîìîãàòåëüíûå ïàðàìåòðû, îáû÷íî èñïîëüçóþòñÿ äëÿ íàõîæäåíèÿ
double m_dShiftX; // êîîðäèíàò âåðøèí, îòíîñèòåëüíî êîîðäèíàò öåíòðà
Gdiplus::PointF* m_arrPoints;
int m_nPointsCount;
public:
Puzzle()
{
m_pHorizontalFactor = 0;
m_pVerticalFactor = 0;
m_nRow = -1;
m_nCol = -1;
m_dSide = -1;
m_nXCount = -1;
m_nYCount = -1;
m_nCount = -1;
m_arrPoints = 0;
m_nPointsCount = -1;
}
virtual ~Puzzle()
{
if ( m_pHorizontalFactor )
delete []m_pHorizontalFactor;
if ( m_pVerticalFactor )
delete []m_pVerticalFactor;
if ( m_arrPoints )
delete []m_arrPoints;
}
void Create( const ImageStudio::Serialize::Paint::Common::DrawPuzzle& pEffect, double dSide, DWORD dwBaseRnd )
{
m_nFigureType = pEffect.m_nType;
if ( 1 == pEffect.m_nType )
GeneratePuzzleMask(pEffect.m_nRow, pEffect.m_nCol, dwBaseRnd );
else if ( 2 <= pEffect.m_nType && 6 >= pEffect.m_nType )
{
m_dSide = dSide;
m_arrPoints = 0;
m_nPointsCount = -1;
m_nFigureType = pEffect.m_nType;
// äàëåå çàïîëíÿåì äîïîëíèòåëüíûå äàííûå
if ( 2 == m_nFigureType )
{
m_dBigRadius = dSide;
m_dShiftX = m_dBigRadius / 2;
m_dShiftY = sqrt(3.0) * m_dBigRadius / 2;
}
else if ( 5 == m_nFigureType)
{
m_dBigRadius = sqrt(3.0) * dSide / 3; // ðàäèóñ îïèñàííîé îêðóæíîñòè
m_dShiftY = m_dBigRadius / 2; // ðàäèóñ âïèñàííîé îêðóæíîñòè
m_dShiftX = dSide / 2;
}
else if ( 3 == m_nFigureType )
{
m_dBigRadius = dSide / sqrt(2.0);
}
else if ( 4 == m_nFigureType )
{
m_dShiftX = dSide / 2;
m_dShiftY = dSide * ( 12.0 / 25.0 ) / 2;
}
else if ( 6 == m_nFigureType )
{
m_dShiftX = dSide / 2;
m_dShiftY = dSide * ( 12.0 / 25.0 ) / 2;
}
}
return;
}
void GeneratePuzzleMask( int nRow, int nCol, DWORD dwBaseRnd )
{
if ( m_pHorizontalFactor && m_pVerticalFactor && nRow == m_nRow && nCol == m_nCol )
return;
if ( m_pHorizontalFactor )
delete []m_pHorizontalFactor;
if ( m_pVerticalFactor )
delete []m_pVerticalFactor;
int nSize = nCol * nRow * 2;
m_nRow = nRow;
m_nCol = nCol;
m_pHorizontalFactor = new int[nSize];
m_pVerticalFactor = new int[nSize];
CRandom rnd( dwBaseRnd );
for ( int nYIndex = 0, nIndex = 0; nYIndex < nRow; nYIndex++ )
{
for ( int nXIndex = 0; nXIndex < nCol; nXIndex++, nIndex += 2 )
{
if ( 1 == nRow )
{
m_pHorizontalFactor[nIndex + 0] = 0;
m_pHorizontalFactor[nIndex + 1] = 0;
continue;
}
if ( 0 == nYIndex )
{
m_pHorizontalFactor[nIndex + 0] = 0;
m_pHorizontalFactor[nIndex + 1] = -1 + 2 * rnd.Rand( 2 );
}
else if ( nRow - 1 == nYIndex )
{
m_pHorizontalFactor[nIndex + 1] = 0;
m_pHorizontalFactor[nIndex + 0] = - m_pHorizontalFactor[nIndex - nCol * 2 + 1];
}
else
{
m_pHorizontalFactor[nIndex + 1] = -1 + 2 * rnd.Rand( 2 );
m_pHorizontalFactor[nIndex + 0] = - m_pHorizontalFactor[nIndex - nCol * 2 + 1];
}
if ( 1 == nCol )
{
m_pVerticalFactor[nIndex + 0] = 0;
m_pVerticalFactor[nIndex + 1] = 0;
continue;
}
if ( 0 == nXIndex )
{
m_pVerticalFactor[nIndex + 0] = 0;
m_pVerticalFactor[nIndex + 1] = -1 + 2 * rnd.Rand( 2 );
}
else if ( nCol - 1 == nXIndex )
{
m_pVerticalFactor[nIndex + 1] = 0;
m_pVerticalFactor[nIndex + 0] = - m_pVerticalFactor[nIndex - 1];
}
else
{
m_pVerticalFactor[nIndex + 1] = -1 + 2 * rnd.Rand( 2 );
m_pVerticalFactor[nIndex + 0] = - m_pVerticalFactor[nIndex - 1];
}
}
}
return;
}
void SetCount(int nFigureType, int nWidth, int nHeight)
{
int nXCount = 0;
int nYCount = 0;
double dSide = m_dSide;
if ( dSide < 5 )
return;
//
// Ðàñ÷åò ÷èñëà êóñî÷êîâ
//
if ( 2 == nFigureType ) // øåñòèóãîëüíèêè
{
nXCount = nWidth / int(1.5 * dSide) + 1;
if( nWidth % int(1.5 * dSide) > 0 )
nXCount++;
nYCount = nHeight / int(sqrt(3.0) * dSide) + 1;
if( nHeight % int(sqrt(3.0) * dSide) > 0 )
nYCount++;
}
else if ( 5 == nFigureType ) // òðåóãîëüíèêè
{
nXCount = nWidth / int(0.5 * dSide) + 1;
if( nWidth % int(0.5 * dSide) > 0 )
nXCount++;
nYCount = nHeight / int(sqrt(3.0) * 0.5 * dSide) + 1;
if( nHeight % int(sqrt(3.0) * 0.5 * dSide) > 0 )
nYCount++;
}
else if ( 3 == nFigureType ) // ðîìáû
{
double dRadius = dSide / sqrt(2.0); // ðàäèóñ îïèñàííîé îêðóæíîñòè
nXCount = nWidth / int(dRadius) + 2;
nYCount = nHeight / int(2 * dRadius) + 2;
}
else if ( 4 == nFigureType ) // êèðïè÷è
{
double dXShift = dSide;
double dYShift = dSide * (12.0 / 25.0);
nXCount = nWidth / int(dXShift) + 2;
nYCount = nHeight / int(dYShift) + 2;
}
else if ( 6 == nFigureType ) //íàêëîííûå êèðïè÷è
{
double dAngle = atan(25.0 / 24.0) - IPP_PI4;
double dXShift = dSide * sqrt( 1.0 / 4.0 + 144.0 / 625.0 ) * cos(dAngle);
nXCount = int((nWidth + nHeight * tan(dAngle)) / int(dXShift) + 2);
nYCount = int((nHeight + nWidth * tan(dAngle)) / int(dXShift) + 2);
}
int nCount = nXCount * nYCount;
m_nXCount = nXCount;
m_nYCount = nYCount;
m_nCount = nCount;
}
BOOL DrawPiece(Gdiplus::Graphics *oRender, double dXCoorResult, double dYCoorResult, int nWidth, int nHeight, double dAlpha, double dFigWidth, double dFigHeight, int nTopFactor, int nRightFactor, int nBottomFactor, int nLeftFactor)
{
if ( !oRender )
return FALSE;
int nSize = 4 * nHeight * nWidth;
double dDiagonal = min(dFigHeight, dFigWidth);
double dUnit = 1 / (72.0) * dDiagonal;
double dCircleWidth = 26 * dUnit; // øèðèíà êðóæî÷êà, ò.å. 2 * ðàäèóñ - (çàçîð ñî ñðåäíåé ÷àñòüþ)
double dRadius = 15 * dUnit; // ðàäèóñ êðóæî÷êà
double dSqrRadius = dRadius * dRadius;
double dInStep = 37 * dUnit;
double dFullHeight = dFigHeight + 2 * dCircleWidth; // ïîëíàÿ âûñîòà êóñî÷êà, ñ ó÷åòîì êðóæêîâ
double dFullWidth = dFigWidth + 2 * dCircleWidth; // ïîëíàÿ øèðèíà êóñî÷êà
double dXResult = dXCoorResult - dCircleWidth;
double dYResult = dYCoorResult - dCircleWidth;
double dStep = 11 * dUnit;
double dSrez = sqrt(dSqrRadius - dStep * dStep);
double dAngle = acos(11 * dUnit / dRadius) * 180 / IPP_PI;
double dAlphaKoef = dAlpha / 255.0;
int nAlphaBlack = int(448 * dAlphaKoef);
int nAlphaWhite = int(448 * dAlphaKoef);
for (int nIndex = 0; nIndex < 5; nIndex++ )
{
nAlphaBlack /= 2;
if (nIndex == 1)
{
nAlphaBlack = int(224 * dAlphaKoef);
nAlphaWhite = int(224 * dAlphaKoef);
}
Gdiplus::Pen oPen( Color( nAlphaBlack, 0, 0, 0) , 1);
if ( 0 == nRightFactor )
oRender->DrawLine(&oPen, float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex), float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dCircleWidth + nIndex));
else
{
if ( 1 == nRightFactor)
oRender->DrawArc(&oPen, float(dXResult + dFullWidth - 2 * dRadius + nIndex), nHeight - float(dYResult + dFullHeight / 2 + dRadius - nIndex), float(2 * (dRadius - nIndex)), float(2 * (dRadius - nIndex)), float(180 + dAngle), float(360 - 2 * dAngle));
else if ( -1 == nRightFactor)
oRender->DrawArc(&oPen, float(dXResult + dFullWidth - 2 * dRadius - nIndex - 2 * dStep), nHeight - float(dYResult + dFullHeight / 2 + dRadius + nIndex), float(2 * (dRadius + nIndex)), float(2 * (dRadius + nIndex)), float(dAngle + nIndex), float(360 - 2 * dAngle - 2* nIndex));
oRender->DrawLine(&oPen, float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex), float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dFullHeight / 2 + dSrez +nIndex));
oRender->DrawLine(&oPen, float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dFullHeight / 2 - dSrez - nIndex), float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dCircleWidth + nIndex));
}
if ( 0 == nTopFactor )
oRender->DrawLine(&oPen, float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dCircleWidth + nIndex), float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dCircleWidth + nIndex));
else
{
if ( 1 == nTopFactor)
oRender->DrawArc(&oPen, float(dXResult + dFullWidth / 2 - dRadius + nIndex), nHeight - float(dYResult + 2 * dRadius - nIndex), float(2 * (dRadius - nIndex)), float(2 * (dRadius - nIndex)), float(270 + dAngle), float(360 - 2 * dAngle));
else if ( -1 == nTopFactor)
oRender->DrawArc(&oPen, float(dXResult + dFullWidth / 2 - dRadius - nIndex), nHeight - float(dYResult + 2 * dRadius + nIndex + 2 * dStep), float(2 * (dRadius + nIndex)), float(2 * (dRadius + nIndex)), float(90 + dAngle + nIndex), float(360 - 2 * dAngle - 2* nIndex));
oRender->DrawLine(&oPen, float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dCircleWidth + nIndex), float(dXResult + dFullWidth / 2 + dSrez + nIndex), nHeight - float(dYResult + dCircleWidth + nIndex));
oRender->DrawLine(&oPen, float(dXResult + dFullWidth / 2 - dSrez - nIndex), nHeight - float(dYResult + dCircleWidth + nIndex), float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dCircleWidth + nIndex));
}
nAlphaWhite /= 2;
oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
if ( 0 == nLeftFactor )
oRender->DrawLine(&oPen, float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dCircleWidth + nIndex), float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex));
else
{
if ( 1 == nLeftFactor)
oRender->DrawArc(&oPen, float(dXResult + nIndex), nHeight - float(dYResult + dFullHeight / 2 + dRadius - nIndex), float(2 * (dRadius - nIndex)), float(2 * (dRadius - nIndex)), float(dAngle), float(360 - 2 * dAngle));
else if ( -1 == nLeftFactor)
oRender->DrawArc(&oPen, float(dXResult - nIndex + 2 * dStep), nHeight - float(dYResult + dFullHeight / 2 + dRadius + nIndex), float(2 * (dRadius + nIndex)), float(2 * (dRadius + nIndex)), float(180 + dAngle + nIndex), float(360 - 2 * dAngle - 2* nIndex));
oRender->DrawLine(&oPen, float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dCircleWidth + nIndex), float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dFullHeight / 2 - dSrez - nIndex));
oRender->DrawLine(&oPen, float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dFullHeight / 2 + dSrez + nIndex), float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex));
}
if ( 0 == nBottomFactor )
oRender->DrawLine(&oPen, float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex), float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex));
else
{
if ( 1 == nBottomFactor)
oRender->DrawArc(&oPen, float(dXResult + dFullWidth / 2 - dRadius + nIndex), nHeight - float(dYResult + dFullHeight - nIndex), float(2 * (dRadius - nIndex)), float(2 * (dRadius - nIndex)), float(90 + dAngle), float(360 - 2 * dAngle));
else if ( -1 == nBottomFactor)
oRender->DrawArc(&oPen, float(dXResult + dFullWidth / 2 - dRadius - nIndex), nHeight - float(dYResult + dFullHeight + nIndex - 2 * dStep), float(2 * (dRadius + nIndex)), float(2 * (dRadius + nIndex)), float(270 + dAngle + nIndex), float(360 - 2 * dAngle - 2* nIndex));
oRender->DrawLine(&oPen, float(dXResult + dFullWidth - dCircleWidth - nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex), float(dXResult + dFullWidth / 2 + dSrez + nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex));
oRender->DrawLine(&oPen, float(dXResult + dFullWidth / 2 - dSrez - nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex), float(dXResult + dCircleWidth + nIndex), nHeight - float(dYResult + dFullHeight - dCircleWidth - nIndex));
}
}
return TRUE;
}
BOOL CreatePolygon(int nNumber, double dX, double dY)
{
if (m_arrPoints)
delete []m_arrPoints;
if (2 == nNumber)
{
m_nPointsCount = 6;
m_arrPoints = new Gdiplus::PointF[6];
int nRadius = int(m_dBigRadius);
double dXShift = m_dShiftX;
double dYShift = m_dShiftY;
m_arrPoints[0].X = float(dX - dXShift);
m_arrPoints[0].Y = float(dY + dYShift);
m_arrPoints[1].X = float(dX + dXShift);
m_arrPoints[1].Y = float(dY + dYShift);
m_arrPoints[2].X = float(dX + nRadius);
m_arrPoints[2].Y = float(dY);
m_arrPoints[3].X = float(dX + dXShift);
m_arrPoints[3].Y = float(dY - dYShift);
m_arrPoints[4].X = float(dX - dXShift);
m_arrPoints[4].Y = float(dY - dYShift);
m_arrPoints[5].X = float(dX - nRadius);
m_arrPoints[5].Y = float(dY);
}
else if ( 30 == nNumber )
{
m_nPointsCount = 3;
m_arrPoints = new Gdiplus::PointF[3];
m_arrPoints[0].X = float(dX - m_dShiftX);
m_arrPoints[0].Y = float(dY + m_dShiftY);
m_arrPoints[1].X = float(dX);
m_arrPoints[1].Y = float(dY - m_dBigRadius);
m_arrPoints[2].X = float(dX + m_dShiftX);
m_arrPoints[2].Y = float(dY + m_dShiftY);
}
else if ( 31 == nNumber )
{
m_nPointsCount = 3;
m_arrPoints = new Gdiplus::PointF[3];
m_arrPoints[0].X = float(dX);
m_arrPoints[0].Y = float(dY + m_dBigRadius);
m_arrPoints[1].X = float(dX - m_dShiftX);
m_arrPoints[1].Y = float(dY - m_dShiftY);
m_arrPoints[2].X = float(dX + m_dShiftX);
m_arrPoints[2].Y = float(dY - m_dShiftY);
}
else if ( 3 == m_nFigureType )
{
m_nPointsCount = 4;
m_arrPoints = new Gdiplus::PointF[4];
m_arrPoints[0].X = float(dX - m_dBigRadius);
m_arrPoints[0].Y = float(dY);
m_arrPoints[1].X = float(dX);
m_arrPoints[1].Y = float(dY + m_dBigRadius);
m_arrPoints[2].X = float(dX + m_dBigRadius);
m_arrPoints[2].Y = float(dY);
m_arrPoints[3].X = float(dX);
m_arrPoints[3].Y = float(dY - m_dBigRadius);
}
else if ( 4 == m_nFigureType )
{
m_nPointsCount = 4;
m_arrPoints = new Gdiplus::PointF[4];
m_arrPoints[0].X = float(dX - m_dShiftX);
m_arrPoints[0].Y = float(dY - m_dShiftY);
m_arrPoints[1].X = float(dX + m_dShiftX);
m_arrPoints[1].Y = float(dY - m_dShiftY);
m_arrPoints[2].X = float(dX + m_dShiftX);
m_arrPoints[2].Y = float(dY + m_dShiftY);
m_arrPoints[3].X = float(dX - m_dShiftX);
m_arrPoints[3].Y = float(dY + m_dShiftY);
}
else if ( 6 == m_nFigureType )
{
m_nPointsCount = 4;
m_arrPoints = new Gdiplus::PointF[4];
double dCos = cos(-IPP_PI4);
double dSin = sin(-IPP_PI4);
m_arrPoints[3].X = float(- m_dShiftX * dCos - (- m_dShiftY) * dSin + dX);
m_arrPoints[3].Y = float(- m_dShiftX * dSin + (- m_dShiftY) * dCos + dY);
m_arrPoints[2].X = float( m_dShiftX * dCos - (- m_dShiftY) * dSin + dX);
m_arrPoints[2].Y = float( m_dShiftX * dSin + (- m_dShiftY) * dCos + dY);
m_arrPoints[1].X = float( m_dShiftX * dCos - ( m_dShiftY) * dSin + dX);
m_arrPoints[1].Y = float( m_dShiftX * dSin + ( m_dShiftY) * dCos + dY);
m_arrPoints[0].X = float(- m_dShiftX * dCos - ( m_dShiftY) * dSin + dX);
m_arrPoints[0].Y = float(- m_dShiftX * dSin + ( m_dShiftY) * dCos + dY);
}
return TRUE;
}
BOOL DrawHexagonBorder(Gdiplus::Graphics *oMainRender, double dXCoorResult, double dYCoorResult, double dEffect)
{
Gdiplus::Pen oPen(Color(0, 0, 0), 1);
CreatePolygon(m_nFigureType, dXCoorResult, dYCoorResult);
int nAlphaBlack = int(448 * dEffect);
int nAlphaWhite = int(448 * dEffect);
for ( int nIndex = 0; nIndex < 5; nIndex++ )
{
nAlphaBlack /= 2;
if (nIndex == 1)
{
nAlphaBlack = int(224 * dEffect);
nAlphaWhite = int(224 * dEffect);
}
nAlphaWhite /= 2;
//oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oMainRender->DrawLine(&oPen, m_arrPoints[0], m_arrPoints[1]);
oMainRender->DrawLine(&oPen, m_arrPoints[1], m_arrPoints[2]);
oMainRender->DrawLine(&oPen, m_arrPoints[2], m_arrPoints[3]);
//oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oMainRender->DrawLine(&oPen, m_arrPoints[3], m_arrPoints[4]);
oMainRender->DrawLine(&oPen, m_arrPoints[4], m_arrPoints[5]);
oMainRender->DrawLine(&oPen, m_arrPoints[5], m_arrPoints[0]);
m_arrPoints[0].X++;
m_arrPoints[0].Y--;
m_arrPoints[1].X--;
m_arrPoints[1].Y--;
m_arrPoints[2].X--;
m_arrPoints[3].X--;
m_arrPoints[3].Y++;
m_arrPoints[4].X++;
m_arrPoints[4].Y++;
m_arrPoints[5].X++;
}
return TRUE;
}
BOOL DrawTriangleBorder(Gdiplus::Graphics *oMainRender, double dXCoorResult, double dYCoorResult, double dEffect, int nType)
{
if (0 == nType )
{
Gdiplus::Pen oPen(Color(0, 0, 0), 1);
CreatePolygon(30, dXCoorResult, dYCoorResult);
int nAlphaBlack = int(448 * dEffect);
int nAlphaWhite = int(448 * dEffect);
for ( int nIndex = 0; nIndex < 5; nIndex++ )
{
nAlphaBlack /= 2;
if (nIndex == 1 || nIndex == 2)
{
nAlphaBlack = int(224 * dEffect);
nAlphaWhite = int(224 * dEffect);
}
nAlphaWhite /= 2;
if(nIndex == 0)
{
nAlphaWhite = 128;
nAlphaBlack = 128;
}
oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oMainRender->DrawLine(&oPen, m_arrPoints[0], m_arrPoints[1]);
oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oMainRender->DrawLine(&oPen, m_arrPoints[1], m_arrPoints[2]);
oMainRender->DrawLine(&oPen, m_arrPoints[2], m_arrPoints[0]);
m_arrPoints[0].X ++;
m_arrPoints[0].Y -= float(0.4);
m_arrPoints[1].Y++;
m_arrPoints[2].X --;
m_arrPoints[2].Y -= float(0.4);
}
}
else if ( 1 == nType)
{
Gdiplus::Pen oPen(Color(0, 0, 0), 1);
CreatePolygon(31, dXCoorResult, dYCoorResult);
int nAlphaBlack = int(448 * dEffect);
int nAlphaWhite = int(448 * dEffect);
for ( int nIndex = 0; nIndex < 5; nIndex++ )
{
nAlphaBlack /= 2;
if (nIndex == 1 || nIndex == 2)
{
nAlphaBlack = int(224 * dEffect);
nAlphaWhite = int(224 * dEffect);
}
nAlphaWhite /= 2;
if(nIndex == 0)
{
nAlphaWhite = 128;
nAlphaBlack = 128;
}
oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oMainRender->DrawLine(&oPen, m_arrPoints[0], m_arrPoints[1]);
oMainRender->DrawLine(&oPen, m_arrPoints[1], m_arrPoints[2]);
oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oMainRender->DrawLine(&oPen, m_arrPoints[2], m_arrPoints[0]);
m_arrPoints[0].Y--;
m_arrPoints[1].X ++;
m_arrPoints[1].Y += float(0.4);
m_arrPoints[2].X --;
m_arrPoints[2].Y += float(0.4);
}
}
return TRUE;
}
BOOL DrawRhombusBorder(Gdiplus::Graphics *oMainRender, double dXCoorResult, double dYCoorResult, double dEffect)
{
Gdiplus::Pen oPen(Color(0, 0, 0), 1);
CreatePolygon(m_nFigureType, dXCoorResult, dYCoorResult);
int nAlphaBlack = int(448 * dEffect);
int nAlphaWhite = int(448 * dEffect);
for ( int nIndex = 0; nIndex < 5; nIndex++ )
{
nAlphaBlack /= 2;
if (nIndex == 1)
{
nAlphaBlack = int(224 * dEffect);
nAlphaWhite = int(224 * dEffect);
}
nAlphaWhite /= 2;
//oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oMainRender->DrawLine(&oPen, m_arrPoints[0], m_arrPoints[1]);
oMainRender->DrawLine(&oPen, m_arrPoints[1], m_arrPoints[2]);
//oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oMainRender->DrawLine(&oPen, m_arrPoints[2], m_arrPoints[3]);
oMainRender->DrawLine(&oPen, m_arrPoints[3], m_arrPoints[0]);
m_arrPoints[0].X++;
m_arrPoints[1].Y--;
m_arrPoints[2].X--;
m_arrPoints[3].Y++;
}
return TRUE;
}
BOOL DrawBrickBorder(Gdiplus::Graphics *oMainRender, double dXCoorResult, double dYCoorResult, double dEffect)
{
Gdiplus::Pen oPen(Color(0, 0, 0), 1);
CreatePolygon(m_nFigureType, dXCoorResult, dYCoorResult);
int nAlphaBlack = int(448 * dEffect);
int nAlphaWhite = int(448 * dEffect);
for ( int nIndex = 0; nIndex < 5; nIndex++ )
{
nAlphaBlack /= 2;
if (nIndex == 1)
{
nAlphaBlack = int(224 * dEffect);
nAlphaWhite = int(224 * dEffect);
}
nAlphaWhite /= 2;
//oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oMainRender->DrawLine(&oPen, m_arrPoints[1], m_arrPoints[2]);
oMainRender->DrawLine(&oPen, m_arrPoints[2], m_arrPoints[3]);
//oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oMainRender->DrawLine(&oPen, m_arrPoints[0], m_arrPoints[1]);
oMainRender->DrawLine(&oPen, m_arrPoints[3], m_arrPoints[0]);
m_arrPoints[0].X++;
m_arrPoints[0].Y++;
m_arrPoints[1].X--;
m_arrPoints[1].Y++;
m_arrPoints[2].X--;
m_arrPoints[2].Y--;
m_arrPoints[3].X++;
m_arrPoints[3].Y--;
}
return TRUE;
}
BOOL DrawInclinedBrickBorder(Gdiplus::Graphics *oMainRender, double dXCoorResult, double dYCoorResult, double dEffect)
{
Gdiplus::Pen oPen(Color(0, 0, 0), 1);
CreatePolygon(m_nFigureType, dXCoorResult, dYCoorResult);
int nAlphaBlack = int(448 * dEffect);
int nAlphaWhite = int(448 * dEffect);
for ( int nIndex = 0; nIndex < 5; nIndex++ )
{
nAlphaBlack /= 2;
if (nIndex == 1)
{
nAlphaBlack = int(224 * dEffect);
nAlphaWhite = int(224 * dEffect);
}
nAlphaWhite /= 2;
//oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oMainRender->DrawLine(&oPen, m_arrPoints[0], m_arrPoints[1]);
oMainRender->DrawLine(&oPen, m_arrPoints[1], m_arrPoints[2]);
//oPen.SetColor(Color(nAlphaBlack, 0, 0, 0));
oPen.SetColor(Color(nAlphaWhite, 255, 255, 255));
oMainRender->DrawLine(&oPen, m_arrPoints[2], m_arrPoints[3]);
oMainRender->DrawLine(&oPen, m_arrPoints[3], m_arrPoints[0]);
m_arrPoints[1].X--;
m_arrPoints[2].Y++;
m_arrPoints[3].X++;
m_arrPoints[0].Y--;
}
return TRUE;
}
BOOL Draw( BYTE* pPixels, int nWidth, int nHeight, int nStride, double dFrame, int nRow, int nCol, double dSideFactor, int nType )
{
double dAlpha = 255 * dFrame;
if( nStride < 0 )
pPixels -= (nHeight - 1) * nStride;
Gdiplus::Bitmap oImage( nWidth, nHeight, nStride, PixelFormat32bppARGB, pPixels );
if( !(Gdiplus::Ok == oImage.GetLastStatus()) )
{
return FALSE;
}
Gdiplus::Graphics oRender( &oImage );
oRender.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
oRender.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
oRender.SetInterpolationMode(Gdiplus::InterpolationModeBilinear);
if ( 0 <= nType && 1 >= nType)
{
double dFigWidth = nWidth / nCol;
double dFigHeight = nHeight / nRow;
if ( 0 == nType )
{
for (int nYIndex = 0, nIndex = 0; nYIndex < nRow; nYIndex ++ )
{
for ( int nXIndex = 0; nXIndex < nCol; nXIndex++, nIndex += 2 )
{
DrawPiece( &oRender, nXIndex * nWidth / nCol, nYIndex * nHeight / nRow, nWidth, nHeight, dAlpha, dFigWidth, dFigHeight, 0, 0, 0, 0);
}
}
}
else if ( 1 == nType )
{
if ( !m_pHorizontalFactor || !m_pVerticalFactor )
return FALSE;
for (int nYIndex = 0, nIndex = 0; nYIndex < nRow; nYIndex ++ )
{
for ( int nXIndex = 0; nXIndex < nCol; nXIndex++, nIndex += 2 )
{
DrawPiece( &oRender, nXIndex * nWidth / nCol, nYIndex * nHeight / nRow, nWidth, nHeight, dAlpha, dFigWidth, dFigHeight, m_pHorizontalFactor[nIndex], m_pVerticalFactor[nIndex + 1], m_pHorizontalFactor[nIndex + 1], m_pVerticalFactor[nIndex]);
}
}
}
}
else
{
SetCount(m_nFigureType, nWidth, nHeight);
int nFullWidth = 0;
int nFullHeight = 0;
dAlpha = dAlpha /256.0;
double dSide = m_dSide;
int nXCount = m_nXCount;
int nYCount = m_nYCount;
int nCount = m_nCount;
if ( 2 == m_nFigureType )
{
nFullWidth = int(3 * dSide);
nFullHeight = int(3 * dSide);
double dCurX = 0;
double dCurY = 0;
int nYLevel = 0;
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
int nYShift = int(sqrt(3.0) * dSide / 2);
if ( dCurX > nWidth + 2 * dSide )
{
if ( 0 == nYLevel )
dCurX = dSide * 1.5;
else
dCurX = 0;
dCurY += nYShift;
nYLevel++;
nYLevel = nYLevel % 2;
}
DrawHexagonBorder(&oRender, dCurX, dCurY, dAlpha);
dCurX += 3 * dSide;
}
}
else if ( 5 == m_nFigureType )
{
nFullWidth = int(dSide);
nFullHeight = int(dSide);
int nCurX = 0;
int nCurY = 0;
int nXLevel = 0;
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
if ( nCurX >= nXCount )
{
nCurX = 0;
nXLevel = 0;
nCurY++;
}
DrawTriangleBorder(&oRender, nCurX * dSide / 2, nCurY * sqrt(3.0) * 0.5 * dSide + nXLevel * sqrt(3.0) / 6 * dSide, dAlpha, 1 - nXLevel);
nCurX++;
nXLevel = (nXLevel + 1) % 2;
}
}
else if ( 3 == m_nFigureType )
{
nFullWidth = int(2 * dSide);
nFullHeight = int(2 * dSide);
double dRadius = dSide / sqrt(2.0); // ðàäèóñ îïèñàííîé îêðóæíîñòè
int nCurX = 0;
int nCurY = 0;
int nXLevel = 0;
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
if ( nCurX >= nXCount )
{
nCurX = 0;
nXLevel = 0;
nCurY++;
}
DrawRhombusBorder(&oRender, nCurX * dRadius, nCurY * 2*dRadius + nXLevel * dRadius, dAlpha);
nCurX++;
nXLevel = (nXLevel + 1) % 2;
}
}
else if ( 4 == m_nFigureType )
{
nFullWidth = int(dSide);
nFullHeight = int(dSide);
double dXShift = dSide;
double dYShift = dSide * (12.0 / 25.0);
int nCurX = 0;
int nCurY = 0;
int nYLevel = 0;
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
if ( nCurX >= nXCount )
{
nCurX = 0;
nYLevel = (nYLevel + 1) % 2;
nCurY++;
}
DrawBrickBorder(&oRender, nCurX * dXShift + nYLevel * dXShift / 2, nCurY * dYShift, dAlpha);
nCurX++;
}
}
else if ( 6 == m_nFigureType )
{
nFullWidth = int(2 * dSide);
nFullHeight = int(2 * dSide);
double dAngle = -IPP_PI4 + atan(25.0 / 24.0);
double dDiagonal = dSide * sqrt (1.0 / 4.0 + 144.0 / 625.0);
double dXShift = dDiagonal * cos(dAngle);
double dXYShift = dDiagonal * sin(dAngle);
int nCurX = 0;
int nCurY = 0;
int nYLevel = 0;
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
if ( nCurX >= nXCount )
{
nCurX = 0;
nYLevel = (nYLevel + 1) % 2;
nCurY++;
}
DrawInclinedBrickBorder(&oRender, nCurX * dXShift - nCurY * dXYShift, nCurY * dXShift - nCurX * dXYShift, dAlpha);
nCurX++;
}
}
}
return TRUE;
}
};
class OldPhoto : public ImageStudio::Caching::CCacheItemPointer
{
private:
class CLocker
{
private: CRITICAL_SECTION m_csThread;
public: CLocker()
{
InitializeCriticalSection(&m_csThread);
}
public: ~CLocker()
{
DeleteCriticalSection(&m_csThread);
}
public: void Lock()
{
EnterCriticalSection(&m_csThread);
}
public: void UnLock()
{
LeaveCriticalSection(&m_csThread);
}
};
static CLocker oLocker;
static CAtlArray<Gdiplus::Bitmap*>* GetMasks()
{
static CAtlArray<Gdiplus::Bitmap*> Masks;
return &Masks;
}
static int ChangeCounter(bool increase)
{
static int counter = 0;
if (increase)
counter++;
else
counter--;
return counter;
}
public:
OldPhoto()
{
}
virtual ~OldPhoto()
{
}
BOOL Draw( BYTE* pPixels, int nWidth, int nHeight, int nMask, int whiteBlack,bool vFlip )
{
oLocker.Lock();
if (GetMasks()->GetCount()<1)
return FALSE;
nMask = nMask%((int)GetMasks()->GetCount());
BYTE* pSourceImage = pPixels;
if (whiteBlack)
GrayscaleImage(pPixels, nWidth, nHeight, 1.0, 1.0);
CBuffer<BYTE> oBuffer(nWidth*nHeight*4);
if( oBuffer.IsEmpty() )
return FALSE;
BYTE* pBuffer = oBuffer.GetPtr();
// memcpy( pBuffer, pPixels, nWidth*nHeight*4 );
Gdiplus::Bitmap oImage( nWidth, nHeight, nWidth*4, PixelFormat32bppARGB, pBuffer );
if( Gdiplus::Ok != oImage.GetLastStatus() )
return FALSE;
Gdiplus::Graphics oRender( &oImage );
if( Gdiplus::Ok != oRender.GetLastStatus() )
return FALSE;
if (vFlip)
GetMasks()->GetAt(nMask)->RotateFlip(Gdiplus::RotateNoneFlipY);
oRender.SetInterpolationMode( InterpolationModeBilinear );
oRender.SetSmoothingMode( SmoothingModeAntiAlias );
oRender.DrawImage(GetMasks()->GetAt(nMask),0,0, nWidth, nHeight);
{
BYTE* pRow = pPixels;
BYTE* pRow2 = pBuffer;
for( int nRow = 0; nRow < nHeight; ++nRow, pRow += nWidth*4, pRow2 += nWidth*4)
{
BYTE* pPix = pRow;
BYTE* pPix2 = pRow2;
for( int nPos = 0; nPos < nWidth; ++nPos, pPix += 4, pPix2 += 4 )
{
for (int i=0;i<3;i++)
{
int blackLevelLow = ((int)pPix[i]);// + (int)pPix[1] +(int)pPix[2])/3;
int blackLevelUp = ((int)pPix2[i]);// + (int)pPix2[1] +(int)pPix2[2])/3;
if (blackLevelLow>127)
{
float tmp_val = ((float)(255-blackLevelLow))/127.0f;
float min_val = (float)(blackLevelLow- (255-blackLevelLow));
float res_val = ((float)blackLevelUp * tmp_val) + min_val;
/*pPix[0] = pPix[1] = */pPix[i] = (int)res_val;
}
else
{
float tmp_val = ((float)(blackLevelLow))/127.0f;
float res_val = ((float)blackLevelUp * tmp_val);
/*pPix[0] = pPix[1] = */pPix[i] = (int)res_val;
}
}
/*int alphaVal = int(255 - 1.2f*(float)blackLevel);
if (alphaVal<0)
pPix[3] = 0;
else
pPix[3] = alphaVal;*/
}
}
}
if (vFlip)
GetMasks()->GetAt(nMask)->RotateFlip(Gdiplus::RotateNoneFlipY);
//memcpy( pPixels, pBuffer, nWidth*nHeight*4 );
oLocker.UnLock();
return TRUE;
}
static void InitMasks(const CString& masksFolder)
{
if (GetMasks()->GetCount()>1)
{
ChangeCounter(true);
return;
}
WIN32_FIND_DATA FindData;
CString insideFilesMask = masksFolder+_T("*");
HANDLE hFindFiles=FindFirstFile(insideFilesMask,&FindData);
if (hFindFiles==INVALID_HANDLE_VALUE) return;
for(;;)
{
if ((_tcscmp(FindData.cFileName,_T("."))!=0) && (_tcscmp(FindData.cFileName,_T(".."))!=0))
{
if (!(FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
{
TCHAR *ptr=_tcsrchr(FindData.cFileName,_T('.'));
if (ptr)
{
if (_tcslen(ptr)==4)
{
if ((ptr[1]==_T('m') && ptr[2]==_T('s') && ptr[3]==_T('k')) ||
(ptr[1]==_T('M') && ptr[2]==_T('S') && ptr[3]==_T('K')))
{
CString sPath1=masksFolder;
sPath1+=FindData.cFileName;
BSTR bstrFilePath = sPath1.AllocSysString();
Gdiplus::Bitmap* newMask = new Gdiplus::Bitmap(bstrFilePath);
SysFreeString(bstrFilePath);
if (newMask && newMask->GetLastStatus() == Ok)
{
/*{
Gdiplus::BitmapData bitmap_data;
BYTE* mask_bits = NULL;
newMask->LockBits( NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat32bppARGB, &bitmap_data );
mask_bits = (BYTE*)bitmap_data.Scan0;
int nHeight = newMask->GetHeight();
int nWidth = newMask->GetWidth();
if (mask_bits)
{
BYTE* pRow = mask_bits;
for( int nRow = 0; nRow < nHeight; ++nRow, pRow += bitmap_data.Stride )
{
BYTE* pPixel = pRow;
for( int nPos = 0; nPos < nWidth; ++nPos, pPixel += 4 )
{
int blackLevel = ((int)pPixel[0] + (int)pPixel[1] +(int)pPixel[2])/3;
int alphaVal = int(255 - 1.2f*(float)blackLevel);
if (alphaVal<0)
pPixel[3] = 0;
else
pPixel[3] = alphaVal;
}
}
newMask->UnlockBits(&bitmap_data);
}
}*/
GetMasks()->Add(newMask);
}
}
}
}
}
}
if (!FindNextFile(hFindFiles,&FindData))
break;
}
FindClose(hFindFiles);
ChangeCounter(true);
}
static void FreeMasks()
{
if (ChangeCounter(false)==0)
{
for (size_t i=0;i<GetMasks()->GetCount();i++)
delete GetMasks()->GetAt(i);
GetMasks()->RemoveAll();
}
}
private:
BOOL GrayscaleImage( BYTE* pBGRASource, int nWidth, int nHeight,double dCompleteness, double dTime )
{
IppiSize ImageSize = {nWidth, nHeight};
Ipp8u* pIntensity = new Ipp8u[nWidth*nHeight];
Ipp8u* pBuffer = new Ipp8u[nWidth*nHeight*4];
Ipp32f coeffs[3];
Ipp8u* pSrc[4];
if (pBuffer && pIntensity)
{
coeffs[0] = 0.11f;
coeffs[1] = 0.59f;
coeffs[2] = 0.3f;
ippiColorToGray_8u_AC4C1R( pBGRASource , 4*nWidth, pIntensity, nWidth, ImageSize, coeffs);
// noise
/*if( true )
{
unsigned int nSeed = GetTickCount();
Ipp16s* psChanel = new Ipp16s[nWidth*nHeight];
ippiConvert_8u16s_C1R(pIntensity, nWidth, psChanel, sizeof(Ipp16s)*nWidth, ImageSize);
ippiAddRandUniform_Direct_16s_C1IR(psChanel, sizeof(Ipp16s)*nWidth, ImageSize, 0, Ipp16s(4 * dCompleteness), &nSeed);
ippiConvert_16s8u_C1R(psChanel, sizeof(Ipp16s)*nWidth, pIntensity, nWidth, ImageSize);
delete [] psChanel;
}
// ìåëêèå àðòåôàêòû
int count = rand() % 7 - 2;
for( int i = 0; i < count; i++)
{
int rnd = rand() % 6;
int size = 1 + rnd*rnd/4;
int x = rand() % (nWidth - size);
int y = rand() % (nHeight - size);
IppiSize CellSize = {size, size};
BYTE c = 0;
if( rand() % 2 )
{
ippiMin_8u_C1R( pIntensity + y * nWidth + x, nWidth, CellSize, &c);
c += 20;
}
else
{
ippiMax_8u_C1R( pIntensity + y * nWidth + x, nWidth, CellSize, &c);
c -= 20;
}
for( int j = size*size/2; j > 0; --j )
{
int xx = rand() % size;
int yy = rand() % size;
pIntensity[(y + yy)*nWidth + (x + xx)] = c;
}
}*/
// áëþð
if( true )
{
Ipp8u* pGauss = new Ipp8u[nWidth*nHeight];
IppiSize GaussSize = {nWidth - 4, nHeight - 4};
Ipp8u* pTempPtr = pIntensity + nWidth*2 + 2;
ippiFilterGauss_8u_C1R( pTempPtr, nWidth, pGauss, nWidth, GaussSize, ippMskSize5x5 );
ippiCopy_8u_C1R( pGauss, nWidth, pTempPtr, nWidth, GaussSize );
delete [] pGauss;
}
// êîïèðîâàíèå ÷¸ðíî-áåëîãî èçîáðàæåíèÿ
pSrc[0] = pIntensity;
pSrc[1] = pIntensity;
pSrc[2] = pIntensity;
pSrc[3] = pIntensity;
ippiCopy_8u_P4C4R(pSrc, nWidth, pBuffer, 4*nWidth, ImageSize);
int alpha = int((1 - dCompleteness) * 255);
if( alpha > 255 ) alpha = 255;
if( alpha < 0 ) alpha = 0;
ippiAlphaCompC_8u_AC4R( pBGRASource, 4*nWidth, Ipp8u(alpha), pBuffer, 4*nWidth, 255, pBGRASource, 4*nWidth, ImageSize, ippAlphaOver);
}
if (pBuffer)
delete[] pBuffer;
if (pIntensity)
delete[] pIntensity;
return TRUE;
}
/*Gdiplus::Bitmap* BitmapFromResource(HINSTANCE hInstance, LPCTSTR szResName, LPCTSTR szResType)
{
HRSRC hrsrc = FindResource(hInstance, szResName, szResType);
if(!hrsrc) return 0;
// "íåíàñòîÿùèé" HGLOBAL - ñì. îïèñàíèå LoadResource
HGLOBAL hgTemp = LoadResource(hInstance, hrsrc);
DWORD sz = SizeofResource(hInstance, hrsrc);
void* ptrRes = LockResource(hgTemp);
HGLOBAL hgRes = GlobalAlloc(GMEM_MOVEABLE, sz);
if(!hgRes) return 0;
void* ptrMem = GlobalLock(hgRes);
// Êîïèðóåì ðàñòðîâûå äàííûå
CopyMemory(ptrMem, ptrRes, sz);
GlobalUnlock(hgRes);
IStream *pStream;
// TRUE îçíà÷àåò îñâîáîäèòü ïàìÿòü ïðè ïîñëåäíåì Release
HRESULT hr = CreateStreamOnHGlobal(hgRes, TRUE, &pStream);
if(FAILED(hr))
{
GlobalFree(hgRes);
return 0;
}
// Èñïîëüçóåì çàãðóçêó èç IStream
Gdiplus::Bitmap *image = Gdiplus::Bitmap::FromStream(pStream);
pStream->Release();
return image;
}*/
};
OldPhoto::CLocker OldPhoto::oLocker;
class Particles : public ImageStudio::Caching::CCacheItemPointer
{
private:
struct TParticle
{
public:
double fTimePeriod;
double fTimeOffset;
DWORD nBaseRandom;
};
private:
CBuffer<TParticle> m_Particles;
int m_nCountParticles;
IMediaFrame* m_pSrcFrame;
int m_nSrcAlpha;
public:
double m_dDirBaseAngle; // óãîë íàïðàâëåíèÿ äâèæåíèÿ
double m_dDirDispAngle; // óãîë îòêëîíåíèÿ äâèæåíèÿ
double m_dMinSize; // áàçîâûé ìàñøòàá
double m_dMaxSize; // îòêëîíåíèå îò áàçîâîãî ìàñøòàáà
double m_dMinLifeTime; // ìèíèìàëüíîå âðåìÿ æèçíè ÷àñòèöû
double m_dMaxLifeTime; // ìàêñèìàëüíîå âðåìÿ æèçíè ÷àñòèöû
double m_dMinRotTime;
double m_dMaxRotTime;
double m_dMinRotAngle;
double m_dMaxRotAngle;
int m_nQuality; // êà÷åñòâî îòðèñîâêè
int m_nAbsRot;
int m_nRotType;
public:
Particles()
{
m_pSrcFrame = NULL;
m_nCountParticles = 0;
m_dDirBaseAngle = 0;
m_dDirDispAngle = 0;
m_dMinSize = 0;
m_dMaxSize = 0;
m_dMinLifeTime = 0;
m_dMaxLifeTime = 0;
m_nQuality = 0;
m_nAbsRot = 0;
m_nRotType = 0; //(0 - íåò âðàùåíèÿ, 1 - ïî ÷àñîâîé ñòðåëêå, 2 - ïðîòèâ ÷àñîâîé ñòðåëêè, 3 - è ïî è ïðîòèâ ÷àñîâîé ñòðåëêè, 4 - êà÷àíèå)
}
~Particles()
{
ReleaseSourceFrame();
}
BOOL SetSorceFrame( IMediaFrame* pFrame, int nAlpha )
{
ReleaseSourceFrame();
if( !pFrame || nAlpha <= 0 )
return FALSE;
pFrame->AddRef();
m_pSrcFrame = pFrame;
m_nSrcAlpha = min(nAlpha, 255);
return TRUE;
}
void ReleaseSourceFrame()
{
if( m_pSrcFrame )
{
m_pSrcFrame->Release();
m_pSrcFrame = NULL;
}
m_nSrcAlpha = 255;
}
BOOL CreateParticles( int nMaxCountParticles )
{
m_Particles.Release();
TParticle* pParticle = m_Particles.Create( nMaxCountParticles );
if( !pParticle )
return FALSE;
m_nCountParticles = nMaxCountParticles;
for( int i = 0; i < nMaxCountParticles; ++i, ++pParticle )
{
pParticle->fTimePeriod = Random( m_dMinLifeTime, m_dMaxLifeTime );
pParticle->fTimeOffset = pParticle->fTimePeriod * Random();
pParticle->nBaseRandom = ::rand();
}
return TRUE;
}
BOOL Draw( BYTE* pPixels, int nWidth, int nHeight, double dTime, double dCompleteness )
{
if( m_Particles.IsEmpty() )
return TRUE;
int nAlpha = int(m_nSrcAlpha * dCompleteness + 0.5);
if( nAlpha <= 0 )
return TRUE;
if( !m_pSrcFrame )
return TRUE;
long lSrcWidth; m_pSrcFrame->get_Width(&lSrcWidth);
long lSrcHeight; m_pSrcFrame->get_Height(&lSrcHeight);
BYTE* pSrcPixels; m_pSrcFrame->get_Buffer(&pSrcPixels);
if( lSrcWidth <= 0 || lSrcHeight <= 0 || !pSrcPixels )
return TRUE;
CBuffer<BYTE> oTmpBuffer;
if( nAlpha < 255 )
{
long lSrcSize = lSrcWidth * lSrcHeight;
if( !oTmpBuffer.Create( lSrcSize * 4 ) )
return FALSE;
DWORD alpha = DWORD(nAlpha) * 0x8081U;
BYTE* src = pSrcPixels;
BYTE* dst = oTmpBuffer.GetPtr();
for( int i = 0; i < lSrcSize; ++i, src += 4, dst += 4 )
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = BYTE((src[3] * alpha + 128 * 0x8081U) >> 23);
}
pSrcPixels = oTmpBuffer.GetPtr();
}
Gdiplus::Bitmap oSrcImage( lSrcWidth, lSrcHeight, lSrcWidth * 4, PixelFormat32bppARGB, pSrcPixels );
if( Gdiplus::Ok != oSrcImage.GetLastStatus() )
return FALSE;
// ïîäãîòîâêà ðåíäåðà
Gdiplus::Bitmap oDstImage( nWidth, nHeight, nWidth * 4, PixelFormat32bppARGB, pPixels );
if( Gdiplus::Ok != oDstImage.GetLastStatus() )
return FALSE;
Gdiplus::Graphics oRender( &oDstImage );
if( Gdiplus::Ok != oRender.GetLastStatus() )
return FALSE;
InterpolationMode mode;
switch( m_nQuality )
{
case 1: mode = Gdiplus::InterpolationModeBicubic; break;
case 2: mode = Gdiplus::InterpolationModeHighQualityBilinear; break;
case 3: mode = Gdiplus::InterpolationModeHighQualityBicubic; break;
default: mode = Gdiplus::InterpolationModeBilinear;
}
oRender.SetInterpolationMode( mode );
double dCenterX = nWidth / 2.0;
double dCenterY = nHeight / 2.0;
// ðàñ÷åò ïîëîæåíèÿ è îòðèñîâêà ÷àñòèöû
TParticle* pParticle = m_Particles.GetPtr();
double dSrcDiagonal = sqrt(double(lSrcWidth * lSrcWidth + lSrcHeight * lSrcHeight));
for( int i = 0; i < m_nCountParticles; ++i, ++pParticle )
{
if( pParticle->fTimePeriod < IPP_EPS23 )
continue;
double time = dTime + pParticle->fTimeOffset;
int period = int(time / pParticle->fTimePeriod);
time -= period * pParticle->fTimePeriod; // abs time
double t = time / pParticle->fTimePeriod; // (0 <= t <= 1)
CRandom oRnd( DWORD(period + pParticle->nBaseRandom) );
double dSize = oRnd.RandF( m_dMinSize, m_dMaxSize );
if( dSize < IPP_EPS23 )
dSize = lSrcWidth;
double dScale = dSize / lSrcWidth;
double dDirAngle = oRnd.RandF( m_dDirBaseAngle - m_dDirDispAngle, m_dDirBaseAngle + m_dDirDispAngle );
double dCos = cos( IPP_PI180 * dDirAngle );
double dSin = sin( IPP_PI180 * dDirAngle );
double dDstWidth = abs(nWidth * dCos) + abs(nHeight * dSin);
double dDstHeight = abs(nHeight * dCos) + abs(nWidth * dSin);
//double dDstScale = sqrt((dDstWidth * dDstHeight) / (nWidth * nHeight));
double dBorder = abs(dSrcDiagonal * dScale);
double dX = (oRnd.RandF() - 0.5) * dDstWidth;
double dY = (t - 0.5) * (dDstHeight + dBorder);
double x = (dX * dCos + dY * dSin) + nWidth / 2.0;
double y = (dY * dCos - dX * dSin) + nHeight / 2.0;
double w = lSrcWidth * dScale;
double h = lSrcHeight * dScale;
Gdiplus::RectF rect( float(x - (w - 1) / 2), float(y - (h - 1) / 2), float(w), float(h) );
if( m_nRotType > 0 && m_nRotType < 5 )
{
double dRotAngle = oRnd.RandF( m_dMinRotAngle, m_dMaxRotAngle );
double dRotTime = oRnd.RandF( m_dMinRotTime, m_dMaxRotTime );
if( dRotTime > IPP_EPS23 )
{
double dAng = (360 / dRotTime) * time;
switch( m_nRotType )
{
case 1: dRotAngle += dAng; break;
case 2: dRotAngle += -dAng; break;
case 3: dRotAngle += (oRnd.Rand( 2 ) > 0) ? dAng : -dAng; break;
case 4:
{
double dRotLength = abs(m_dMaxRotAngle - m_dMinRotAngle);
if( dRotLength > IPP_EPS23 )
{
dRotAngle -= m_dMinRotAngle;
dRotAngle += (oRnd.Rand( 2 ) > 0) ? dAng : -dAng;
dRotAngle -= 2 * dRotLength * floor( dRotAngle / (2 * dRotLength) );
if( dRotAngle > dRotLength )
{
dRotAngle = 2 * dRotLength - dRotAngle;
}
dRotAngle += m_dMinRotAngle;
}
}
}
}
if( !m_nAbsRot )
{
dRotAngle += dDirAngle;
}
Gdiplus::Matrix m(1, 0, 0, 1, 0, 0);
m.RotateAt( float(-dRotAngle), Gdiplus::PointF( float(x), float(y) ), Gdiplus::MatrixOrderAppend );
oRender.SetTransform( &m );
}
Gdiplus::Status status = oRender.DrawImage( &oSrcImage, rect );
}
return TRUE;
}
};
}
}
}