| Index: third_party/libpng/contrib/visupng/VisualPng.c
|
| diff --git a/third_party/libpng/contrib/visupng/VisualPng.c b/third_party/libpng/contrib/visupng/VisualPng.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..236525a59fef1f19cd9a6e78b751081275042708
|
| --- /dev/null
|
| +++ b/third_party/libpng/contrib/visupng/VisualPng.c
|
| @@ -0,0 +1,970 @@
|
| +/*------------------------------------
|
| + * VisualPng.C -- Shows a PNG image
|
| + *------------------------------------
|
| + *
|
| + * Copyright 2000, Willem van Schaik.
|
| + *
|
| + * This code is released under the libpng license.
|
| + * For conditions of distribution and use, see the disclaimer
|
| + * and license in png.h
|
| + */
|
| +
|
| +/* switches */
|
| +
|
| +/* defines */
|
| +
|
| +#define PROGNAME "VisualPng"
|
| +#define LONGNAME "Win32 Viewer for PNG-files"
|
| +#define VERSION "1.0 of 2000 June 07"
|
| +
|
| +/* constants */
|
| +
|
| +#define MARGIN 8
|
| +
|
| +/* standard includes */
|
| +
|
| +#include <stdio.h>
|
| +#include <stdlib.h>
|
| +#include <string.h>
|
| +#include <windows.h>
|
| +#include <zlib.h>
|
| +
|
| +/* application includes */
|
| +
|
| +#include "png.h"
|
| +#include "pngfile.h"
|
| +#include "resource.h"
|
| +
|
| +/* macros */
|
| +
|
| +/* function prototypes */
|
| +
|
| +LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
|
| +BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
|
| +
|
| +BOOL CenterAbout (HWND hwndChild, HWND hwndParent);
|
| +
|
| +BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
|
| + int *pFileIndex);
|
| +
|
| +BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex,
|
| + PTSTR pstrPrevName, PTSTR pstrNextName);
|
| +
|
| +BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName,
|
| + png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels,
|
| + png_color *pBkgColor);
|
| +
|
| +BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
|
| + BYTE **ppDiData, int cxWinSize, int cyWinSize,
|
| + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
|
| + BOOL bStretched);
|
| +
|
| +BOOL InitBitmap (
|
| + BYTE *pDiData, int cxWinSize, int cyWinSize);
|
| +
|
| +BOOL FillBitmap (
|
| + BYTE *pDiData, int cxWinSize, int cyWinSize,
|
| + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
|
| + BOOL bStretched);
|
| +
|
| +/* a few global variables */
|
| +
|
| +static char *szProgName = PROGNAME;
|
| +static char *szAppName = LONGNAME;
|
| +static char *szIconName = PROGNAME;
|
| +static char szCmdFileName [MAX_PATH];
|
| +
|
| +/* MAIN routine */
|
| +
|
| +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
| + PSTR szCmdLine, int iCmdShow)
|
| +{
|
| + HACCEL hAccel;
|
| + HWND hwnd;
|
| + MSG msg;
|
| + WNDCLASS wndclass;
|
| + int ixBorders, iyBorders;
|
| +
|
| + wndclass.style = CS_HREDRAW | CS_VREDRAW;
|
| + wndclass.lpfnWndProc = WndProc;
|
| + wndclass.cbClsExtra = 0;
|
| + wndclass.cbWndExtra = 0;
|
| + wndclass.hInstance = hInstance;
|
| + wndclass.hIcon = LoadIcon (hInstance, szIconName) ;
|
| + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
|
| + wndclass.hbrBackground = NULL; /* (HBRUSH) GetStockObject (GRAY_BRUSH); */
|
| + wndclass.lpszMenuName = szProgName;
|
| + wndclass.lpszClassName = szProgName;
|
| +
|
| + if (!RegisterClass (&wndclass))
|
| + {
|
| + MessageBox (NULL, TEXT ("Error: this program requires Windows NT!"),
|
| + szProgName, MB_ICONERROR);
|
| + return 0;
|
| + }
|
| +
|
| + /* if filename given on commandline, store it */
|
| + if ((szCmdLine != NULL) && (*szCmdLine != '\0'))
|
| + if (szCmdLine[0] == '"')
|
| + strncpy (szCmdFileName, szCmdLine + 1, strlen(szCmdLine) - 2);
|
| + else
|
| + strcpy (szCmdFileName, szCmdLine);
|
| + else
|
| + strcpy (szCmdFileName, "");
|
| +
|
| + /* calculate size of window-borders */
|
| + ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) +
|
| + GetSystemMetrics (SM_CXDLGFRAME));
|
| + iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) +
|
| + GetSystemMetrics (SM_CYDLGFRAME)) +
|
| + GetSystemMetrics (SM_CYCAPTION) +
|
| + GetSystemMetrics (SM_CYMENUSIZE) +
|
| + 1; /* WvS: don't ask me why? */
|
| +
|
| + hwnd = CreateWindow (szProgName, szAppName,
|
| + WS_OVERLAPPEDWINDOW,
|
| + CW_USEDEFAULT, CW_USEDEFAULT,
|
| + 512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders,
|
| +/* CW_USEDEFAULT, CW_USEDEFAULT, */
|
| + NULL, NULL, hInstance, NULL);
|
| +
|
| + ShowWindow (hwnd, iCmdShow);
|
| + UpdateWindow (hwnd);
|
| +
|
| + hAccel = LoadAccelerators (hInstance, szProgName);
|
| +
|
| + while (GetMessage (&msg, NULL, 0, 0))
|
| + {
|
| + if (!TranslateAccelerator (hwnd, hAccel, &msg))
|
| + {
|
| + TranslateMessage (&msg);
|
| + DispatchMessage (&msg);
|
| + }
|
| + }
|
| + return msg.wParam;
|
| +}
|
| +
|
| +LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
|
| + LPARAM lParam)
|
| +{
|
| + static HINSTANCE hInstance ;
|
| + static HDC hdc;
|
| + static PAINTSTRUCT ps;
|
| + static HMENU hMenu;
|
| +
|
| + static BITMAPFILEHEADER *pbmfh;
|
| + static BITMAPINFOHEADER *pbmih;
|
| + static BYTE *pbImage;
|
| + static int cxWinSize, cyWinSize;
|
| + static int cxImgSize, cyImgSize;
|
| + static int cImgChannels;
|
| + static png_color bkgColor = {127, 127, 127};
|
| +
|
| + static BOOL bStretched = TRUE;
|
| +
|
| + static BYTE *pDib = NULL;
|
| + static BYTE *pDiData = NULL;
|
| +
|
| + static TCHAR szImgPathName [MAX_PATH];
|
| + static TCHAR szTitleName [MAX_PATH];
|
| +
|
| + static TCHAR *pPngFileList = NULL;
|
| + static int iPngFileCount;
|
| + static int iPngFileIndex;
|
| +
|
| + BOOL bOk;
|
| +
|
| + switch (message)
|
| + {
|
| + case WM_CREATE:
|
| + hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
|
| + PngFileInitialize (hwnd);
|
| +
|
| + strcpy (szImgPathName, "");
|
| +
|
| + /* in case we process file given on command-line */
|
| +
|
| + if (szCmdFileName[0] != '\0')
|
| + {
|
| + strcpy (szImgPathName, szCmdFileName);
|
| +
|
| + /* read the other png-files in the directory for later */
|
| + /* next/previous commands */
|
| +
|
| + BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
|
| + &iPngFileIndex);
|
| +
|
| + /* load the image from file */
|
| +
|
| + if (!LoadImageFile (hwnd, szImgPathName,
|
| + &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
|
| + return 0;
|
| +
|
| + /* invalidate the client area for later update */
|
| +
|
| + InvalidateRect (hwnd, NULL, TRUE);
|
| +
|
| + /* display the PNG into the DIBitmap */
|
| +
|
| + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
|
| + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
|
| + }
|
| +
|
| + return 0;
|
| +
|
| + case WM_SIZE:
|
| + cxWinSize = LOWORD (lParam);
|
| + cyWinSize = HIWORD (lParam);
|
| +
|
| + /* invalidate the client area for later update */
|
| +
|
| + InvalidateRect (hwnd, NULL, TRUE);
|
| +
|
| + /* display the PNG into the DIBitmap */
|
| +
|
| + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
|
| + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
|
| +
|
| + return 0;
|
| +
|
| + case WM_INITMENUPOPUP:
|
| + hMenu = GetMenu (hwnd);
|
| +
|
| + if (pbImage)
|
| + EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_ENABLED);
|
| + else
|
| + EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_GRAYED);
|
| +
|
| + return 0;
|
| +
|
| + case WM_COMMAND:
|
| + hMenu = GetMenu (hwnd);
|
| +
|
| + switch (LOWORD (wParam))
|
| + {
|
| + case IDM_FILE_OPEN:
|
| +
|
| + /* show the File Open dialog box */
|
| +
|
| + if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName))
|
| + return 0;
|
| +
|
| + /* read the other png-files in the directory for later */
|
| + /* next/previous commands */
|
| +
|
| + BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
|
| + &iPngFileIndex);
|
| +
|
| + /* load the image from file */
|
| +
|
| + if (!LoadImageFile (hwnd, szImgPathName,
|
| + &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
|
| + return 0;
|
| +
|
| + /* invalidate the client area for later update */
|
| +
|
| + InvalidateRect (hwnd, NULL, TRUE);
|
| +
|
| + /* display the PNG into the DIBitmap */
|
| +
|
| + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
|
| + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
|
| +
|
| + return 0;
|
| +
|
| + case IDM_FILE_SAVE:
|
| +
|
| + /* show the File Save dialog box */
|
| +
|
| + if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName))
|
| + return 0;
|
| +
|
| + /* save the PNG to a disk file */
|
| +
|
| + SetCursor (LoadCursor (NULL, IDC_WAIT));
|
| + ShowCursor (TRUE);
|
| +
|
| + bOk = PngSaveImage (szImgPathName, pDiData, cxWinSize, cyWinSize,
|
| + bkgColor);
|
| +
|
| + ShowCursor (FALSE);
|
| + SetCursor (LoadCursor (NULL, IDC_ARROW));
|
| +
|
| + if (!bOk)
|
| + MessageBox (hwnd, TEXT ("Error in saving the PNG image"),
|
| + szProgName, MB_ICONEXCLAMATION | MB_OK);
|
| + return 0;
|
| +
|
| + case IDM_FILE_NEXT:
|
| +
|
| + /* read next entry in the directory */
|
| +
|
| + if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
|
| + NULL, szImgPathName))
|
| + {
|
| + if (strcmp (szImgPathName, "") == 0)
|
| + return 0;
|
| +
|
| + /* load the image from file */
|
| +
|
| + if (!LoadImageFile (hwnd, szImgPathName, &pbImage,
|
| + &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
|
| + return 0;
|
| +
|
| + /* invalidate the client area for later update */
|
| +
|
| + InvalidateRect (hwnd, NULL, TRUE);
|
| +
|
| + /* display the PNG into the DIBitmap */
|
| +
|
| + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
|
| + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
|
| + }
|
| +
|
| + return 0;
|
| +
|
| + case IDM_FILE_PREVIOUS:
|
| +
|
| + /* read previous entry in the directory */
|
| +
|
| + if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
|
| + szImgPathName, NULL))
|
| + {
|
| +
|
| + if (strcmp (szImgPathName, "") == 0)
|
| + return 0;
|
| +
|
| + /* load the image from file */
|
| +
|
| + if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize,
|
| + &cyImgSize, &cImgChannels, &bkgColor))
|
| + return 0;
|
| +
|
| + /* invalidate the client area for later update */
|
| +
|
| + InvalidateRect (hwnd, NULL, TRUE);
|
| +
|
| + /* display the PNG into the DIBitmap */
|
| +
|
| + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
|
| + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
|
| + }
|
| +
|
| + return 0;
|
| +
|
| + case IDM_FILE_EXIT:
|
| +
|
| + /* more cleanup needed... */
|
| +
|
| + /* free image buffer */
|
| +
|
| + if (pDib != NULL)
|
| + {
|
| + free (pDib);
|
| + pDib = NULL;
|
| + }
|
| +
|
| + /* free file-list */
|
| +
|
| + if (pPngFileList != NULL)
|
| + {
|
| + free (pPngFileList);
|
| + pPngFileList = NULL;
|
| + }
|
| +
|
| + /* let's go ... */
|
| +
|
| + exit (0);
|
| +
|
| + return 0;
|
| +
|
| + case IDM_OPTIONS_STRETCH:
|
| + bStretched = !bStretched;
|
| + if (bStretched)
|
| + CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_CHECKED);
|
| + else
|
| + CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED);
|
| +
|
| + /* invalidate the client area for later update */
|
| +
|
| + InvalidateRect (hwnd, NULL, TRUE);
|
| +
|
| + /* display the PNG into the DIBitmap */
|
| +
|
| + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
|
| + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
|
| +
|
| + return 0;
|
| +
|
| + case IDM_HELP_ABOUT:
|
| + DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ;
|
| + return 0;
|
| +
|
| + } /* end switch */
|
| +
|
| + break;
|
| +
|
| + case WM_PAINT:
|
| + hdc = BeginPaint (hwnd, &ps);
|
| +
|
| + if (pDib)
|
| + SetDIBitsToDevice (hdc, 0, 0, cxWinSize, cyWinSize, 0, 0,
|
| + 0, cyWinSize, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS);
|
| +
|
| + EndPaint (hwnd, &ps);
|
| + return 0;
|
| +
|
| + case WM_DESTROY:
|
| + if (pbmfh)
|
| + {
|
| + free (pbmfh);
|
| + pbmfh = NULL;
|
| + }
|
| +
|
| + PostQuitMessage (0);
|
| + return 0;
|
| + }
|
| +
|
| + return DefWindowProc (hwnd, message, wParam, lParam);
|
| +}
|
| +
|
| +BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,
|
| + WPARAM wParam, LPARAM lParam)
|
| +{
|
| + switch (message)
|
| + {
|
| + case WM_INITDIALOG :
|
| + ShowWindow (hDlg, SW_HIDE);
|
| + CenterAbout (hDlg, GetWindow (hDlg, GW_OWNER));
|
| + ShowWindow (hDlg, SW_SHOW);
|
| + return TRUE ;
|
| +
|
| + case WM_COMMAND :
|
| + switch (LOWORD (wParam))
|
| + {
|
| + case IDOK :
|
| + case IDCANCEL :
|
| + EndDialog (hDlg, 0) ;
|
| + return TRUE ;
|
| + }
|
| + break ;
|
| + }
|
| + return FALSE ;
|
| +}
|
| +
|
| +/*---------------
|
| + * CenterAbout
|
| + *---------------
|
| + */
|
| +BOOL CenterAbout (HWND hwndChild, HWND hwndParent)
|
| +{
|
| + RECT rChild, rParent, rWorkArea;
|
| + int wChild, hChild, wParent, hParent;
|
| + int xNew, yNew;
|
| + BOOL bResult;
|
| +
|
| + /* Get the Height and Width of the child window */
|
| + GetWindowRect (hwndChild, &rChild);
|
| + wChild = rChild.right - rChild.left;
|
| + hChild = rChild.bottom - rChild.top;
|
| +
|
| + /* Get the Height and Width of the parent window */
|
| + GetWindowRect (hwndParent, &rParent);
|
| + wParent = rParent.right - rParent.left;
|
| + hParent = rParent.bottom - rParent.top;
|
| +
|
| + /* Get the limits of the 'workarea' */
|
| + bResult = SystemParametersInfo(
|
| + SPI_GETWORKAREA, /* system parameter to query or set */
|
| + sizeof(RECT),
|
| + &rWorkArea,
|
| + 0);
|
| + if (!bResult) {
|
| + rWorkArea.left = rWorkArea.top = 0;
|
| + rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
|
| + rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
|
| + }
|
| +
|
| + /* Calculate new X position, then adjust for workarea */
|
| + xNew = rParent.left + ((wParent - wChild) /2);
|
| + if (xNew < rWorkArea.left) {
|
| + xNew = rWorkArea.left;
|
| + } else if ((xNew+wChild) > rWorkArea.right) {
|
| + xNew = rWorkArea.right - wChild;
|
| + }
|
| +
|
| + /* Calculate new Y position, then adjust for workarea */
|
| + yNew = rParent.top + ((hParent - hChild) /2);
|
| + if (yNew < rWorkArea.top) {
|
| + yNew = rWorkArea.top;
|
| + } else if ((yNew+hChild) > rWorkArea.bottom) {
|
| + yNew = rWorkArea.bottom - hChild;
|
| + }
|
| +
|
| + /* Set it, and return */
|
| + return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE |
|
| + SWP_NOZORDER);
|
| +}
|
| +
|
| +/*----------------
|
| + * BuildPngList
|
| + *----------------
|
| + */
|
| +BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
|
| + int *pFileIndex)
|
| +{
|
| + static TCHAR szImgPathName [MAX_PATH];
|
| + static TCHAR szImgFileName [MAX_PATH];
|
| + static TCHAR szImgFindName [MAX_PATH];
|
| +
|
| + WIN32_FIND_DATA finddata;
|
| + HANDLE hFind;
|
| +
|
| + static TCHAR szTmp [MAX_PATH];
|
| + BOOL bOk;
|
| + int i, ii;
|
| + int j, jj;
|
| +
|
| + /* free previous file-list */
|
| +
|
| + if (*ppFileList != NULL)
|
| + {
|
| + free (*ppFileList);
|
| + *ppFileList = NULL;
|
| + }
|
| +
|
| + /* extract foldername, filename and search-name */
|
| +
|
| + strcpy (szImgPathName, pstrPathName);
|
| + strcpy (szImgFileName, strrchr (pstrPathName, '\\') + 1);
|
| +
|
| + strcpy (szImgFindName, szImgPathName);
|
| + *(strrchr (szImgFindName, '\\') + 1) = '\0';
|
| + strcat (szImgFindName, "*.png");
|
| +
|
| + /* first cycle: count number of files in directory for memory allocation */
|
| +
|
| + *pFileCount = 0;
|
| +
|
| + hFind = FindFirstFile(szImgFindName, &finddata);
|
| + bOk = (hFind != (HANDLE) -1);
|
| +
|
| + while (bOk)
|
| + {
|
| + *pFileCount += 1;
|
| + bOk = FindNextFile(hFind, &finddata);
|
| + }
|
| + FindClose(hFind);
|
| +
|
| + /* allocation memory for file-list */
|
| +
|
| + *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH);
|
| +
|
| + /* second cycle: read directory and store filenames in file-list */
|
| +
|
| + hFind = FindFirstFile(szImgFindName, &finddata);
|
| + bOk = (hFind != (HANDLE) -1);
|
| +
|
| + i = 0;
|
| + ii = 0;
|
| + while (bOk)
|
| + {
|
| + strcpy (*ppFileList + ii, szImgPathName);
|
| + strcpy (strrchr(*ppFileList + ii, '\\') + 1, finddata.cFileName);
|
| +
|
| + if (strcmp(pstrPathName, *ppFileList + ii) == 0)
|
| + *pFileIndex = i;
|
| +
|
| + ii += MAX_PATH;
|
| + i++;
|
| +
|
| + bOk = FindNextFile(hFind, &finddata);
|
| + }
|
| + FindClose(hFind);
|
| +
|
| + /* finally we must sort the file-list */
|
| +
|
| + for (i = 0; i < *pFileCount - 1; i++)
|
| + {
|
| + ii = i * MAX_PATH;
|
| + for (j = i+1; j < *pFileCount; j++)
|
| + {
|
| + jj = j * MAX_PATH;
|
| + if (strcmp (*ppFileList + ii, *ppFileList + jj) > 0)
|
| + {
|
| + strcpy (szTmp, *ppFileList + jj);
|
| + strcpy (*ppFileList + jj, *ppFileList + ii);
|
| + strcpy (*ppFileList + ii, szTmp);
|
| +
|
| + /* check if this was the current image that we moved */
|
| +
|
| + if (*pFileIndex == i)
|
| + *pFileIndex = j;
|
| + else
|
| + if (*pFileIndex == j)
|
| + *pFileIndex = i;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return TRUE;
|
| +}
|
| +
|
| +/*----------------
|
| + * SearchPngList
|
| + *----------------
|
| + */
|
| +
|
| +BOOL SearchPngList (
|
| + TCHAR *pFileList, int FileCount, int *pFileIndex,
|
| + PTSTR pstrPrevName, PTSTR pstrNextName)
|
| +{
|
| + if (FileCount > 0)
|
| + {
|
| + /* get previous entry */
|
| +
|
| + if (pstrPrevName != NULL)
|
| + {
|
| + if (*pFileIndex > 0)
|
| + *pFileIndex -= 1;
|
| + else
|
| + *pFileIndex = FileCount - 1;
|
| +
|
| + strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH));
|
| + }
|
| +
|
| + /* get next entry */
|
| +
|
| + if (pstrNextName != NULL)
|
| + {
|
| + if (*pFileIndex < FileCount - 1)
|
| + *pFileIndex += 1;
|
| + else
|
| + *pFileIndex = 0;
|
| +
|
| + strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH));
|
| + }
|
| +
|
| + return TRUE;
|
| + }
|
| + else
|
| + {
|
| + return FALSE;
|
| + }
|
| +}
|
| +
|
| +/*-----------------
|
| + * LoadImageFile
|
| + *-----------------
|
| + */
|
| +
|
| +BOOL LoadImageFile (HWND hwnd, PTSTR pstrPathName,
|
| + png_byte **ppbImage, int *pxImgSize, int *pyImgSize,
|
| + int *piChannels, png_color *pBkgColor)
|
| +{
|
| + static TCHAR szTmp [MAX_PATH];
|
| +
|
| + /* if there's an existing PNG, free the memory */
|
| +
|
| + if (*ppbImage)
|
| + {
|
| + free (*ppbImage);
|
| + *ppbImage = NULL;
|
| + }
|
| +
|
| + /* Load the entire PNG into memory */
|
| +
|
| + SetCursor (LoadCursor (NULL, IDC_WAIT));
|
| + ShowCursor (TRUE);
|
| +
|
| + PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels,
|
| + pBkgColor);
|
| +
|
| + ShowCursor (FALSE);
|
| + SetCursor (LoadCursor (NULL, IDC_ARROW));
|
| +
|
| + if (*ppbImage != NULL)
|
| + {
|
| + sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1);
|
| + SetWindowText (hwnd, szTmp);
|
| + }
|
| + else
|
| + {
|
| + MessageBox (hwnd, TEXT ("Error in loading the PNG image"),
|
| + szProgName, MB_ICONEXCLAMATION | MB_OK);
|
| + return FALSE;
|
| + }
|
| +
|
| + return TRUE;
|
| +}
|
| +
|
| +/*----------------
|
| + * DisplayImage
|
| + *----------------
|
| + */
|
| +BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
|
| + BYTE **ppDiData, int cxWinSize, int cyWinSize,
|
| + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
|
| + BOOL bStretched)
|
| +{
|
| + BYTE *pDib = *ppDib;
|
| + BYTE *pDiData = *ppDiData;
|
| + /* BITMAPFILEHEADER *pbmfh; */
|
| + BITMAPINFOHEADER *pbmih;
|
| + WORD wDIRowBytes;
|
| + png_color bkgBlack = {0, 0, 0};
|
| + png_color bkgGray = {127, 127, 127};
|
| + png_color bkgWhite = {255, 255, 255};
|
| +
|
| + /* allocate memory for the Device Independant bitmap */
|
| +
|
| + wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2;
|
| +
|
| + if (pDib)
|
| + {
|
| + free (pDib);
|
| + pDib = NULL;
|
| + }
|
| +
|
| + if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) +
|
| + wDIRowBytes * cyWinSize)))
|
| + {
|
| + MessageBox (hwnd, TEXT ("Error in displaying the PNG image"),
|
| + szProgName, MB_ICONEXCLAMATION | MB_OK);
|
| + *ppDib = pDib = NULL;
|
| + return FALSE;
|
| + }
|
| + *ppDib = pDib;
|
| + memset (pDib, 0, sizeof(BITMAPINFOHEADER));
|
| +
|
| + /* initialize the dib-structure */
|
| +
|
| + pbmih = (BITMAPINFOHEADER *) pDib;
|
| + pbmih->biSize = sizeof(BITMAPINFOHEADER);
|
| + pbmih->biWidth = cxWinSize;
|
| + pbmih->biHeight = -((long) cyWinSize);
|
| + pbmih->biPlanes = 1;
|
| + pbmih->biBitCount = 24;
|
| + pbmih->biCompression = 0;
|
| + pDiData = pDib + sizeof(BITMAPINFOHEADER);
|
| + *ppDiData = pDiData;
|
| +
|
| + /* first fill bitmap with gray and image border */
|
| +
|
| + InitBitmap (pDiData, cxWinSize, cyWinSize);
|
| +
|
| + /* then fill bitmap with image */
|
| +
|
| + if (pbImage)
|
| + {
|
| + FillBitmap (
|
| + pDiData, cxWinSize, cyWinSize,
|
| + pbImage, cxImgSize, cyImgSize, cImgChannels,
|
| + bStretched);
|
| + }
|
| +
|
| + return TRUE;
|
| +}
|
| +
|
| +/*--------------
|
| + * InitBitmap
|
| + *--------------
|
| + */
|
| +BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize)
|
| +{
|
| + BYTE *dst;
|
| + int x, y, col;
|
| +
|
| + /* initialize the background with gray */
|
| +
|
| + dst = pDiData;
|
| + for (y = 0; y < cyWinSize; y++)
|
| + {
|
| + col = 0;
|
| + for (x = 0; x < cxWinSize; x++)
|
| + {
|
| + /* fill with GRAY */
|
| + *dst++ = 127;
|
| + *dst++ = 127;
|
| + *dst++ = 127;
|
| + col += 3;
|
| + }
|
| + /* rows start on 4 byte boundaries */
|
| + while ((col % 4) != 0)
|
| + {
|
| + dst++;
|
| + col++;
|
| + }
|
| + }
|
| +
|
| + return TRUE;
|
| +}
|
| +
|
| +/*--------------
|
| + * FillBitmap
|
| + *--------------
|
| + */
|
| +BOOL FillBitmap (
|
| + BYTE *pDiData, int cxWinSize, int cyWinSize,
|
| + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
|
| + BOOL bStretched)
|
| +{
|
| + BYTE *pStretchedImage;
|
| + BYTE *pImg;
|
| + BYTE *src, *dst;
|
| + BYTE r, g, b, a;
|
| + const int cDIChannels = 3;
|
| + WORD wImgRowBytes;
|
| + WORD wDIRowBytes;
|
| + int cxNewSize, cyNewSize;
|
| + int cxImgPos, cyImgPos;
|
| + int xImg, yImg;
|
| + int xWin, yWin;
|
| + int xOld, yOld;
|
| + int xNew, yNew;
|
| +
|
| + if (bStretched)
|
| + {
|
| + cxNewSize = cxWinSize - 2 * MARGIN;
|
| + cyNewSize = cyWinSize - 2 * MARGIN;
|
| +
|
| + /* stretch the image to it's window determined size */
|
| +
|
| + /* the following two are mathematically the same, but the first
|
| + * has side-effects because of rounding
|
| + */
|
| +/* if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize)) */
|
| + if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize))
|
| + {
|
| + cyNewSize = cxNewSize * cyImgSize / cxImgSize;
|
| + cxImgPos = MARGIN;
|
| + cyImgPos = (cyWinSize - cyNewSize) / 2;
|
| + }
|
| + else
|
| + {
|
| + cxNewSize = cyNewSize * cxImgSize / cyImgSize;
|
| + cyImgPos = MARGIN;
|
| + cxImgPos = (cxWinSize - cxNewSize) / 2;
|
| + }
|
| +
|
| + pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize);
|
| + pImg = pStretchedImage;
|
| +
|
| + for (yNew = 0; yNew < cyNewSize; yNew++)
|
| + {
|
| + yOld = yNew * cyImgSize / cyNewSize;
|
| + for (xNew = 0; xNew < cxNewSize; xNew++)
|
| + {
|
| + xOld = xNew * cxImgSize / cxNewSize;
|
| +
|
| + r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0);
|
| + g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1);
|
| + b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2);
|
| + *pImg++ = r;
|
| + *pImg++ = g;
|
| + *pImg++ = b;
|
| + if (cImgChannels == 4)
|
| + {
|
| + a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld)
|
| + + 3);
|
| + *pImg++ = a;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* calculate row-bytes */
|
| +
|
| + wImgRowBytes = cImgChannels * cxNewSize;
|
| + wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
|
| +
|
| + /* copy image to screen */
|
| +
|
| + for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++)
|
| + {
|
| + if (yWin >= cyWinSize - cyImgPos)
|
| + break;
|
| + src = pStretchedImage + yImg * wImgRowBytes;
|
| + dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
|
| +
|
| + for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++)
|
| + {
|
| + if (xWin >= cxWinSize - cxImgPos)
|
| + break;
|
| + r = *src++;
|
| + g = *src++;
|
| + b = *src++;
|
| + *dst++ = b; /* note the reverse order */
|
| + *dst++ = g;
|
| + *dst++ = r;
|
| + if (cImgChannels == 4)
|
| + {
|
| + a = *src++;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* free memory */
|
| +
|
| + if (pStretchedImage != NULL)
|
| + {
|
| + free (pStretchedImage);
|
| + pStretchedImage = NULL;
|
| + }
|
| +
|
| + }
|
| +
|
| + /* process the image not-stretched */
|
| +
|
| + else
|
| + {
|
| + /* calculate the central position */
|
| +
|
| + cxImgPos = (cxWinSize - cxImgSize) / 2;
|
| + cyImgPos = (cyWinSize - cyImgSize) / 2;
|
| +
|
| + /* check for image larger than window */
|
| +
|
| + if (cxImgPos < MARGIN)
|
| + cxImgPos = MARGIN;
|
| + if (cyImgPos < MARGIN)
|
| + cyImgPos = MARGIN;
|
| +
|
| + /* calculate both row-bytes */
|
| +
|
| + wImgRowBytes = cImgChannels * cxImgSize;
|
| + wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
|
| +
|
| + /* copy image to screen */
|
| +
|
| + for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++)
|
| + {
|
| + if (yWin >= cyWinSize - MARGIN)
|
| + break;
|
| + src = pbImage + yImg * wImgRowBytes;
|
| + dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
|
| +
|
| + for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++)
|
| + {
|
| + if (xWin >= cxWinSize - MARGIN)
|
| + break;
|
| + r = *src++;
|
| + g = *src++;
|
| + b = *src++;
|
| + *dst++ = b; /* note the reverse order */
|
| + *dst++ = g;
|
| + *dst++ = r;
|
| + if (cImgChannels == 4)
|
| + {
|
| + a = *src++;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + return TRUE;
|
| +}
|
| +
|
| +/*-----------------
|
| + * end of source
|
| + *-----------------
|
| + */
|
|
|