gdiplusを用いて画像特効---画像特効(スキャン、モザイク、ブラインド..)を作成
転載は引用と明記してくださいhttp://blog.csdn.net/chenyujing1234
皆さんの意見を歓迎して、一緒に討論します!
ソースコードが必要な場合は、単独で連絡してください.
画像表示の特効は、画像をいくつかの小さなブロックに細分化し、一定の順序で出力するプロセスです.
1、基本原理
(1)スキャン特効は、画像を複数行に分割し、1行の画像を表示するたびに、画像がすべて表示されるまで2回の表示間を遅延させることである.
スキャン特効は特効の中で最も簡単で、最も基本的な特効表示方式であり、表面は画像の琢行や琢列を表示し、カーテンを開けたり巻いたりするのに似ている.
(2)モザイク効果は,画像を大きさが等しいブロックに分割し,ランダムに表示することである.
(3)ブラインドの特効はストライプ状のブロックを分けることです.
(4)水平グリッドバー.水平イメージバーの場合、奇数偶数イメージバーの移動方向が逆になります.
......
2、プログラミング実現
ステップ1:メモリに画像を事前に描画します.
PreDrawImageはgdiplusgraphic方法で画像をメモリにロードする.
2番目: ビュー再描画関数OnDrawで特効を行います.
デュアルバッファ図面を使用します.まずShowPictureで画像を表示する(このような画像の画素はmemDC上にある)、EffectDisplayImageで特効をとる.
第三歩:特効関数の実現に重点を置く
ここでは、下向きスキャン、垂直二重スキャン、 モザイク特効の実現
皆さんの意見を歓迎して、一緒に討論します!
ソースコードが必要な場合は、単独で連絡してください.
画像表示の特効は、画像をいくつかの小さなブロックに細分化し、一定の順序で出力するプロセスです.
1、基本原理
(1)スキャン特効は、画像を複数行に分割し、1行の画像を表示するたびに、画像がすべて表示されるまで2回の表示間を遅延させることである.
スキャン特効は特効の中で最も簡単で、最も基本的な特効表示方式であり、表面は画像の琢行や琢列を表示し、カーテンを開けたり巻いたりするのに似ている.
(2)モザイク効果は,画像を大きさが等しいブロックに分割し,ランダムに表示することである.
(3)ブラインドの特効はストライプ状のブロックを分けることです.
(4)水平グリッドバー.水平イメージバーの場合、奇数偶数イメージバーの移動方向が逆になります.
......
2、プログラミング実現
ステップ1:メモリに画像を事前に描画します.
PreDrawImageはgdiplusgraphic方法で画像をメモリにロードする.
//--------------------------------------------------------------
// :
//--------------------------------------------------------------
void CMagicHouseView::PreDrawImage(void)
{
Image image(GetFilePath(m_nPos));
::delete m_pBitmap;
m_pBitmap = ::new Bitmap(image.GetWidth(), image.GetHeight(), PixelFormat32bppARGB);
Graphics* graph = Graphics::FromImage(m_pBitmap);
graph->DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());
SAFE_DELETE (graph);
}
2番目: ビュー再描画関数OnDrawで特効を行います.
デュアルバッファ図面を使用します.まずShowPictureで画像を表示する(このような画像の画素はmemDC上にある)、EffectDisplayImageで特効をとる.
//--------------------------------------------------------------
// :
//--------------------------------------------------------------
void CMagicHouseView::OnDraw(CDC* pDC)
{
CMagicHouseDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CRect rect;
GetClientRect(rect);
CDC memDC;
CBitmap MemBitmap;
//
memDC.CreateCompatibleDC(NULL);
//
MemBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
//
memDC.SelectObject(MemBitmap);
memDC.FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(255,255,255));
//
// memDC , memDC
if (m_nPos >= 0)
ShowPicture(&memDC, *m_pBitmap, m_nShowType);
if (m_bEffectDraw && m_nEffectDisplayType != EDT_NONE)
{
int nHeight = rect.Height() - m_nShowPicHeight;
int nWidth = rect.Width() - m_nShowPicWidth;
if (nHeight < 0)
nHeight = 0;
if (nWidth < 0)
nWidth = 0;
pDC->FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(255,255,255));
EffectDisplay::s_nOffsetX = nWidth / 2;
EffectDisplay::s_nOffsetY = nHeight / 2;
EffectDisplay::s_nPicWidth = m_nShowPicWidth;
EffectDisplay::s_nPicHeight = m_nShowPicHeight;
EffectDisplay::s_nCDCWidth = rect.Width();
EffectDisplay::s_nCDCHeight = rect.Height();
// , memDC , pDC
EffectDisplayImage(pDC, &memDC);
m_bEffectDraw = false;
}
else
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
MemBitmap.DeleteObject();
memDC.DeleteDC();
}
//----------------------------------
// :
// :
// pDC
// image
// nShowType
//----------------------------------
void CMagicHouseView::ShowPicture(CDC* pDC, Image& image, int nShowType)
{
Graphics graph(pDC->GetSafeHdc());
CRect winRect;
GetClientRect(winRect);
REAL x = 0.0;
REAL y = 0.0;
CSize showPicSize = GetShowPicSize(image, m_nShowType);
REAL width = (REAL)showPicSize.cx;
REAL height = (REAL)showPicSize.cy;
//
if ((UINT)winRect.Width() > width)
x = (winRect.Width() - width) / 2.0f;
if ( (UINT)winRect.Height() > height )
y = ((UINT)winRect.Height() - height) / 2.0f;
if (m_bWidhtOut)
x += m_nXX;
if (m_bHeightOut)
y += m_nYY;
m_nShowPicHeight = (int)height;
m_nShowPicWidth = (int)width;
// gdiplusgraphics
graph.DrawImage(&image, x, y, width, height);
}
第三歩:特効関数の実現に重点を置く
//
enum EffectDislayType
{
EDT_SCANDOWN = 0, //
EDT_VSCAN, //
EDT_MOVERIGHT, //
EDT_HSMOVE, //
EDT_VBLIND, //
EDT_HBLIND, //
EDT_VRASTER, //
EDT_HRASTER, //
EDT_MOSAIC, //
EDT_RAINDROP, //
EDT_NONE, //
EDT_RAND //
};
//--------------------------------------------------------------
// :
// :
// pDC
// pMemDC
// :
//--------------------------------------------------------------
void CMagicHouseView::EffectDisplayImage(CDC* pDC, CDC* pMemDC)
{
int nType = m_nEffectDisplayType;
if (nType == EDT_RAND)
{
LARGE_INTEGER seed;
QueryPerformanceFrequency(&seed);
QueryPerformanceCounter(&seed);
//
srand((int)seed.QuadPart);
nType = rand() % 10;
}
switch (nType)
{
case EDT_SCANDOWN:
EffectDisplay::ScanDownDisplay(pDC, pMemDC);
break;
case EDT_VSCAN:
EffectDisplay::VSScanDisplay(pDC, pMemDC);
break;
case EDT_MOVERIGHT:
EffectDisplay::MoveRightDisplay(pDC, pMemDC);
break;
case EDT_HSMOVE:
EffectDisplay::HSMoveDisplay(pDC, pMemDC);
break;
case EDT_VBLIND:
EffectDisplay::VBlindDisplay(pDC, pMemDC);
break;
case EDT_HBLIND:
EffectDisplay::HBlindDisplay(pDC, pMemDC);
break;
case EDT_VRASTER:
EffectDisplay::VRasterDisplay(pDC, pMemDC);
break;
case EDT_HRASTER:
EffectDisplay::HRasterDisplay(pDC, pMemDC);
break;
case EDT_MOSAIC:
EffectDisplay::MosaicDisplay(pDC, pMemDC);
break;
default:
EffectDisplay::RaindropDisplay(pDC, pMemDC);
}
}
ここでは、下向きスキャン、垂直二重スキャン、 モザイク特効の実現
//--------------------------------------------
// :
//--------------------------------------------
void EffectDisplay::ScanDownDisplay(CDC* pDC, CDC* pMemDC)
{
//
int nHeight = min(s_nPicHeight, s_nCDCHeight);
//
int nWidth = min(s_nPicWidth, s_nCDCWidth);
for (int i = 0; i <= nHeight; i += 1)
{
pDC->BitBlt(s_nOffsetX, i + s_nOffsetY, nWidth, 1,
pMemDC, s_nOffsetX, i + s_nOffsetY, SRCCOPY);
DelayTime(1);
}
}
//--------------------------------------------
// :
//--------------------------------------------
void EffectDisplay::VSScanDisplay(CDC* pDC, CDC* pMemDC)
{
//
int nHeight = min(s_nPicHeight, s_nCDCHeight);
//
int nWidth = min(s_nPicWidth, s_nCDCWidth);
for (int i = 0; i <= nHeight / 2; i += 1)
{
//
pDC->BitBlt(s_nOffsetX, i + s_nOffsetY, nWidth, 1,
pMemDC, s_nOffsetX, i + s_nOffsetY, SRCCOPY);
//
pDC->BitBlt(s_nOffsetX, nHeight - i + s_nOffsetY, nWidth, 1,
pMemDC, s_nOffsetX, nHeight - i + s_nOffsetY, SRCCOPY);
DelayTime(2);
}
}
//--------------------------------------------
// :
//--------------------------------------------
void EffectDisplay::MosaicDisplay(CDC* pDC, CDC* pMemDC)
{
int nTileSize = 24; //
int nRw = 0;
int nRh = 0;
if (s_nPicWidth % nTileSize != 0)
nRw = 1;
if (s_nPicHeight % nTileSize != 0)
nRh = 1;
//
int nTileCount = (s_nPicWidth / nTileSize + nRw) * (s_nPicHeight / nTileSize + nRh);
CPtrArray points; //
long lx = 0;
long ly = 0;
for (int k = 0; k < nTileCount; k++)
{
CPoint* point = new CPoint;
point->x = lx;
point->y = ly;
lx = lx + nTileSize;
if (lx >= s_nPicWidth)
{
lx = 0;
ly = ly + nTileSize;
}
points.Add(point);
}
int nDelayTime = 2;
if (s_nPicHeight * s_nPicWidth > 600 * 500)
nDelayTime = 1;
LARGE_INTEGER seed;
QueryPerformanceFrequency(&seed);
QueryPerformanceCounter(&seed);
//
srand((int)seed.QuadPart);
for (int i = nTileCount - 1; i >= 0; i--)
{
int n = rand() % (i + 1);
CPoint* point = (CPoint*)points[n];
lx = point->x;
ly = point->y;
pDC->BitBlt(lx + s_nOffsetX, ly + s_nOffsetY, nTileSize, nTileSize,
pMemDC, lx + s_nOffsetX, ly + s_nOffsetY, SRCCOPY);
SAFE_DELETE (point);
points.RemoveAt(n);
DelayTime(nDelayTime);
}
}
//--------------------------------------------
// :
//--------------------------------------------
void EffectDisplay::RaindropDisplay(CDC* pDC, CDC* pMemDC)
{
//
int nHeight = min(s_nPicHeight, s_nCDCHeight);
//
int nWidth = min(s_nPicWidth, s_nCDCWidth);
for (int i = 0; i <= nHeight + s_nOffsetY; i++)
{
for (int j = 0; j <= nHeight + s_nOffsetY - i; j++)
{
pDC->BitBlt(s_nOffsetX, j, nWidth, 1,
pMemDC, s_nOffsetX, nHeight + s_nOffsetY - i, SRCCOPY);
}
DelayTime(1);
}
}