mirror of
https://github.com/reactos/reactos.git
synced 2025-06-06 01:40:36 +00:00
[SHIMGVW] Play gif animation (#934)
Make "Picture and Fax Viewer" able to play GIF animation. CORE-12680
This commit is contained in:
parent
efbebf983c
commit
375a78e706
1 changed files with 177 additions and 3 deletions
|
@ -9,6 +9,7 @@
|
|||
#define WIN32_NO_STATUS
|
||||
#define _INC_WINDOWS
|
||||
#define COM_NO_WINDOWS_H
|
||||
#define INITGUID
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
@ -31,7 +32,6 @@
|
|||
|
||||
#include "shimgvw.h"
|
||||
|
||||
|
||||
HINSTANCE hInstance;
|
||||
SHIMGVW_SETTINGS shiSettings;
|
||||
SHIMGVW_FILENODE *currentFile;
|
||||
|
@ -49,6 +49,137 @@ static const UINT ZoomSteps[] =
|
|||
10, 25, 50, 100, 200, 400, 800, 1600
|
||||
};
|
||||
|
||||
/* animation */
|
||||
UINT m_nFrameIndex = 0;
|
||||
UINT m_nFrameCount = 0;
|
||||
UINT m_nLoopIndex = 0;
|
||||
UINT m_nLoopCount = (UINT)-1;
|
||||
PropertyItem *m_pDelayItem = NULL;
|
||||
|
||||
#define ANIME_TIMER_ID 9999
|
||||
|
||||
static void Anime_FreeInfo(void)
|
||||
{
|
||||
if (m_pDelayItem)
|
||||
{
|
||||
free(m_pDelayItem);
|
||||
m_pDelayItem = NULL;
|
||||
}
|
||||
m_nFrameIndex = 0;
|
||||
m_nFrameCount = 0;
|
||||
m_nLoopIndex = 0;
|
||||
m_nLoopCount = (UINT)-1;
|
||||
}
|
||||
|
||||
static BOOL Anime_LoadInfo(void)
|
||||
{
|
||||
GUID *dims;
|
||||
UINT nDimCount = 0;
|
||||
UINT cbItem;
|
||||
UINT result;
|
||||
PropertyItem *pItem;
|
||||
|
||||
Anime_FreeInfo();
|
||||
KillTimer(hDispWnd, ANIME_TIMER_ID);
|
||||
|
||||
if (!image)
|
||||
return FALSE;
|
||||
|
||||
GdipImageGetFrameDimensionsCount(image, &nDimCount);
|
||||
if (nDimCount)
|
||||
{
|
||||
dims = (GUID *)calloc(nDimCount, sizeof(GUID));
|
||||
if (dims)
|
||||
{
|
||||
GdipImageGetFrameDimensionsList(image, dims, nDimCount);
|
||||
GdipImageGetFrameCount(image, dims, &result);
|
||||
m_nFrameCount = result;
|
||||
free(dims);
|
||||
}
|
||||
}
|
||||
|
||||
result = 0;
|
||||
GdipGetPropertyItemSize(image, PropertyTagFrameDelay, &result);
|
||||
cbItem = result;
|
||||
if (cbItem)
|
||||
{
|
||||
m_pDelayItem = (PropertyItem *)malloc(cbItem);
|
||||
GdipGetPropertyItem(image, PropertyTagFrameDelay, cbItem, m_pDelayItem);
|
||||
}
|
||||
|
||||
result = 0;
|
||||
GdipGetPropertyItemSize(image, PropertyTagLoopCount, &result);
|
||||
cbItem = result;
|
||||
if (cbItem)
|
||||
{
|
||||
pItem = (PropertyItem *)malloc(cbItem);
|
||||
if (pItem)
|
||||
{
|
||||
if (GdipGetPropertyItem(image, PropertyTagLoopCount, cbItem, pItem) == Ok)
|
||||
{
|
||||
m_nLoopCount = *(WORD *)pItem->value;
|
||||
}
|
||||
free(pItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pDelayItem)
|
||||
{
|
||||
SetTimer(hDispWnd, ANIME_TIMER_ID, 0, NULL);
|
||||
}
|
||||
|
||||
return m_pDelayItem != NULL;
|
||||
}
|
||||
|
||||
static void Anime_SetFrameIndex(UINT nFrameIndex)
|
||||
{
|
||||
if (nFrameIndex < m_nFrameCount)
|
||||
{
|
||||
GUID guid = FrameDimensionTime;
|
||||
if (Ok != GdipImageSelectActiveFrame(image, &guid, nFrameIndex))
|
||||
{
|
||||
guid = FrameDimensionPage;
|
||||
GdipImageSelectActiveFrame(image, &guid, nFrameIndex);
|
||||
}
|
||||
}
|
||||
m_nFrameIndex = nFrameIndex;
|
||||
}
|
||||
|
||||
DWORD Anime_GetFrameDelay(UINT nFrameIndex)
|
||||
{
|
||||
if (nFrameIndex < m_nFrameCount && m_pDelayItem)
|
||||
{
|
||||
return ((DWORD *)m_pDelayItem->value)[m_nFrameIndex] * 10;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL Anime_Step(DWORD *pdwDelay)
|
||||
{
|
||||
*pdwDelay = INFINITE;
|
||||
if (m_nLoopCount == (UINT)-1)
|
||||
return FALSE;
|
||||
|
||||
if (m_nFrameIndex + 1 < m_nFrameCount)
|
||||
{
|
||||
*pdwDelay = Anime_GetFrameDelay(m_nFrameIndex);
|
||||
Anime_SetFrameIndex(m_nFrameIndex);
|
||||
++m_nFrameIndex;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (m_nLoopCount == 0 || m_nLoopIndex < m_nLoopCount)
|
||||
{
|
||||
*pdwDelay = Anime_GetFrameDelay(m_nFrameIndex);
|
||||
Anime_SetFrameIndex(m_nFrameIndex);
|
||||
m_nFrameIndex = 0;
|
||||
++m_nLoopIndex;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ZoomInOrOut(BOOL bZoomIn)
|
||||
{
|
||||
INT i;
|
||||
|
@ -171,6 +302,7 @@ static void pLoadImage(LPWSTR szOpenFileName)
|
|||
DPRINT1("GdipLoadImageFromFile() failed\n");
|
||||
return;
|
||||
}
|
||||
Anime_LoadInfo();
|
||||
|
||||
/* reset zoom */
|
||||
ResetZoom();
|
||||
|
@ -257,10 +389,27 @@ static void pSaveImageAs(HWND hwnd)
|
|||
|
||||
if (GetSaveFileNameW(&sfn))
|
||||
{
|
||||
if (m_pDelayItem)
|
||||
{
|
||||
/* save animation */
|
||||
KillTimer(hDispWnd, ANIME_TIMER_ID);
|
||||
|
||||
DPRINT1("FIXME: save animation\n");
|
||||
if (GdipSaveImageToFile(image, szSaveFileName, &codecInfo[sfn.nFilterIndex - 1].Clsid, NULL) != Ok)
|
||||
{
|
||||
DPRINT1("GdipSaveImageToFile() failed\n");
|
||||
}
|
||||
|
||||
SetTimer(hDispWnd, ANIME_TIMER_ID, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save non-animation */
|
||||
if (GdipSaveImageToFile(image, szSaveFileName, &codecInfo[sfn.nFilterIndex - 1].Clsid, NULL) != Ok)
|
||||
{
|
||||
DPRINT1("GdipSaveImageToFile() failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(szFilterMask);
|
||||
|
@ -595,6 +744,19 @@ ImageView_CreateToolBar(HWND hwnd)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void ImageView_OnTimer(HWND hwnd)
|
||||
{
|
||||
DWORD dwDelay;
|
||||
|
||||
KillTimer(hwnd, ANIME_TIMER_ID);
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
|
||||
if (Anime_Step(&dwDelay))
|
||||
{
|
||||
SetTimer(hwnd, ANIME_TIMER_ID, dwDelay, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
ImageView_DispWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -605,6 +767,15 @@ ImageView_DispWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
|||
ImageView_DrawImage(hwnd);
|
||||
return 0L;
|
||||
}
|
||||
case WM_TIMER:
|
||||
{
|
||||
if (wParam == ANIME_TIMER_ID)
|
||||
{
|
||||
ImageView_OnTimer(hwnd);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return CallWindowProc(PrevProc, hwnd, Message, wParam, lParam);
|
||||
}
|
||||
|
@ -874,6 +1045,9 @@ ImageView_CreateWindow(HWND hwnd, LPWSTR szFileName)
|
|||
|
||||
if (image)
|
||||
GdipDisposeImage(image);
|
||||
|
||||
Anime_FreeInfo();
|
||||
|
||||
GdiplusShutdown(gdiplusToken);
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue