mirror of
				https://git.code.sf.net/p/libpng/code.git
				synced 2025-07-10 18:04:09 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			970 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			970 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*------------------------------------
 | |
|  *  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>
 | |
| 
 | |
| /* 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
 | |
|  *-----------------
 | |
|  */
 | 
