symbian-qemu-0.9.1-12/libpng-1.2.32/contrib/visupng/VisualPng.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 //------------------------------------
       
     2 //  VisualPng.C -- Shows a PNG image
       
     3 //------------------------------------
       
     4 
       
     5 // Copyright 2000, Willem van Schaik.  For conditions of distribution and
       
     6 // use, see the copyright/license/disclaimer notice in png.h
       
     7 
       
     8 // switches
       
     9 
       
    10 // defines
       
    11 
       
    12 #define PROGNAME  "VisualPng"
       
    13 #define LONGNAME  "Win32 Viewer for PNG-files"
       
    14 #define VERSION   "1.0 of 2000 June 07"
       
    15 
       
    16 // constants
       
    17 
       
    18 #define MARGIN 8
       
    19 
       
    20 // standard includes
       
    21 
       
    22 #include <stdio.h>
       
    23 #include <stdlib.h>
       
    24 #include <string.h>
       
    25 #include <windows.h>
       
    26 
       
    27 // application includes
       
    28 
       
    29 #include "png.h"
       
    30 #include "pngfile.h"
       
    31 #include "resource.h"
       
    32 
       
    33 // macros
       
    34 
       
    35 // function prototypes
       
    36 
       
    37 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
       
    38 BOOL    CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
       
    39 
       
    40 BOOL CenterAbout (HWND hwndChild, HWND hwndParent);
       
    41 
       
    42 BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
       
    43         int *pFileIndex);
       
    44 
       
    45 BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex,
       
    46         PTSTR pstrPrevName, PTSTR pstrNextName);
       
    47 
       
    48 BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName,
       
    49         png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels,
       
    50         png_color *pBkgColor);
       
    51 
       
    52 BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
       
    53         BYTE **ppDiData, int cxWinSize, int cyWinSize,
       
    54         BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
       
    55         BOOL bStretched);
       
    56 
       
    57 BOOL InitBitmap (
       
    58         BYTE *pDiData, int cxWinSize, int cyWinSize);
       
    59 
       
    60 BOOL FillBitmap (
       
    61         BYTE *pDiData, int cxWinSize, int cyWinSize,
       
    62         BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
       
    63         BOOL bStretched);
       
    64 
       
    65 // a few global variables
       
    66 
       
    67 static char *szProgName = PROGNAME;
       
    68 static char *szAppName = LONGNAME;
       
    69 static char *szIconName = PROGNAME;
       
    70 static char szCmdFileName [MAX_PATH];
       
    71 
       
    72 // MAIN routine
       
    73 
       
    74 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
       
    75                     PSTR szCmdLine, int iCmdShow)
       
    76 {
       
    77     HACCEL   hAccel;
       
    78     HWND     hwnd;
       
    79     MSG      msg;
       
    80     WNDCLASS wndclass;
       
    81     int ixBorders, iyBorders;
       
    82 
       
    83     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
       
    84     wndclass.lpfnWndProc   = WndProc;
       
    85     wndclass.cbClsExtra    = 0;
       
    86     wndclass.cbWndExtra    = 0;
       
    87     wndclass.hInstance     = hInstance;
       
    88     wndclass.hIcon         = LoadIcon (hInstance, szIconName) ;
       
    89     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
       
    90     wndclass.hbrBackground = NULL; // (HBRUSH) GetStockObject (GRAY_BRUSH);
       
    91     wndclass.lpszMenuName  = szProgName;
       
    92     wndclass.lpszClassName = szProgName;
       
    93 
       
    94     if (!RegisterClass (&wndclass))
       
    95     {
       
    96         MessageBox (NULL, TEXT ("Error: this program requires Windows NT!"),
       
    97             szProgName, MB_ICONERROR);
       
    98         return 0;
       
    99     }
       
   100 
       
   101     // if filename given on commandline, store it
       
   102     if ((szCmdLine != NULL) && (*szCmdLine != '\0'))
       
   103         if (szCmdLine[0] == '"')
       
   104             strncpy (szCmdFileName, szCmdLine + 1, strlen(szCmdLine) - 2);
       
   105         else
       
   106             strcpy (szCmdFileName, szCmdLine);
       
   107     else
       
   108         strcpy (szCmdFileName, "");
       
   109 
       
   110     // calculate size of window-borders
       
   111     ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) +
       
   112                      GetSystemMetrics (SM_CXDLGFRAME));
       
   113     iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) +
       
   114                      GetSystemMetrics (SM_CYDLGFRAME)) +
       
   115                      GetSystemMetrics (SM_CYCAPTION) +
       
   116                      GetSystemMetrics (SM_CYMENUSIZE) +
       
   117                      1; /* WvS: don't ask me why? */
       
   118 
       
   119     hwnd = CreateWindow (szProgName, szAppName,
       
   120         WS_OVERLAPPEDWINDOW,
       
   121         CW_USEDEFAULT, CW_USEDEFAULT,
       
   122         512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders,
       
   123 //      CW_USEDEFAULT, CW_USEDEFAULT,
       
   124         NULL, NULL, hInstance, NULL);
       
   125 
       
   126     ShowWindow (hwnd, iCmdShow);
       
   127     UpdateWindow (hwnd);
       
   128 
       
   129     hAccel = LoadAccelerators (hInstance, szProgName);
       
   130 
       
   131     while (GetMessage (&msg, NULL, 0, 0))
       
   132     {
       
   133         if (!TranslateAccelerator (hwnd, hAccel, &msg))
       
   134         {
       
   135             TranslateMessage (&msg);
       
   136             DispatchMessage (&msg);
       
   137         }
       
   138     }
       
   139     return msg.wParam;
       
   140 }
       
   141 
       
   142 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
       
   143         LPARAM lParam)
       
   144 {
       
   145     static HINSTANCE          hInstance ;
       
   146     static HDC                hdc;
       
   147     static PAINTSTRUCT        ps;
       
   148     static HMENU              hMenu;
       
   149 
       
   150     static BITMAPFILEHEADER  *pbmfh;
       
   151     static BITMAPINFOHEADER  *pbmih;
       
   152     static BYTE              *pbImage;
       
   153     static int                cxWinSize, cyWinSize;
       
   154     static int                cxImgSize, cyImgSize;
       
   155     static int                cImgChannels;
       
   156     static png_color          bkgColor = {127, 127, 127};
       
   157 
       
   158     static BOOL               bStretched = TRUE;
       
   159 
       
   160     static BYTE              *pDib = NULL;
       
   161     static BYTE              *pDiData = NULL;
       
   162 
       
   163     static TCHAR              szImgPathName [MAX_PATH];
       
   164     static TCHAR              szTitleName [MAX_PATH];
       
   165 
       
   166     static TCHAR             *pPngFileList = NULL;
       
   167     static int                iPngFileCount;
       
   168     static int                iPngFileIndex;
       
   169 
       
   170     BOOL                      bOk;
       
   171 
       
   172     switch (message)
       
   173     {
       
   174     case WM_CREATE:
       
   175         hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
       
   176         PngFileInitialize (hwnd);
       
   177 
       
   178         strcpy (szImgPathName, "");
       
   179 
       
   180         // in case we process file given on command-line
       
   181 
       
   182         if (szCmdFileName[0] != '\0')
       
   183         {
       
   184             strcpy (szImgPathName, szCmdFileName);
       
   185 
       
   186             // read the other png-files in the directory for later
       
   187             // next/previous commands
       
   188 
       
   189             BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
       
   190                           &iPngFileIndex);
       
   191 
       
   192             // load the image from file
       
   193 
       
   194             if (!LoadImageFile (hwnd, szImgPathName,
       
   195                 &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
       
   196                 return 0;
       
   197 
       
   198             // invalidate the client area for later update
       
   199 
       
   200             InvalidateRect (hwnd, NULL, TRUE);
       
   201 
       
   202             // display the PNG into the DIBitmap
       
   203 
       
   204             DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
       
   205                 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
       
   206         }
       
   207 
       
   208         return 0;
       
   209 
       
   210     case WM_SIZE:
       
   211         cxWinSize = LOWORD (lParam);
       
   212         cyWinSize = HIWORD (lParam);
       
   213 
       
   214         // invalidate the client area for later update
       
   215 
       
   216         InvalidateRect (hwnd, NULL, TRUE);
       
   217 
       
   218         // display the PNG into the DIBitmap
       
   219 
       
   220         DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
       
   221             pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
       
   222 
       
   223         return 0;
       
   224 
       
   225     case WM_INITMENUPOPUP:
       
   226         hMenu = GetMenu (hwnd);
       
   227 
       
   228         if (pbImage)
       
   229             EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_ENABLED);
       
   230         else
       
   231             EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_GRAYED);
       
   232 
       
   233         return 0;
       
   234 
       
   235     case WM_COMMAND:
       
   236         hMenu = GetMenu (hwnd);
       
   237 
       
   238         switch (LOWORD (wParam))
       
   239         {
       
   240         case IDM_FILE_OPEN:
       
   241 
       
   242             // show the File Open dialog box
       
   243 
       
   244             if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName))
       
   245                 return 0;
       
   246 
       
   247             // read the other png-files in the directory for later
       
   248             // next/previous commands
       
   249 
       
   250             BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
       
   251                           &iPngFileIndex);
       
   252 
       
   253             // load the image from file
       
   254 
       
   255             if (!LoadImageFile (hwnd, szImgPathName,
       
   256                 &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
       
   257                 return 0;
       
   258 
       
   259             // invalidate the client area for later update
       
   260 
       
   261             InvalidateRect (hwnd, NULL, TRUE);
       
   262 
       
   263             // display the PNG into the DIBitmap
       
   264 
       
   265             DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
       
   266                 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
       
   267 
       
   268             return 0;
       
   269 
       
   270         case IDM_FILE_SAVE:
       
   271 
       
   272             // show the File Save dialog box
       
   273 
       
   274             if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName))
       
   275                 return 0;
       
   276 
       
   277             // save the PNG to a disk file
       
   278 
       
   279             SetCursor (LoadCursor (NULL, IDC_WAIT));
       
   280             ShowCursor (TRUE);
       
   281 
       
   282             bOk = PngSaveImage (szImgPathName, pDiData, cxWinSize, cyWinSize,
       
   283                   bkgColor);
       
   284 
       
   285             ShowCursor (FALSE);
       
   286             SetCursor (LoadCursor (NULL, IDC_ARROW));
       
   287 
       
   288             if (!bOk)
       
   289                 MessageBox (hwnd, TEXT ("Error in saving the PNG image"),
       
   290                 szProgName, MB_ICONEXCLAMATION | MB_OK);
       
   291             return 0;
       
   292 
       
   293         case IDM_FILE_NEXT:
       
   294 
       
   295             // read next entry in the directory
       
   296 
       
   297             if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
       
   298                 NULL, szImgPathName))
       
   299             {
       
   300                 if (strcmp (szImgPathName, "") == 0)
       
   301                     return 0;
       
   302                 
       
   303                 // load the image from file
       
   304                 
       
   305                 if (!LoadImageFile (hwnd, szImgPathName, &pbImage,
       
   306                         &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
       
   307                     return 0;
       
   308                 
       
   309                 // invalidate the client area for later update
       
   310                 
       
   311                 InvalidateRect (hwnd, NULL, TRUE);
       
   312                 
       
   313                 // display the PNG into the DIBitmap
       
   314                 
       
   315                 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
       
   316                     pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
       
   317             }
       
   318             
       
   319             return 0;
       
   320 
       
   321         case IDM_FILE_PREVIOUS:
       
   322 
       
   323             // read previous entry in the directory
       
   324 
       
   325             if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
       
   326                 szImgPathName, NULL))
       
   327             {
       
   328                 
       
   329                 if (strcmp (szImgPathName, "") == 0)
       
   330                     return 0;
       
   331                 
       
   332                 // load the image from file
       
   333                 
       
   334                 if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize,
       
   335                     &cyImgSize, &cImgChannels, &bkgColor))
       
   336                     return 0;
       
   337                 
       
   338                 // invalidate the client area for later update
       
   339                 
       
   340                 InvalidateRect (hwnd, NULL, TRUE);
       
   341                 
       
   342                 // display the PNG into the DIBitmap
       
   343                 
       
   344                 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
       
   345                     pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
       
   346             }
       
   347 
       
   348             return 0;
       
   349 
       
   350         case IDM_FILE_EXIT:
       
   351 
       
   352             // more cleanup needed...
       
   353 
       
   354             // free image buffer
       
   355 
       
   356             if (pDib != NULL)
       
   357             {
       
   358                 free (pDib);
       
   359                 pDib = NULL;
       
   360             }
       
   361 
       
   362             // free file-list
       
   363 
       
   364             if (pPngFileList != NULL)
       
   365             {
       
   366                 free (pPngFileList);
       
   367                 pPngFileList = NULL;
       
   368             }
       
   369 
       
   370             // let's go ...
       
   371 
       
   372             exit (0);
       
   373 
       
   374             return 0;
       
   375 
       
   376         case IDM_OPTIONS_STRETCH:
       
   377             bStretched = !bStretched;
       
   378             if (bStretched)
       
   379                 CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_CHECKED);
       
   380             else
       
   381                 CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED);
       
   382 
       
   383             // invalidate the client area for later update
       
   384 
       
   385             InvalidateRect (hwnd, NULL, TRUE);
       
   386 
       
   387             // display the PNG into the DIBitmap
       
   388 
       
   389             DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
       
   390                 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
       
   391 
       
   392             return 0;
       
   393 
       
   394         case IDM_HELP_ABOUT:
       
   395             DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ;
       
   396             return 0;
       
   397 
       
   398         } // end switch
       
   399 
       
   400         break;
       
   401 
       
   402     case WM_PAINT:
       
   403         hdc = BeginPaint (hwnd, &ps);
       
   404 
       
   405         if (pDib)
       
   406             SetDIBitsToDevice (hdc, 0, 0, cxWinSize, cyWinSize, 0, 0,
       
   407                 0, cyWinSize, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS);
       
   408 
       
   409         EndPaint (hwnd, &ps);
       
   410         return 0;
       
   411 
       
   412     case WM_DESTROY:
       
   413         if (pbmfh)
       
   414         {
       
   415             free (pbmfh);
       
   416             pbmfh = NULL;
       
   417         }
       
   418 
       
   419         PostQuitMessage (0);
       
   420         return 0;
       
   421     }
       
   422 
       
   423     return DefWindowProc (hwnd, message, wParam, lParam);
       
   424 }
       
   425 
       
   426 BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,
       
   427                             WPARAM wParam, LPARAM lParam)
       
   428 {
       
   429      switch (message)
       
   430      {
       
   431      case WM_INITDIALOG :
       
   432           ShowWindow (hDlg, SW_HIDE);
       
   433           CenterAbout (hDlg, GetWindow (hDlg, GW_OWNER));
       
   434           ShowWindow (hDlg, SW_SHOW);
       
   435           return TRUE ;
       
   436 
       
   437      case WM_COMMAND :
       
   438           switch (LOWORD (wParam))
       
   439           {
       
   440           case IDOK :
       
   441           case IDCANCEL :
       
   442                EndDialog (hDlg, 0) ;
       
   443                return TRUE ;
       
   444           }
       
   445           break ;
       
   446      }
       
   447      return FALSE ;
       
   448 }
       
   449 
       
   450 //---------------
       
   451 //  CenterAbout
       
   452 //---------------
       
   453 
       
   454 BOOL CenterAbout (HWND hwndChild, HWND hwndParent)
       
   455 {
       
   456    RECT    rChild, rParent, rWorkArea;
       
   457    int     wChild, hChild, wParent, hParent;
       
   458    int     xNew, yNew;
       
   459    BOOL  bResult;
       
   460 
       
   461    // Get the Height and Width of the child window
       
   462    GetWindowRect (hwndChild, &rChild);
       
   463    wChild = rChild.right - rChild.left;
       
   464    hChild = rChild.bottom - rChild.top;
       
   465 
       
   466    // Get the Height and Width of the parent window
       
   467    GetWindowRect (hwndParent, &rParent);
       
   468    wParent = rParent.right - rParent.left;
       
   469    hParent = rParent.bottom - rParent.top;
       
   470 
       
   471    // Get the limits of the 'workarea'
       
   472    bResult = SystemParametersInfo(
       
   473       SPI_GETWORKAREA,  // system parameter to query or set
       
   474       sizeof(RECT),
       
   475       &rWorkArea,
       
   476       0);
       
   477    if (!bResult) {
       
   478       rWorkArea.left = rWorkArea.top = 0;
       
   479       rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
       
   480       rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
       
   481    }
       
   482 
       
   483    // Calculate new X position, then adjust for workarea
       
   484    xNew = rParent.left + ((wParent - wChild) /2);
       
   485    if (xNew < rWorkArea.left) {
       
   486       xNew = rWorkArea.left;
       
   487    } else if ((xNew+wChild) > rWorkArea.right) {
       
   488       xNew = rWorkArea.right - wChild;
       
   489    }
       
   490 
       
   491    // Calculate new Y position, then adjust for workarea
       
   492    yNew = rParent.top  + ((hParent - hChild) /2);
       
   493    if (yNew < rWorkArea.top) {
       
   494       yNew = rWorkArea.top;
       
   495    } else if ((yNew+hChild) > rWorkArea.bottom) {
       
   496       yNew = rWorkArea.bottom - hChild;
       
   497    }
       
   498 
       
   499    // Set it, and return
       
   500    return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE |
       
   501           SWP_NOZORDER);
       
   502 }
       
   503 
       
   504 //----------------
       
   505 //  BuildPngList
       
   506 //----------------
       
   507 
       
   508 BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
       
   509      int *pFileIndex)
       
   510 {
       
   511     static TCHAR              szImgPathName [MAX_PATH];
       
   512     static TCHAR              szImgFileName [MAX_PATH];
       
   513     static TCHAR              szImgFindName [MAX_PATH];
       
   514 
       
   515     WIN32_FIND_DATA           finddata;
       
   516     HANDLE                    hFind;
       
   517 
       
   518     static TCHAR              szTmp [MAX_PATH];
       
   519     BOOL                      bOk;
       
   520     int                       i, ii;
       
   521     int                       j, jj;
       
   522 
       
   523     // free previous file-list
       
   524 
       
   525     if (*ppFileList != NULL)
       
   526     {
       
   527         free (*ppFileList);
       
   528         *ppFileList = NULL;
       
   529     }
       
   530 
       
   531     // extract foldername, filename and search-name
       
   532 
       
   533     strcpy (szImgPathName, pstrPathName);
       
   534     strcpy (szImgFileName, strrchr (pstrPathName, '\\') + 1);
       
   535 
       
   536     strcpy (szImgFindName, szImgPathName);
       
   537     *(strrchr (szImgFindName, '\\') + 1) = '\0';
       
   538     strcat (szImgFindName, "*.png");
       
   539 
       
   540     // first cycle: count number of files in directory for memory allocation
       
   541 
       
   542     *pFileCount = 0;
       
   543 
       
   544     hFind = FindFirstFile(szImgFindName, &finddata);
       
   545     bOk = (hFind != (HANDLE) -1);
       
   546 
       
   547     while (bOk)
       
   548     {
       
   549         *pFileCount += 1;
       
   550         bOk = FindNextFile(hFind, &finddata);
       
   551     }
       
   552     FindClose(hFind);
       
   553 
       
   554     // allocation memory for file-list
       
   555 
       
   556     *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH);
       
   557 
       
   558     // second cycle: read directory and store filenames in file-list
       
   559 
       
   560     hFind = FindFirstFile(szImgFindName, &finddata);
       
   561     bOk = (hFind != (HANDLE) -1);
       
   562 
       
   563     i = 0;
       
   564     ii = 0;
       
   565     while (bOk)
       
   566     {
       
   567         strcpy (*ppFileList + ii, szImgPathName);
       
   568         strcpy (strrchr(*ppFileList + ii, '\\') + 1, finddata.cFileName);
       
   569 
       
   570         if (strcmp(pstrPathName, *ppFileList + ii) == 0)
       
   571             *pFileIndex = i;
       
   572 
       
   573         ii += MAX_PATH;
       
   574         i++;
       
   575 
       
   576         bOk = FindNextFile(hFind, &finddata);
       
   577     }
       
   578     FindClose(hFind);
       
   579 
       
   580     // finally we must sort the file-list
       
   581 
       
   582     for (i = 0; i < *pFileCount - 1; i++)
       
   583     {
       
   584         ii = i * MAX_PATH;
       
   585         for (j = i+1; j < *pFileCount; j++)
       
   586         {
       
   587             jj = j * MAX_PATH;
       
   588             if (strcmp (*ppFileList + ii, *ppFileList + jj) > 0)
       
   589             {
       
   590                 strcpy (szTmp, *ppFileList + jj);
       
   591                 strcpy (*ppFileList + jj, *ppFileList + ii);
       
   592                 strcpy (*ppFileList + ii, szTmp);
       
   593 
       
   594                 // check if this was the current image that we moved
       
   595 
       
   596                 if (*pFileIndex == i)
       
   597                     *pFileIndex = j;
       
   598                 else
       
   599                     if (*pFileIndex == j)
       
   600                         *pFileIndex = i;
       
   601             }
       
   602         }
       
   603     }
       
   604 
       
   605     return TRUE;
       
   606 }
       
   607 
       
   608 //----------------
       
   609 //  SearchPngList
       
   610 //----------------
       
   611 
       
   612 BOOL SearchPngList (
       
   613         TCHAR *pFileList, int FileCount, int *pFileIndex,
       
   614         PTSTR pstrPrevName, PTSTR pstrNextName)
       
   615 {
       
   616     if (FileCount > 0)
       
   617     {
       
   618         // get previous entry
       
   619         
       
   620         if (pstrPrevName != NULL)
       
   621         {
       
   622             if (*pFileIndex > 0)
       
   623                 *pFileIndex -= 1;
       
   624             else
       
   625                 *pFileIndex = FileCount - 1;
       
   626             
       
   627             strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH));
       
   628         }
       
   629         
       
   630         // get next entry
       
   631         
       
   632         if (pstrNextName != NULL)
       
   633         {
       
   634             if (*pFileIndex < FileCount - 1)
       
   635                 *pFileIndex += 1;
       
   636             else
       
   637                 *pFileIndex = 0;
       
   638             
       
   639             strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH));
       
   640         }
       
   641         
       
   642         return TRUE;
       
   643     }
       
   644     else
       
   645     {
       
   646         return FALSE;
       
   647     }
       
   648 }
       
   649 
       
   650 //-----------------
       
   651 //  LoadImageFile
       
   652 //-----------------
       
   653 
       
   654 BOOL LoadImageFile (HWND hwnd, PTSTR pstrPathName,
       
   655                 png_byte **ppbImage, int *pxImgSize, int *pyImgSize,
       
   656                 int *piChannels, png_color *pBkgColor)
       
   657 {
       
   658     static TCHAR szTmp [MAX_PATH];
       
   659 
       
   660     // if there's an existing PNG, free the memory
       
   661 
       
   662     if (*ppbImage)
       
   663     {
       
   664         free (*ppbImage);
       
   665         *ppbImage = NULL;
       
   666     }
       
   667 
       
   668     // Load the entire PNG into memory
       
   669 
       
   670     SetCursor (LoadCursor (NULL, IDC_WAIT));
       
   671     ShowCursor (TRUE);
       
   672 
       
   673     PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels,
       
   674                   pBkgColor);
       
   675 
       
   676     ShowCursor (FALSE);
       
   677     SetCursor (LoadCursor (NULL, IDC_ARROW));
       
   678 
       
   679     if (*ppbImage != NULL)
       
   680     {
       
   681         sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1);
       
   682         SetWindowText (hwnd, szTmp);
       
   683     }
       
   684     else
       
   685     {
       
   686         MessageBox (hwnd, TEXT ("Error in loading the PNG image"),
       
   687             szProgName, MB_ICONEXCLAMATION | MB_OK);
       
   688         return FALSE;
       
   689     }
       
   690 
       
   691     return TRUE;
       
   692 }
       
   693 
       
   694 //----------------
       
   695 //  DisplayImage
       
   696 //----------------
       
   697 
       
   698 BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
       
   699         BYTE **ppDiData, int cxWinSize, int cyWinSize,
       
   700         BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
       
   701         BOOL bStretched)
       
   702 {
       
   703     BYTE                       *pDib = *ppDib;
       
   704     BYTE                       *pDiData = *ppDiData;
       
   705     // BITMAPFILEHEADER        *pbmfh;
       
   706     BITMAPINFOHEADER           *pbmih;
       
   707     WORD                        wDIRowBytes;
       
   708     png_color                   bkgBlack = {0, 0, 0};
       
   709     png_color                   bkgGray  = {127, 127, 127};
       
   710     png_color                   bkgWhite = {255, 255, 255};
       
   711 
       
   712     // allocate memory for the Device Independant bitmap
       
   713 
       
   714     wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2;
       
   715 
       
   716     if (pDib)
       
   717     {
       
   718         free (pDib);
       
   719         pDib = NULL;
       
   720     }
       
   721 
       
   722     if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) +
       
   723         wDIRowBytes * cyWinSize)))
       
   724     {
       
   725         MessageBox (hwnd, TEXT ("Error in displaying the PNG image"),
       
   726             szProgName, MB_ICONEXCLAMATION | MB_OK);
       
   727         *ppDib = pDib = NULL;
       
   728         return FALSE;
       
   729     }
       
   730     *ppDib = pDib;
       
   731     memset (pDib, 0, sizeof(BITMAPINFOHEADER));
       
   732 
       
   733     // initialize the dib-structure
       
   734 
       
   735     pbmih = (BITMAPINFOHEADER *) pDib;
       
   736     pbmih->biSize = sizeof(BITMAPINFOHEADER);
       
   737     pbmih->biWidth = cxWinSize;
       
   738     pbmih->biHeight = -((long) cyWinSize);
       
   739     pbmih->biPlanes = 1;
       
   740     pbmih->biBitCount = 24;
       
   741     pbmih->biCompression = 0;
       
   742     pDiData = pDib + sizeof(BITMAPINFOHEADER);
       
   743     *ppDiData = pDiData;
       
   744 
       
   745     // first fill bitmap with gray and image border
       
   746 
       
   747     InitBitmap (pDiData, cxWinSize, cyWinSize);
       
   748 
       
   749     // then fill bitmap with image
       
   750 
       
   751     if (pbImage)
       
   752     {
       
   753         FillBitmap (
       
   754             pDiData, cxWinSize, cyWinSize,
       
   755             pbImage, cxImgSize, cyImgSize, cImgChannels,
       
   756             bStretched);
       
   757     }
       
   758 
       
   759     return TRUE;
       
   760 }
       
   761 
       
   762 //--------------
       
   763 //  InitBitmap
       
   764 //--------------
       
   765 
       
   766 BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize)
       
   767 {
       
   768     BYTE *dst;
       
   769     int x, y, col;
       
   770 
       
   771     // initialize the background with gray
       
   772 
       
   773     dst = pDiData;
       
   774     for (y = 0; y < cyWinSize; y++)
       
   775     {
       
   776         col = 0;
       
   777         for (x = 0; x < cxWinSize; x++)
       
   778         {
       
   779             // fill with GRAY
       
   780             *dst++ = 127;
       
   781             *dst++ = 127;
       
   782             *dst++ = 127;
       
   783             col += 3;
       
   784         }
       
   785         // rows start on 4 byte boundaries
       
   786         while ((col % 4) != 0)
       
   787         {
       
   788             dst++;
       
   789             col++;
       
   790         }
       
   791     }
       
   792 
       
   793     return TRUE;
       
   794 }
       
   795 
       
   796 //--------------
       
   797 //  FillBitmap
       
   798 //--------------
       
   799 
       
   800 BOOL FillBitmap (
       
   801         BYTE *pDiData, int cxWinSize, int cyWinSize,
       
   802         BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
       
   803         BOOL bStretched)
       
   804 {
       
   805     BYTE *pStretchedImage;
       
   806     BYTE *pImg;
       
   807     BYTE *src, *dst;
       
   808     BYTE r, g, b, a;
       
   809     const int cDIChannels = 3;
       
   810     WORD wImgRowBytes;
       
   811     WORD wDIRowBytes;
       
   812     int cxNewSize, cyNewSize;
       
   813     int cxImgPos, cyImgPos;
       
   814     int xImg, yImg;
       
   815     int xWin, yWin;
       
   816     int xOld, yOld;
       
   817     int xNew, yNew;
       
   818 
       
   819     if (bStretched)
       
   820     {
       
   821         cxNewSize = cxWinSize - 2 * MARGIN;
       
   822         cyNewSize = cyWinSize - 2 * MARGIN;
       
   823 
       
   824         // stretch the image to it's window determined size
       
   825 
       
   826         // the following two are the same, but the first has side-effects
       
   827         // because of rounding
       
   828 //      if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize))
       
   829         if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize))
       
   830         {
       
   831             cyNewSize = cxNewSize * cyImgSize / cxImgSize;
       
   832             cxImgPos = MARGIN;
       
   833             cyImgPos = (cyWinSize - cyNewSize) / 2;
       
   834         }
       
   835         else
       
   836         {
       
   837             cxNewSize = cyNewSize * cxImgSize / cyImgSize;
       
   838             cyImgPos = MARGIN;
       
   839             cxImgPos = (cxWinSize - cxNewSize) / 2;
       
   840         }
       
   841 
       
   842         pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize);
       
   843         pImg = pStretchedImage;
       
   844 
       
   845         for (yNew = 0; yNew < cyNewSize; yNew++)
       
   846         {
       
   847             yOld = yNew * cyImgSize / cyNewSize;
       
   848             for (xNew = 0; xNew < cxNewSize; xNew++)
       
   849             {
       
   850                 xOld = xNew * cxImgSize / cxNewSize;
       
   851 
       
   852                 r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0);
       
   853                 g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1);
       
   854                 b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2);
       
   855                 *pImg++ = r;
       
   856                 *pImg++ = g;
       
   857                 *pImg++ = b;
       
   858                 if (cImgChannels == 4)
       
   859                 {
       
   860                     a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld)
       
   861                         + 3);
       
   862                     *pImg++ = a;
       
   863                 }
       
   864             }
       
   865         }
       
   866 
       
   867         // calculate row-bytes
       
   868 
       
   869         wImgRowBytes = cImgChannels * cxNewSize;
       
   870         wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
       
   871 
       
   872         // copy image to screen
       
   873 
       
   874         for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++)
       
   875         {
       
   876             if (yWin >= cyWinSize - cyImgPos)
       
   877                 break;
       
   878             src = pStretchedImage + yImg * wImgRowBytes;
       
   879             dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
       
   880 
       
   881             for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++)
       
   882             {
       
   883                 if (xWin >= cxWinSize - cxImgPos)
       
   884                     break;
       
   885                 r = *src++;
       
   886                 g = *src++;
       
   887                 b = *src++;
       
   888                 *dst++ = b; /* note the reverse order */
       
   889                 *dst++ = g;
       
   890                 *dst++ = r;
       
   891                 if (cImgChannels == 4)
       
   892                 {
       
   893                     a = *src++;
       
   894                 }
       
   895             }
       
   896         }
       
   897 
       
   898         // free memory
       
   899 
       
   900         if (pStretchedImage != NULL)
       
   901         {
       
   902             free (pStretchedImage);
       
   903             pStretchedImage = NULL;
       
   904         }
       
   905 
       
   906     }
       
   907 
       
   908     // process the image not-stretched
       
   909 
       
   910     else
       
   911     {
       
   912         // calculate the central position
       
   913 
       
   914         cxImgPos = (cxWinSize - cxImgSize) / 2;
       
   915         cyImgPos = (cyWinSize - cyImgSize) / 2;
       
   916 
       
   917         // check for image larger than window
       
   918 
       
   919         if (cxImgPos < MARGIN)
       
   920             cxImgPos = MARGIN;
       
   921         if (cyImgPos < MARGIN)
       
   922             cyImgPos = MARGIN;
       
   923 
       
   924         // calculate both row-bytes
       
   925 
       
   926         wImgRowBytes = cImgChannels * cxImgSize;
       
   927         wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
       
   928 
       
   929         // copy image to screen
       
   930 
       
   931         for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++)
       
   932         {
       
   933             if (yWin >= cyWinSize - MARGIN)
       
   934                 break;
       
   935             src = pbImage + yImg * wImgRowBytes;
       
   936             dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
       
   937 
       
   938             for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++)
       
   939             {
       
   940                 if (xWin >= cxWinSize - MARGIN)
       
   941                     break;
       
   942                 r = *src++;
       
   943                 g = *src++;
       
   944                 b = *src++;
       
   945                 *dst++ = b; /* note the reverse order */
       
   946                 *dst++ = g;
       
   947                 *dst++ = r;
       
   948                 if (cImgChannels == 4)
       
   949                 {
       
   950                     a = *src++;
       
   951                 }
       
   952             }
       
   953         }
       
   954     }
       
   955 
       
   956     return TRUE;
       
   957 }
       
   958 
       
   959 //-----------------
       
   960 //  end of source
       
   961 //-----------------