blob: 20e1625fa7dc432bbbc0d082521ed4845f37c619 [file] [log] [blame]
Chris Craikca2bf812013-07-29 15:28:30 -07001/*------------------------------------
2 * VisualPng.C -- Shows a PNG image
3 *------------------------------------
4 *
Leon Scroggins III3cc83ac2017-10-06 11:02:56 -04005 * Copyright 2000,2017 Willem van Schaik.
Chris Craikca2bf812013-07-29 15:28:30 -07006 *
7 * This code is released under the libpng license.
8 * For conditions of distribution and use, see the disclaimer
9 * and license in png.h
10 */
The Android Open Source Project893912b2009-03-03 19:30:05 -080011
Chris Craikca2bf812013-07-29 15:28:30 -070012/* switches */
Patrick Scotta0bb96c2009-07-22 11:50:02 -040013
Chris Craikca2bf812013-07-29 15:28:30 -070014/* defines */
The Android Open Source Project893912b2009-03-03 19:30:05 -080015
16#define PROGNAME "VisualPng"
17#define LONGNAME "Win32 Viewer for PNG-files"
18#define VERSION "1.0 of 2000 June 07"
19
Chris Craikca2bf812013-07-29 15:28:30 -070020/* constants */
The Android Open Source Project893912b2009-03-03 19:30:05 -080021
22#define MARGIN 8
23
Chris Craikca2bf812013-07-29 15:28:30 -070024/* standard includes */
The Android Open Source Project893912b2009-03-03 19:30:05 -080025
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <windows.h>
Chris Craikca2bf812013-07-29 15:28:30 -070030#include <zlib.h>
The Android Open Source Project893912b2009-03-03 19:30:05 -080031
Chris Craikca2bf812013-07-29 15:28:30 -070032/* application includes */
The Android Open Source Project893912b2009-03-03 19:30:05 -080033
34#include "png.h"
35#include "pngfile.h"
36#include "resource.h"
37
Chris Craikca2bf812013-07-29 15:28:30 -070038/* macros */
The Android Open Source Project893912b2009-03-03 19:30:05 -080039
Chris Craikca2bf812013-07-29 15:28:30 -070040/* function prototypes */
The Android Open Source Project893912b2009-03-03 19:30:05 -080041
42LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
43BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
44
45BOOL CenterAbout (HWND hwndChild, HWND hwndParent);
46
47BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
48 int *pFileIndex);
49
50BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex,
51 PTSTR pstrPrevName, PTSTR pstrNextName);
52
53BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName,
54 png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels,
55 png_color *pBkgColor);
56
57BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
58 BYTE **ppDiData, int cxWinSize, int cyWinSize,
59 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
60 BOOL bStretched);
61
62BOOL InitBitmap (
63 BYTE *pDiData, int cxWinSize, int cyWinSize);
64
65BOOL FillBitmap (
66 BYTE *pDiData, int cxWinSize, int cyWinSize,
67 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
68 BOOL bStretched);
69
Chris Craikca2bf812013-07-29 15:28:30 -070070/* a few global variables */
The Android Open Source Project893912b2009-03-03 19:30:05 -080071
72static char *szProgName = PROGNAME;
73static char *szAppName = LONGNAME;
74static char *szIconName = PROGNAME;
75static char szCmdFileName [MAX_PATH];
76
Chris Craikca2bf812013-07-29 15:28:30 -070077/* MAIN routine */
The Android Open Source Project893912b2009-03-03 19:30:05 -080078
79int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
80 PSTR szCmdLine, int iCmdShow)
81{
82 HACCEL hAccel;
83 HWND hwnd;
84 MSG msg;
85 WNDCLASS wndclass;
86 int ixBorders, iyBorders;
87
88 wndclass.style = CS_HREDRAW | CS_VREDRAW;
89 wndclass.lpfnWndProc = WndProc;
90 wndclass.cbClsExtra = 0;
91 wndclass.cbWndExtra = 0;
92 wndclass.hInstance = hInstance;
93 wndclass.hIcon = LoadIcon (hInstance, szIconName) ;
94 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
Chris Craikca2bf812013-07-29 15:28:30 -070095 wndclass.hbrBackground = NULL; /* (HBRUSH) GetStockObject (GRAY_BRUSH); */
The Android Open Source Project893912b2009-03-03 19:30:05 -080096 wndclass.lpszMenuName = szProgName;
97 wndclass.lpszClassName = szProgName;
98
99 if (!RegisterClass (&wndclass))
100 {
101 MessageBox (NULL, TEXT ("Error: this program requires Windows NT!"),
102 szProgName, MB_ICONERROR);
103 return 0;
104 }
105
Chris Craikca2bf812013-07-29 15:28:30 -0700106 /* if filename given on commandline, store it */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800107 if ((szCmdLine != NULL) && (*szCmdLine != '\0'))
108 if (szCmdLine[0] == '"')
109 strncpy (szCmdFileName, szCmdLine + 1, strlen(szCmdLine) - 2);
110 else
111 strcpy (szCmdFileName, szCmdLine);
112 else
113 strcpy (szCmdFileName, "");
114
Chris Craikca2bf812013-07-29 15:28:30 -0700115 /* calculate size of window-borders */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800116 ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) +
117 GetSystemMetrics (SM_CXDLGFRAME));
118 iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) +
119 GetSystemMetrics (SM_CYDLGFRAME)) +
120 GetSystemMetrics (SM_CYCAPTION) +
121 GetSystemMetrics (SM_CYMENUSIZE) +
Chris Craikca2bf812013-07-29 15:28:30 -0700122 1; /* WvS: don't ask me why? */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800123
124 hwnd = CreateWindow (szProgName, szAppName,
125 WS_OVERLAPPEDWINDOW,
126 CW_USEDEFAULT, CW_USEDEFAULT,
127 512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders,
Chris Craikca2bf812013-07-29 15:28:30 -0700128/* CW_USEDEFAULT, CW_USEDEFAULT, */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800129 NULL, NULL, hInstance, NULL);
130
131 ShowWindow (hwnd, iCmdShow);
132 UpdateWindow (hwnd);
133
134 hAccel = LoadAccelerators (hInstance, szProgName);
135
136 while (GetMessage (&msg, NULL, 0, 0))
137 {
138 if (!TranslateAccelerator (hwnd, hAccel, &msg))
139 {
140 TranslateMessage (&msg);
141 DispatchMessage (&msg);
142 }
143 }
144 return msg.wParam;
145}
146
147LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
148 LPARAM lParam)
149{
150 static HINSTANCE hInstance ;
151 static HDC hdc;
152 static PAINTSTRUCT ps;
153 static HMENU hMenu;
154
155 static BITMAPFILEHEADER *pbmfh;
156 static BITMAPINFOHEADER *pbmih;
157 static BYTE *pbImage;
158 static int cxWinSize, cyWinSize;
159 static int cxImgSize, cyImgSize;
160 static int cImgChannels;
161 static png_color bkgColor = {127, 127, 127};
162
163 static BOOL bStretched = TRUE;
164
165 static BYTE *pDib = NULL;
166 static BYTE *pDiData = NULL;
167
168 static TCHAR szImgPathName [MAX_PATH];
169 static TCHAR szTitleName [MAX_PATH];
170
171 static TCHAR *pPngFileList = NULL;
172 static int iPngFileCount;
173 static int iPngFileIndex;
174
175 BOOL bOk;
176
177 switch (message)
178 {
179 case WM_CREATE:
180 hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
181 PngFileInitialize (hwnd);
182
183 strcpy (szImgPathName, "");
184
Chris Craikca2bf812013-07-29 15:28:30 -0700185 /* in case we process file given on command-line */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800186
187 if (szCmdFileName[0] != '\0')
188 {
189 strcpy (szImgPathName, szCmdFileName);
190
Chris Craikca2bf812013-07-29 15:28:30 -0700191 /* read the other png-files in the directory for later */
192 /* next/previous commands */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800193
194 BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
195 &iPngFileIndex);
196
Chris Craikca2bf812013-07-29 15:28:30 -0700197 /* load the image from file */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800198
199 if (!LoadImageFile (hwnd, szImgPathName,
200 &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
201 return 0;
202
Chris Craikca2bf812013-07-29 15:28:30 -0700203 /* invalidate the client area for later update */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800204
205 InvalidateRect (hwnd, NULL, TRUE);
206
Chris Craikca2bf812013-07-29 15:28:30 -0700207 /* display the PNG into the DIBitmap */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800208
209 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
210 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
211 }
212
213 return 0;
214
215 case WM_SIZE:
216 cxWinSize = LOWORD (lParam);
217 cyWinSize = HIWORD (lParam);
218
Chris Craikca2bf812013-07-29 15:28:30 -0700219 /* invalidate the client area for later update */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800220
221 InvalidateRect (hwnd, NULL, TRUE);
222
Chris Craikca2bf812013-07-29 15:28:30 -0700223 /* display the PNG into the DIBitmap */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800224
225 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
226 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
227
228 return 0;
229
230 case WM_INITMENUPOPUP:
231 hMenu = GetMenu (hwnd);
232
233 if (pbImage)
234 EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_ENABLED);
235 else
236 EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_GRAYED);
237
238 return 0;
239
240 case WM_COMMAND:
241 hMenu = GetMenu (hwnd);
242
243 switch (LOWORD (wParam))
244 {
245 case IDM_FILE_OPEN:
246
Chris Craikca2bf812013-07-29 15:28:30 -0700247 /* show the File Open dialog box */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800248
249 if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName))
250 return 0;
251
Chris Craikca2bf812013-07-29 15:28:30 -0700252 /* read the other png-files in the directory for later */
253 /* next/previous commands */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800254
255 BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
256 &iPngFileIndex);
257
Chris Craikca2bf812013-07-29 15:28:30 -0700258 /* load the image from file */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800259
260 if (!LoadImageFile (hwnd, szImgPathName,
261 &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
262 return 0;
263
Chris Craikca2bf812013-07-29 15:28:30 -0700264 /* invalidate the client area for later update */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800265
266 InvalidateRect (hwnd, NULL, TRUE);
267
Chris Craikca2bf812013-07-29 15:28:30 -0700268 /* display the PNG into the DIBitmap */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800269
270 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
271 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
272
273 return 0;
274
275 case IDM_FILE_SAVE:
276
Chris Craikca2bf812013-07-29 15:28:30 -0700277 /* show the File Save dialog box */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800278
279 if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName))
280 return 0;
281
Chris Craikca2bf812013-07-29 15:28:30 -0700282 /* save the PNG to a disk file */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800283
284 SetCursor (LoadCursor (NULL, IDC_WAIT));
285 ShowCursor (TRUE);
286
287 bOk = PngSaveImage (szImgPathName, pDiData, cxWinSize, cyWinSize,
288 bkgColor);
289
290 ShowCursor (FALSE);
291 SetCursor (LoadCursor (NULL, IDC_ARROW));
292
293 if (!bOk)
294 MessageBox (hwnd, TEXT ("Error in saving the PNG image"),
295 szProgName, MB_ICONEXCLAMATION | MB_OK);
296 return 0;
297
298 case IDM_FILE_NEXT:
299
Chris Craikca2bf812013-07-29 15:28:30 -0700300 /* read next entry in the directory */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800301
302 if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
303 NULL, szImgPathName))
304 {
305 if (strcmp (szImgPathName, "") == 0)
306 return 0;
Chris Craikca2bf812013-07-29 15:28:30 -0700307
308 /* load the image from file */
309
The Android Open Source Project893912b2009-03-03 19:30:05 -0800310 if (!LoadImageFile (hwnd, szImgPathName, &pbImage,
311 &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
312 return 0;
Chris Craikca2bf812013-07-29 15:28:30 -0700313
314 /* invalidate the client area for later update */
315
The Android Open Source Project893912b2009-03-03 19:30:05 -0800316 InvalidateRect (hwnd, NULL, TRUE);
Chris Craikca2bf812013-07-29 15:28:30 -0700317
318 /* display the PNG into the DIBitmap */
319
The Android Open Source Project893912b2009-03-03 19:30:05 -0800320 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
321 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
322 }
Chris Craikca2bf812013-07-29 15:28:30 -0700323
The Android Open Source Project893912b2009-03-03 19:30:05 -0800324 return 0;
325
326 case IDM_FILE_PREVIOUS:
327
Chris Craikca2bf812013-07-29 15:28:30 -0700328 /* read previous entry in the directory */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800329
330 if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
331 szImgPathName, NULL))
332 {
Chris Craikca2bf812013-07-29 15:28:30 -0700333
The Android Open Source Project893912b2009-03-03 19:30:05 -0800334 if (strcmp (szImgPathName, "") == 0)
335 return 0;
Chris Craikca2bf812013-07-29 15:28:30 -0700336
337 /* load the image from file */
338
The Android Open Source Project893912b2009-03-03 19:30:05 -0800339 if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize,
340 &cyImgSize, &cImgChannels, &bkgColor))
341 return 0;
Chris Craikca2bf812013-07-29 15:28:30 -0700342
343 /* invalidate the client area for later update */
344
The Android Open Source Project893912b2009-03-03 19:30:05 -0800345 InvalidateRect (hwnd, NULL, TRUE);
Chris Craikca2bf812013-07-29 15:28:30 -0700346
347 /* display the PNG into the DIBitmap */
348
The Android Open Source Project893912b2009-03-03 19:30:05 -0800349 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
350 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
351 }
352
353 return 0;
354
355 case IDM_FILE_EXIT:
356
Chris Craikca2bf812013-07-29 15:28:30 -0700357 /* more cleanup needed... */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800358
Chris Craikca2bf812013-07-29 15:28:30 -0700359 /* free image buffer */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800360
361 if (pDib != NULL)
362 {
363 free (pDib);
364 pDib = NULL;
365 }
366
Chris Craikca2bf812013-07-29 15:28:30 -0700367 /* free file-list */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800368
369 if (pPngFileList != NULL)
370 {
371 free (pPngFileList);
372 pPngFileList = NULL;
373 }
374
Chris Craikca2bf812013-07-29 15:28:30 -0700375 /* let's go ... */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800376
377 exit (0);
378
379 return 0;
380
381 case IDM_OPTIONS_STRETCH:
382 bStretched = !bStretched;
383 if (bStretched)
384 CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_CHECKED);
385 else
386 CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED);
387
Chris Craikca2bf812013-07-29 15:28:30 -0700388 /* invalidate the client area for later update */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800389
390 InvalidateRect (hwnd, NULL, TRUE);
391
Chris Craikca2bf812013-07-29 15:28:30 -0700392 /* display the PNG into the DIBitmap */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800393
394 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
395 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
396
397 return 0;
398
399 case IDM_HELP_ABOUT:
400 DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ;
401 return 0;
402
Chris Craikca2bf812013-07-29 15:28:30 -0700403 } /* end switch */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800404
405 break;
406
407 case WM_PAINT:
408 hdc = BeginPaint (hwnd, &ps);
409
410 if (pDib)
411 SetDIBitsToDevice (hdc, 0, 0, cxWinSize, cyWinSize, 0, 0,
412 0, cyWinSize, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS);
413
414 EndPaint (hwnd, &ps);
415 return 0;
416
417 case WM_DESTROY:
418 if (pbmfh)
419 {
420 free (pbmfh);
421 pbmfh = NULL;
422 }
423
424 PostQuitMessage (0);
425 return 0;
426 }
427
428 return DefWindowProc (hwnd, message, wParam, lParam);
429}
430
431BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,
432 WPARAM wParam, LPARAM lParam)
433{
434 switch (message)
435 {
436 case WM_INITDIALOG :
437 ShowWindow (hDlg, SW_HIDE);
438 CenterAbout (hDlg, GetWindow (hDlg, GW_OWNER));
439 ShowWindow (hDlg, SW_SHOW);
440 return TRUE ;
441
442 case WM_COMMAND :
443 switch (LOWORD (wParam))
444 {
445 case IDOK :
446 case IDCANCEL :
447 EndDialog (hDlg, 0) ;
448 return TRUE ;
449 }
450 break ;
451 }
452 return FALSE ;
453}
454
Chris Craikca2bf812013-07-29 15:28:30 -0700455/*---------------
456 * CenterAbout
457 *---------------
458 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800459BOOL CenterAbout (HWND hwndChild, HWND hwndParent)
460{
461 RECT rChild, rParent, rWorkArea;
462 int wChild, hChild, wParent, hParent;
463 int xNew, yNew;
464 BOOL bResult;
465
Chris Craikca2bf812013-07-29 15:28:30 -0700466 /* Get the Height and Width of the child window */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800467 GetWindowRect (hwndChild, &rChild);
468 wChild = rChild.right - rChild.left;
469 hChild = rChild.bottom - rChild.top;
470
Chris Craikca2bf812013-07-29 15:28:30 -0700471 /* Get the Height and Width of the parent window */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800472 GetWindowRect (hwndParent, &rParent);
473 wParent = rParent.right - rParent.left;
474 hParent = rParent.bottom - rParent.top;
475
Chris Craikca2bf812013-07-29 15:28:30 -0700476 /* Get the limits of the 'workarea' */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800477 bResult = SystemParametersInfo(
Chris Craikca2bf812013-07-29 15:28:30 -0700478 SPI_GETWORKAREA, /* system parameter to query or set */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800479 sizeof(RECT),
480 &rWorkArea,
481 0);
482 if (!bResult) {
483 rWorkArea.left = rWorkArea.top = 0;
484 rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
485 rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
486 }
487
Chris Craikca2bf812013-07-29 15:28:30 -0700488 /* Calculate new X position, then adjust for workarea */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800489 xNew = rParent.left + ((wParent - wChild) /2);
490 if (xNew < rWorkArea.left) {
491 xNew = rWorkArea.left;
492 } else if ((xNew+wChild) > rWorkArea.right) {
493 xNew = rWorkArea.right - wChild;
494 }
495
Chris Craikca2bf812013-07-29 15:28:30 -0700496 /* Calculate new Y position, then adjust for workarea */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800497 yNew = rParent.top + ((hParent - hChild) /2);
498 if (yNew < rWorkArea.top) {
499 yNew = rWorkArea.top;
500 } else if ((yNew+hChild) > rWorkArea.bottom) {
501 yNew = rWorkArea.bottom - hChild;
502 }
503
Chris Craikca2bf812013-07-29 15:28:30 -0700504 /* Set it, and return */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800505 return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE |
506 SWP_NOZORDER);
507}
508
Chris Craikca2bf812013-07-29 15:28:30 -0700509/*----------------
510 * BuildPngList
511 *----------------
512 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800513BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
514 int *pFileIndex)
515{
516 static TCHAR szImgPathName [MAX_PATH];
517 static TCHAR szImgFileName [MAX_PATH];
518 static TCHAR szImgFindName [MAX_PATH];
519
520 WIN32_FIND_DATA finddata;
521 HANDLE hFind;
522
523 static TCHAR szTmp [MAX_PATH];
524 BOOL bOk;
525 int i, ii;
526 int j, jj;
527
Chris Craikca2bf812013-07-29 15:28:30 -0700528 /* free previous file-list */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800529
530 if (*ppFileList != NULL)
531 {
532 free (*ppFileList);
533 *ppFileList = NULL;
534 }
535
Chris Craikca2bf812013-07-29 15:28:30 -0700536 /* extract foldername, filename and search-name */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800537
538 strcpy (szImgPathName, pstrPathName);
539 strcpy (szImgFileName, strrchr (pstrPathName, '\\') + 1);
540
541 strcpy (szImgFindName, szImgPathName);
542 *(strrchr (szImgFindName, '\\') + 1) = '\0';
543 strcat (szImgFindName, "*.png");
544
Chris Craikca2bf812013-07-29 15:28:30 -0700545 /* first cycle: count number of files in directory for memory allocation */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800546
547 *pFileCount = 0;
548
549 hFind = FindFirstFile(szImgFindName, &finddata);
550 bOk = (hFind != (HANDLE) -1);
551
552 while (bOk)
553 {
554 *pFileCount += 1;
555 bOk = FindNextFile(hFind, &finddata);
556 }
557 FindClose(hFind);
558
Chris Craikca2bf812013-07-29 15:28:30 -0700559 /* allocation memory for file-list */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800560
561 *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH);
562
Chris Craikca2bf812013-07-29 15:28:30 -0700563 /* second cycle: read directory and store filenames in file-list */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800564
565 hFind = FindFirstFile(szImgFindName, &finddata);
566 bOk = (hFind != (HANDLE) -1);
567
568 i = 0;
569 ii = 0;
570 while (bOk)
571 {
572 strcpy (*ppFileList + ii, szImgPathName);
573 strcpy (strrchr(*ppFileList + ii, '\\') + 1, finddata.cFileName);
574
575 if (strcmp(pstrPathName, *ppFileList + ii) == 0)
576 *pFileIndex = i;
577
578 ii += MAX_PATH;
579 i++;
580
581 bOk = FindNextFile(hFind, &finddata);
582 }
583 FindClose(hFind);
584
Chris Craikca2bf812013-07-29 15:28:30 -0700585 /* finally we must sort the file-list */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800586
587 for (i = 0; i < *pFileCount - 1; i++)
588 {
589 ii = i * MAX_PATH;
590 for (j = i+1; j < *pFileCount; j++)
591 {
592 jj = j * MAX_PATH;
593 if (strcmp (*ppFileList + ii, *ppFileList + jj) > 0)
594 {
595 strcpy (szTmp, *ppFileList + jj);
596 strcpy (*ppFileList + jj, *ppFileList + ii);
597 strcpy (*ppFileList + ii, szTmp);
598
Chris Craikca2bf812013-07-29 15:28:30 -0700599 /* check if this was the current image that we moved */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800600
601 if (*pFileIndex == i)
602 *pFileIndex = j;
603 else
604 if (*pFileIndex == j)
605 *pFileIndex = i;
606 }
607 }
608 }
609
610 return TRUE;
611}
612
Chris Craikca2bf812013-07-29 15:28:30 -0700613/*----------------
614 * SearchPngList
615 *----------------
616 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800617
618BOOL SearchPngList (
619 TCHAR *pFileList, int FileCount, int *pFileIndex,
620 PTSTR pstrPrevName, PTSTR pstrNextName)
621{
622 if (FileCount > 0)
623 {
Chris Craikca2bf812013-07-29 15:28:30 -0700624 /* get previous entry */
625
The Android Open Source Project893912b2009-03-03 19:30:05 -0800626 if (pstrPrevName != NULL)
627 {
628 if (*pFileIndex > 0)
629 *pFileIndex -= 1;
630 else
631 *pFileIndex = FileCount - 1;
Chris Craikca2bf812013-07-29 15:28:30 -0700632
The Android Open Source Project893912b2009-03-03 19:30:05 -0800633 strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH));
634 }
Chris Craikca2bf812013-07-29 15:28:30 -0700635
636 /* get next entry */
637
The Android Open Source Project893912b2009-03-03 19:30:05 -0800638 if (pstrNextName != NULL)
639 {
640 if (*pFileIndex < FileCount - 1)
641 *pFileIndex += 1;
642 else
643 *pFileIndex = 0;
Chris Craikca2bf812013-07-29 15:28:30 -0700644
The Android Open Source Project893912b2009-03-03 19:30:05 -0800645 strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH));
646 }
Chris Craikca2bf812013-07-29 15:28:30 -0700647
The Android Open Source Project893912b2009-03-03 19:30:05 -0800648 return TRUE;
649 }
650 else
651 {
652 return FALSE;
653 }
654}
655
Chris Craikca2bf812013-07-29 15:28:30 -0700656/*-----------------
657 * LoadImageFile
658 *-----------------
659 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800660
661BOOL LoadImageFile (HWND hwnd, PTSTR pstrPathName,
662 png_byte **ppbImage, int *pxImgSize, int *pyImgSize,
663 int *piChannels, png_color *pBkgColor)
664{
665 static TCHAR szTmp [MAX_PATH];
666
Chris Craikca2bf812013-07-29 15:28:30 -0700667 /* if there's an existing PNG, free the memory */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800668
669 if (*ppbImage)
670 {
671 free (*ppbImage);
672 *ppbImage = NULL;
673 }
674
Chris Craikca2bf812013-07-29 15:28:30 -0700675 /* Load the entire PNG into memory */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800676
677 SetCursor (LoadCursor (NULL, IDC_WAIT));
678 ShowCursor (TRUE);
679
680 PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels,
681 pBkgColor);
682
683 ShowCursor (FALSE);
684 SetCursor (LoadCursor (NULL, IDC_ARROW));
685
686 if (*ppbImage != NULL)
687 {
688 sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1);
689 SetWindowText (hwnd, szTmp);
690 }
691 else
692 {
693 MessageBox (hwnd, TEXT ("Error in loading the PNG image"),
694 szProgName, MB_ICONEXCLAMATION | MB_OK);
695 return FALSE;
696 }
697
698 return TRUE;
699}
700
Chris Craikca2bf812013-07-29 15:28:30 -0700701/*----------------
702 * DisplayImage
703 *----------------
704 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800705BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
706 BYTE **ppDiData, int cxWinSize, int cyWinSize,
707 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
708 BOOL bStretched)
709{
710 BYTE *pDib = *ppDib;
711 BYTE *pDiData = *ppDiData;
Chris Craikca2bf812013-07-29 15:28:30 -0700712 /* BITMAPFILEHEADER *pbmfh; */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800713 BITMAPINFOHEADER *pbmih;
714 WORD wDIRowBytes;
715 png_color bkgBlack = {0, 0, 0};
716 png_color bkgGray = {127, 127, 127};
717 png_color bkgWhite = {255, 255, 255};
718
Chris Craikca2bf812013-07-29 15:28:30 -0700719 /* allocate memory for the Device Independant bitmap */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800720
721 wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2;
722
723 if (pDib)
724 {
725 free (pDib);
726 pDib = NULL;
727 }
728
Leon Scroggins III3cc83ac2017-10-06 11:02:56 -0400729 if (cyWinSize > ((size_t)(-1))/wDIRowBytes) {
730 {
731 MessageBox (hwnd, TEXT ("Visual PNG: image is too big");
732 }
The Android Open Source Project893912b2009-03-03 19:30:05 -0800733 if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) +
734 wDIRowBytes * cyWinSize)))
735 {
736 MessageBox (hwnd, TEXT ("Error in displaying the PNG image"),
737 szProgName, MB_ICONEXCLAMATION | MB_OK);
738 *ppDib = pDib = NULL;
739 return FALSE;
740 }
741 *ppDib = pDib;
742 memset (pDib, 0, sizeof(BITMAPINFOHEADER));
743
Chris Craikca2bf812013-07-29 15:28:30 -0700744 /* initialize the dib-structure */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800745
746 pbmih = (BITMAPINFOHEADER *) pDib;
747 pbmih->biSize = sizeof(BITMAPINFOHEADER);
748 pbmih->biWidth = cxWinSize;
749 pbmih->biHeight = -((long) cyWinSize);
750 pbmih->biPlanes = 1;
751 pbmih->biBitCount = 24;
752 pbmih->biCompression = 0;
753 pDiData = pDib + sizeof(BITMAPINFOHEADER);
754 *ppDiData = pDiData;
755
Chris Craikca2bf812013-07-29 15:28:30 -0700756 /* first fill bitmap with gray and image border */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800757
758 InitBitmap (pDiData, cxWinSize, cyWinSize);
759
Chris Craikca2bf812013-07-29 15:28:30 -0700760 /* then fill bitmap with image */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800761
762 if (pbImage)
763 {
764 FillBitmap (
765 pDiData, cxWinSize, cyWinSize,
766 pbImage, cxImgSize, cyImgSize, cImgChannels,
767 bStretched);
768 }
769
770 return TRUE;
771}
772
Chris Craikca2bf812013-07-29 15:28:30 -0700773/*--------------
774 * InitBitmap
775 *--------------
776 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800777BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize)
778{
779 BYTE *dst;
780 int x, y, col;
781
Chris Craikca2bf812013-07-29 15:28:30 -0700782 /* initialize the background with gray */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800783
784 dst = pDiData;
785 for (y = 0; y < cyWinSize; y++)
786 {
787 col = 0;
788 for (x = 0; x < cxWinSize; x++)
789 {
Chris Craikca2bf812013-07-29 15:28:30 -0700790 /* fill with GRAY */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800791 *dst++ = 127;
792 *dst++ = 127;
793 *dst++ = 127;
794 col += 3;
795 }
Chris Craikca2bf812013-07-29 15:28:30 -0700796 /* rows start on 4 byte boundaries */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800797 while ((col % 4) != 0)
798 {
799 dst++;
800 col++;
801 }
802 }
803
804 return TRUE;
805}
806
Chris Craikca2bf812013-07-29 15:28:30 -0700807/*--------------
808 * FillBitmap
809 *--------------
810 */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800811BOOL FillBitmap (
812 BYTE *pDiData, int cxWinSize, int cyWinSize,
813 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
814 BOOL bStretched)
815{
816 BYTE *pStretchedImage;
817 BYTE *pImg;
818 BYTE *src, *dst;
819 BYTE r, g, b, a;
820 const int cDIChannels = 3;
821 WORD wImgRowBytes;
822 WORD wDIRowBytes;
823 int cxNewSize, cyNewSize;
824 int cxImgPos, cyImgPos;
825 int xImg, yImg;
826 int xWin, yWin;
827 int xOld, yOld;
828 int xNew, yNew;
829
830 if (bStretched)
831 {
832 cxNewSize = cxWinSize - 2 * MARGIN;
833 cyNewSize = cyWinSize - 2 * MARGIN;
834
Chris Craikca2bf812013-07-29 15:28:30 -0700835 /* stretch the image to it's window determined size */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800836
Chris Craikca2bf812013-07-29 15:28:30 -0700837 /* the following two are mathematically the same, but the first
838 * has side-effects because of rounding
839 */
840/* if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize)) */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800841 if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize))
842 {
843 cyNewSize = cxNewSize * cyImgSize / cxImgSize;
844 cxImgPos = MARGIN;
845 cyImgPos = (cyWinSize - cyNewSize) / 2;
846 }
847 else
848 {
849 cxNewSize = cyNewSize * cxImgSize / cyImgSize;
850 cyImgPos = MARGIN;
851 cxImgPos = (cxWinSize - cxNewSize) / 2;
852 }
853
Leon Scroggins III3cc83ac2017-10-06 11:02:56 -0400854 if (cyNewSize > ((size_t)(-1))/(cImgChannels * cxNewSize)) {
855 {
856 MessageBox (hwnd, TEXT ("Visual PNG: stretched image is too big");
857 }
The Android Open Source Project893912b2009-03-03 19:30:05 -0800858 pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize);
859 pImg = pStretchedImage;
860
861 for (yNew = 0; yNew < cyNewSize; yNew++)
862 {
863 yOld = yNew * cyImgSize / cyNewSize;
864 for (xNew = 0; xNew < cxNewSize; xNew++)
865 {
866 xOld = xNew * cxImgSize / cxNewSize;
867
868 r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0);
869 g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1);
870 b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2);
871 *pImg++ = r;
872 *pImg++ = g;
873 *pImg++ = b;
874 if (cImgChannels == 4)
875 {
876 a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld)
877 + 3);
878 *pImg++ = a;
879 }
880 }
881 }
882
Chris Craikca2bf812013-07-29 15:28:30 -0700883 /* calculate row-bytes */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800884
885 wImgRowBytes = cImgChannels * cxNewSize;
886 wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
887
Chris Craikca2bf812013-07-29 15:28:30 -0700888 /* copy image to screen */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800889
890 for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++)
891 {
892 if (yWin >= cyWinSize - cyImgPos)
893 break;
894 src = pStretchedImage + yImg * wImgRowBytes;
895 dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
896
897 for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++)
898 {
899 if (xWin >= cxWinSize - cxImgPos)
900 break;
901 r = *src++;
902 g = *src++;
903 b = *src++;
Chris Craikca2bf812013-07-29 15:28:30 -0700904 *dst++ = b; /* note the reverse order */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800905 *dst++ = g;
906 *dst++ = r;
907 if (cImgChannels == 4)
908 {
909 a = *src++;
910 }
911 }
912 }
913
Chris Craikca2bf812013-07-29 15:28:30 -0700914 /* free memory */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800915
916 if (pStretchedImage != NULL)
917 {
918 free (pStretchedImage);
919 pStretchedImage = NULL;
920 }
921
922 }
923
Chris Craikca2bf812013-07-29 15:28:30 -0700924 /* process the image not-stretched */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800925
926 else
927 {
Chris Craikca2bf812013-07-29 15:28:30 -0700928 /* calculate the central position */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800929
930 cxImgPos = (cxWinSize - cxImgSize) / 2;
931 cyImgPos = (cyWinSize - cyImgSize) / 2;
932
Chris Craikca2bf812013-07-29 15:28:30 -0700933 /* check for image larger than window */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800934
935 if (cxImgPos < MARGIN)
936 cxImgPos = MARGIN;
937 if (cyImgPos < MARGIN)
938 cyImgPos = MARGIN;
939
Chris Craikca2bf812013-07-29 15:28:30 -0700940 /* calculate both row-bytes */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800941
942 wImgRowBytes = cImgChannels * cxImgSize;
943 wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
944
Chris Craikca2bf812013-07-29 15:28:30 -0700945 /* copy image to screen */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800946
947 for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++)
948 {
949 if (yWin >= cyWinSize - MARGIN)
950 break;
951 src = pbImage + yImg * wImgRowBytes;
952 dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
953
954 for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++)
955 {
956 if (xWin >= cxWinSize - MARGIN)
957 break;
958 r = *src++;
959 g = *src++;
960 b = *src++;
Chris Craikca2bf812013-07-29 15:28:30 -0700961 *dst++ = b; /* note the reverse order */
The Android Open Source Project893912b2009-03-03 19:30:05 -0800962 *dst++ = g;
963 *dst++ = r;
964 if (cImgChannels == 4)
965 {
966 a = *src++;
967 }
968 }
969 }
970 }
971
972 return TRUE;
973}
974
Chris Craikca2bf812013-07-29 15:28:30 -0700975/*-----------------
976 * end of source
977 *-----------------
978 */