blob: 009f120e3564920896e3402426270020052a88bd [file] [log] [blame]
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -05001/*------------------------------------
2 * VisualPng.C -- Shows a PNG image
3 *------------------------------------
4 *
5 * Copyright 2000, Willem van Schaik.
6 *
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 */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050011
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050012/* switches */
Glenn Randers-Pehrson12a11c52009-07-19 13:31:53 -050013
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050014/* defines */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050015
16#define PROGNAME "VisualPng"
17#define LONGNAME "Win32 Viewer for PNG-files"
18#define VERSION "1.0 of 2000 June 07"
19
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050020/* constants */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050021
22#define MARGIN 8
23
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050024/* standard includes */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050025
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <windows.h>
30
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050031/* application includes */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050032
33#include "png.h"
34#include "pngfile.h"
35#include "resource.h"
36
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050037/* macros */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050038
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050039/* function prototypes */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050040
41LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
42BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
43
44BOOL CenterAbout (HWND hwndChild, HWND hwndParent);
45
46BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
47 int *pFileIndex);
48
49BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex,
50 PTSTR pstrPrevName, PTSTR pstrNextName);
51
52BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName,
53 png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels,
54 png_color *pBkgColor);
55
56BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
57 BYTE **ppDiData, int cxWinSize, int cyWinSize,
58 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
59 BOOL bStretched);
60
61BOOL InitBitmap (
62 BYTE *pDiData, int cxWinSize, int cyWinSize);
63
64BOOL FillBitmap (
65 BYTE *pDiData, int cxWinSize, int cyWinSize,
66 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
67 BOOL bStretched);
68
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050069/* a few global variables */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050070
71static char *szProgName = PROGNAME;
72static char *szAppName = LONGNAME;
73static char *szIconName = PROGNAME;
74static char szCmdFileName [MAX_PATH];
75
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050076/* MAIN routine */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050077
78int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
79 PSTR szCmdLine, int iCmdShow)
80{
81 HACCEL hAccel;
82 HWND hwnd;
83 MSG msg;
84 WNDCLASS wndclass;
85 int ixBorders, iyBorders;
86
87 wndclass.style = CS_HREDRAW | CS_VREDRAW;
88 wndclass.lpfnWndProc = WndProc;
89 wndclass.cbClsExtra = 0;
90 wndclass.cbWndExtra = 0;
91 wndclass.hInstance = hInstance;
92 wndclass.hIcon = LoadIcon (hInstance, szIconName) ;
93 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -050094 wndclass.hbrBackground = NULL; /* (HBRUSH) GetStockObject (GRAY_BRUSH); */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -050095 wndclass.lpszMenuName = szProgName;
96 wndclass.lpszClassName = szProgName;
97
98 if (!RegisterClass (&wndclass))
99 {
100 MessageBox (NULL, TEXT ("Error: this program requires Windows NT!"),
101 szProgName, MB_ICONERROR);
102 return 0;
103 }
104
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500105 /* if filename given on commandline, store it */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500106 if ((szCmdLine != NULL) && (*szCmdLine != '\0'))
107 if (szCmdLine[0] == '"')
108 strncpy (szCmdFileName, szCmdLine + 1, strlen(szCmdLine) - 2);
109 else
110 strcpy (szCmdFileName, szCmdLine);
111 else
112 strcpy (szCmdFileName, "");
113
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500114 /* calculate size of window-borders */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500115 ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) +
116 GetSystemMetrics (SM_CXDLGFRAME));
117 iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) +
118 GetSystemMetrics (SM_CYDLGFRAME)) +
119 GetSystemMetrics (SM_CYCAPTION) +
120 GetSystemMetrics (SM_CYMENUSIZE) +
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500121 1; /* WvS: don't ask me why? */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500122
123 hwnd = CreateWindow (szProgName, szAppName,
124 WS_OVERLAPPEDWINDOW,
125 CW_USEDEFAULT, CW_USEDEFAULT,
126 512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders,
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500127/* CW_USEDEFAULT, CW_USEDEFAULT, */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500128 NULL, NULL, hInstance, NULL);
129
130 ShowWindow (hwnd, iCmdShow);
131 UpdateWindow (hwnd);
132
133 hAccel = LoadAccelerators (hInstance, szProgName);
134
135 while (GetMessage (&msg, NULL, 0, 0))
136 {
137 if (!TranslateAccelerator (hwnd, hAccel, &msg))
138 {
139 TranslateMessage (&msg);
140 DispatchMessage (&msg);
141 }
142 }
143 return msg.wParam;
144}
145
146LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
147 LPARAM lParam)
148{
149 static HINSTANCE hInstance ;
150 static HDC hdc;
151 static PAINTSTRUCT ps;
152 static HMENU hMenu;
153
154 static BITMAPFILEHEADER *pbmfh;
155 static BITMAPINFOHEADER *pbmih;
156 static BYTE *pbImage;
157 static int cxWinSize, cyWinSize;
158 static int cxImgSize, cyImgSize;
159 static int cImgChannels;
160 static png_color bkgColor = {127, 127, 127};
161
162 static BOOL bStretched = TRUE;
163
164 static BYTE *pDib = NULL;
165 static BYTE *pDiData = NULL;
166
167 static TCHAR szImgPathName [MAX_PATH];
168 static TCHAR szTitleName [MAX_PATH];
169
170 static TCHAR *pPngFileList = NULL;
171 static int iPngFileCount;
172 static int iPngFileIndex;
173
174 BOOL bOk;
175
176 switch (message)
177 {
178 case WM_CREATE:
179 hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
180 PngFileInitialize (hwnd);
181
182 strcpy (szImgPathName, "");
183
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500184 /* in case we process file given on command-line */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500185
186 if (szCmdFileName[0] != '\0')
187 {
188 strcpy (szImgPathName, szCmdFileName);
189
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500190 /* read the other png-files in the directory for later */
191 /* next/previous commands */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500192
193 BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
194 &iPngFileIndex);
195
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500196 /* load the image from file */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500197
198 if (!LoadImageFile (hwnd, szImgPathName,
199 &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
200 return 0;
201
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500202 /* invalidate the client area for later update */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500203
204 InvalidateRect (hwnd, NULL, TRUE);
205
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500206 /* display the PNG into the DIBitmap */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500207
208 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
209 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
210 }
211
212 return 0;
213
214 case WM_SIZE:
215 cxWinSize = LOWORD (lParam);
216 cyWinSize = HIWORD (lParam);
217
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500218 /* invalidate the client area for later update */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500219
220 InvalidateRect (hwnd, NULL, TRUE);
221
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500222 /* display the PNG into the DIBitmap */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500223
224 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
225 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
226
227 return 0;
228
229 case WM_INITMENUPOPUP:
230 hMenu = GetMenu (hwnd);
231
232 if (pbImage)
233 EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_ENABLED);
234 else
235 EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_GRAYED);
236
237 return 0;
238
239 case WM_COMMAND:
240 hMenu = GetMenu (hwnd);
241
242 switch (LOWORD (wParam))
243 {
244 case IDM_FILE_OPEN:
245
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500246 /* show the File Open dialog box */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500247
248 if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName))
249 return 0;
250
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500251 /* read the other png-files in the directory for later */
252 /* next/previous commands */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500253
254 BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
255 &iPngFileIndex);
256
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500257 /* load the image from file */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500258
259 if (!LoadImageFile (hwnd, szImgPathName,
260 &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
261 return 0;
262
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500263 /* invalidate the client area for later update */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500264
265 InvalidateRect (hwnd, NULL, TRUE);
266
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500267 /* display the PNG into the DIBitmap */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500268
269 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
270 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
271
272 return 0;
273
274 case IDM_FILE_SAVE:
275
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500276 /* show the File Save dialog box */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500277
278 if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName))
279 return 0;
280
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500281 /* save the PNG to a disk file */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500282
283 SetCursor (LoadCursor (NULL, IDC_WAIT));
284 ShowCursor (TRUE);
285
286 bOk = PngSaveImage (szImgPathName, pDiData, cxWinSize, cyWinSize,
287 bkgColor);
288
289 ShowCursor (FALSE);
290 SetCursor (LoadCursor (NULL, IDC_ARROW));
291
292 if (!bOk)
293 MessageBox (hwnd, TEXT ("Error in saving the PNG image"),
294 szProgName, MB_ICONEXCLAMATION | MB_OK);
295 return 0;
296
297 case IDM_FILE_NEXT:
298
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500299 /* read next entry in the directory */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500300
301 if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
302 NULL, szImgPathName))
303 {
304 if (strcmp (szImgPathName, "") == 0)
305 return 0;
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500306
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500307 /* load the image from file */
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500308
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500309 if (!LoadImageFile (hwnd, szImgPathName, &pbImage,
310 &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
311 return 0;
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500312
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500313 /* invalidate the client area for later update */
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500314
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500315 InvalidateRect (hwnd, NULL, TRUE);
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500316
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500317 /* display the PNG into the DIBitmap */
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500318
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500319 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
320 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
321 }
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500322
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500323 return 0;
324
325 case IDM_FILE_PREVIOUS:
326
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500327 /* read previous entry in the directory */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500328
329 if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
330 szImgPathName, NULL))
331 {
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500332
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500333 if (strcmp (szImgPathName, "") == 0)
334 return 0;
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500335
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500336 /* load the image from file */
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500337
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500338 if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize,
339 &cyImgSize, &cImgChannels, &bkgColor))
340 return 0;
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500341
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500342 /* invalidate the client area for later update */
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500343
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500344 InvalidateRect (hwnd, NULL, TRUE);
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500345
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500346 /* display the PNG into the DIBitmap */
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500347
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500348 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
349 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
350 }
351
352 return 0;
353
354 case IDM_FILE_EXIT:
355
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500356 /* more cleanup needed... */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500357
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500358 /* free image buffer */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500359
360 if (pDib != NULL)
361 {
362 free (pDib);
363 pDib = NULL;
364 }
365
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500366 /* free file-list */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500367
368 if (pPngFileList != NULL)
369 {
370 free (pPngFileList);
371 pPngFileList = NULL;
372 }
373
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500374 /* let's go ... */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500375
376 exit (0);
377
378 return 0;
379
380 case IDM_OPTIONS_STRETCH:
381 bStretched = !bStretched;
382 if (bStretched)
383 CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_CHECKED);
384 else
385 CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED);
386
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500387 /* invalidate the client area for later update */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500388
389 InvalidateRect (hwnd, NULL, TRUE);
390
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500391 /* display the PNG into the DIBitmap */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500392
393 DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
394 pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
395
396 return 0;
397
398 case IDM_HELP_ABOUT:
399 DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ;
400 return 0;
401
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500402 } /* end switch */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500403
404 break;
405
406 case WM_PAINT:
407 hdc = BeginPaint (hwnd, &ps);
408
409 if (pDib)
410 SetDIBitsToDevice (hdc, 0, 0, cxWinSize, cyWinSize, 0, 0,
411 0, cyWinSize, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS);
412
413 EndPaint (hwnd, &ps);
414 return 0;
415
416 case WM_DESTROY:
417 if (pbmfh)
418 {
419 free (pbmfh);
420 pbmfh = NULL;
421 }
422
423 PostQuitMessage (0);
424 return 0;
425 }
426
427 return DefWindowProc (hwnd, message, wParam, lParam);
428}
429
430BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,
431 WPARAM wParam, LPARAM lParam)
432{
433 switch (message)
434 {
435 case WM_INITDIALOG :
436 ShowWindow (hDlg, SW_HIDE);
437 CenterAbout (hDlg, GetWindow (hDlg, GW_OWNER));
438 ShowWindow (hDlg, SW_SHOW);
439 return TRUE ;
440
441 case WM_COMMAND :
442 switch (LOWORD (wParam))
443 {
444 case IDOK :
445 case IDCANCEL :
446 EndDialog (hDlg, 0) ;
447 return TRUE ;
448 }
449 break ;
450 }
451 return FALSE ;
452}
453
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500454/*---------------
455 * CenterAbout
456 *---------------
457 */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500458BOOL CenterAbout (HWND hwndChild, HWND hwndParent)
459{
460 RECT rChild, rParent, rWorkArea;
461 int wChild, hChild, wParent, hParent;
462 int xNew, yNew;
463 BOOL bResult;
464
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500465 /* Get the Height and Width of the child window */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500466 GetWindowRect (hwndChild, &rChild);
467 wChild = rChild.right - rChild.left;
468 hChild = rChild.bottom - rChild.top;
469
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500470 /* Get the Height and Width of the parent window */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500471 GetWindowRect (hwndParent, &rParent);
472 wParent = rParent.right - rParent.left;
473 hParent = rParent.bottom - rParent.top;
474
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500475 /* Get the limits of the 'workarea' */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500476 bResult = SystemParametersInfo(
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500477 SPI_GETWORKAREA, /* system parameter to query or set */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500478 sizeof(RECT),
479 &rWorkArea,
480 0);
481 if (!bResult) {
482 rWorkArea.left = rWorkArea.top = 0;
483 rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
484 rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
485 }
486
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500487 /* Calculate new X position, then adjust for workarea */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500488 xNew = rParent.left + ((wParent - wChild) /2);
489 if (xNew < rWorkArea.left) {
490 xNew = rWorkArea.left;
491 } else if ((xNew+wChild) > rWorkArea.right) {
492 xNew = rWorkArea.right - wChild;
493 }
494
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500495 /* Calculate new Y position, then adjust for workarea */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500496 yNew = rParent.top + ((hParent - hChild) /2);
497 if (yNew < rWorkArea.top) {
498 yNew = rWorkArea.top;
499 } else if ((yNew+hChild) > rWorkArea.bottom) {
500 yNew = rWorkArea.bottom - hChild;
501 }
502
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500503 /* Set it, and return */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500504 return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE |
505 SWP_NOZORDER);
506}
507
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500508/*----------------
509 * BuildPngList
510 *----------------
511 */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500512BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
513 int *pFileIndex)
514{
515 static TCHAR szImgPathName [MAX_PATH];
516 static TCHAR szImgFileName [MAX_PATH];
517 static TCHAR szImgFindName [MAX_PATH];
518
519 WIN32_FIND_DATA finddata;
520 HANDLE hFind;
521
522 static TCHAR szTmp [MAX_PATH];
523 BOOL bOk;
524 int i, ii;
525 int j, jj;
526
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500527 /* free previous file-list */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500528
529 if (*ppFileList != NULL)
530 {
531 free (*ppFileList);
532 *ppFileList = NULL;
533 }
534
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500535 /* extract foldername, filename and search-name */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500536
537 strcpy (szImgPathName, pstrPathName);
538 strcpy (szImgFileName, strrchr (pstrPathName, '\\') + 1);
539
540 strcpy (szImgFindName, szImgPathName);
541 *(strrchr (szImgFindName, '\\') + 1) = '\0';
542 strcat (szImgFindName, "*.png");
543
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500544 /* first cycle: count number of files in directory for memory allocation */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500545
546 *pFileCount = 0;
547
548 hFind = FindFirstFile(szImgFindName, &finddata);
549 bOk = (hFind != (HANDLE) -1);
550
551 while (bOk)
552 {
553 *pFileCount += 1;
554 bOk = FindNextFile(hFind, &finddata);
555 }
556 FindClose(hFind);
557
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500558 /* allocation memory for file-list */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500559
560 *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH);
561
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500562 /* second cycle: read directory and store filenames in file-list */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500563
564 hFind = FindFirstFile(szImgFindName, &finddata);
565 bOk = (hFind != (HANDLE) -1);
566
567 i = 0;
568 ii = 0;
569 while (bOk)
570 {
571 strcpy (*ppFileList + ii, szImgPathName);
572 strcpy (strrchr(*ppFileList + ii, '\\') + 1, finddata.cFileName);
573
574 if (strcmp(pstrPathName, *ppFileList + ii) == 0)
575 *pFileIndex = i;
576
577 ii += MAX_PATH;
578 i++;
579
580 bOk = FindNextFile(hFind, &finddata);
581 }
582 FindClose(hFind);
583
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500584 /* finally we must sort the file-list */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500585
586 for (i = 0; i < *pFileCount - 1; i++)
587 {
588 ii = i * MAX_PATH;
589 for (j = i+1; j < *pFileCount; j++)
590 {
591 jj = j * MAX_PATH;
592 if (strcmp (*ppFileList + ii, *ppFileList + jj) > 0)
593 {
594 strcpy (szTmp, *ppFileList + jj);
595 strcpy (*ppFileList + jj, *ppFileList + ii);
596 strcpy (*ppFileList + ii, szTmp);
597
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500598 /* check if this was the current image that we moved */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500599
600 if (*pFileIndex == i)
601 *pFileIndex = j;
602 else
603 if (*pFileIndex == j)
604 *pFileIndex = i;
605 }
606 }
607 }
608
609 return TRUE;
610}
611
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500612/*----------------
613 * SearchPngList
614 *----------------
615 */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500616
617BOOL SearchPngList (
618 TCHAR *pFileList, int FileCount, int *pFileIndex,
619 PTSTR pstrPrevName, PTSTR pstrNextName)
620{
621 if (FileCount > 0)
622 {
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500623 /* get previous entry */
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500624
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500625 if (pstrPrevName != NULL)
626 {
627 if (*pFileIndex > 0)
628 *pFileIndex -= 1;
629 else
630 *pFileIndex = FileCount - 1;
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500631
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500632 strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH));
633 }
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500634
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500635 /* get next entry */
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500636
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500637 if (pstrNextName != NULL)
638 {
639 if (*pFileIndex < FileCount - 1)
640 *pFileIndex += 1;
641 else
642 *pFileIndex = 0;
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500643
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500644 strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH));
645 }
Glenn Randers-Pehrsonaf855e42011-05-07 10:52:49 -0500646
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500647 return TRUE;
648 }
649 else
650 {
651 return FALSE;
652 }
653}
654
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500655/*-----------------
656 * LoadImageFile
657 *-----------------
658 */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500659
660BOOL LoadImageFile (HWND hwnd, PTSTR pstrPathName,
661 png_byte **ppbImage, int *pxImgSize, int *pyImgSize,
662 int *piChannels, png_color *pBkgColor)
663{
664 static TCHAR szTmp [MAX_PATH];
665
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500666 /* if there's an existing PNG, free the memory */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500667
668 if (*ppbImage)
669 {
670 free (*ppbImage);
671 *ppbImage = NULL;
672 }
673
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500674 /* Load the entire PNG into memory */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500675
676 SetCursor (LoadCursor (NULL, IDC_WAIT));
677 ShowCursor (TRUE);
678
679 PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels,
680 pBkgColor);
681
682 ShowCursor (FALSE);
683 SetCursor (LoadCursor (NULL, IDC_ARROW));
684
685 if (*ppbImage != NULL)
686 {
687 sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1);
688 SetWindowText (hwnd, szTmp);
689 }
690 else
691 {
692 MessageBox (hwnd, TEXT ("Error in loading the PNG image"),
693 szProgName, MB_ICONEXCLAMATION | MB_OK);
694 return FALSE;
695 }
696
697 return TRUE;
698}
699
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500700/*----------------
701 * DisplayImage
702 *----------------
703 */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500704BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
705 BYTE **ppDiData, int cxWinSize, int cyWinSize,
706 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
707 BOOL bStretched)
708{
709 BYTE *pDib = *ppDib;
710 BYTE *pDiData = *ppDiData;
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500711 /* BITMAPFILEHEADER *pbmfh; */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500712 BITMAPINFOHEADER *pbmih;
713 WORD wDIRowBytes;
714 png_color bkgBlack = {0, 0, 0};
715 png_color bkgGray = {127, 127, 127};
716 png_color bkgWhite = {255, 255, 255};
717
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500718 /* allocate memory for the Device Independant bitmap */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500719
720 wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2;
721
722 if (pDib)
723 {
724 free (pDib);
725 pDib = NULL;
726 }
727
728 if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) +
729 wDIRowBytes * cyWinSize)))
730 {
731 MessageBox (hwnd, TEXT ("Error in displaying the PNG image"),
732 szProgName, MB_ICONEXCLAMATION | MB_OK);
733 *ppDib = pDib = NULL;
734 return FALSE;
735 }
736 *ppDib = pDib;
737 memset (pDib, 0, sizeof(BITMAPINFOHEADER));
738
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500739 /* initialize the dib-structure */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500740
741 pbmih = (BITMAPINFOHEADER *) pDib;
742 pbmih->biSize = sizeof(BITMAPINFOHEADER);
743 pbmih->biWidth = cxWinSize;
744 pbmih->biHeight = -((long) cyWinSize);
745 pbmih->biPlanes = 1;
746 pbmih->biBitCount = 24;
747 pbmih->biCompression = 0;
748 pDiData = pDib + sizeof(BITMAPINFOHEADER);
749 *ppDiData = pDiData;
750
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500751 /* first fill bitmap with gray and image border */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500752
753 InitBitmap (pDiData, cxWinSize, cyWinSize);
754
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500755 /* then fill bitmap with image */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500756
757 if (pbImage)
758 {
759 FillBitmap (
760 pDiData, cxWinSize, cyWinSize,
761 pbImage, cxImgSize, cyImgSize, cImgChannels,
762 bStretched);
763 }
764
765 return TRUE;
766}
767
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500768/*--------------
769 * InitBitmap
770 *--------------
771 */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500772BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize)
773{
774 BYTE *dst;
775 int x, y, col;
776
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500777 /* initialize the background with gray */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500778
779 dst = pDiData;
780 for (y = 0; y < cyWinSize; y++)
781 {
782 col = 0;
783 for (x = 0; x < cxWinSize; x++)
784 {
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500785 /* fill with GRAY */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500786 *dst++ = 127;
787 *dst++ = 127;
788 *dst++ = 127;
789 col += 3;
790 }
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500791 /* rows start on 4 byte boundaries */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500792 while ((col % 4) != 0)
793 {
794 dst++;
795 col++;
796 }
797 }
798
799 return TRUE;
800}
801
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500802/*--------------
803 * FillBitmap
804 *--------------
805 */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500806BOOL FillBitmap (
807 BYTE *pDiData, int cxWinSize, int cyWinSize,
808 BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
809 BOOL bStretched)
810{
811 BYTE *pStretchedImage;
812 BYTE *pImg;
813 BYTE *src, *dst;
814 BYTE r, g, b, a;
815 const int cDIChannels = 3;
816 WORD wImgRowBytes;
817 WORD wDIRowBytes;
818 int cxNewSize, cyNewSize;
819 int cxImgPos, cyImgPos;
820 int xImg, yImg;
821 int xWin, yWin;
822 int xOld, yOld;
823 int xNew, yNew;
824
825 if (bStretched)
826 {
827 cxNewSize = cxWinSize - 2 * MARGIN;
828 cyNewSize = cyWinSize - 2 * MARGIN;
829
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500830 /* stretch the image to it's window determined size */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500831
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500832 /* the following two are mathematically the same, but the first
833 * has side-effects because of rounding
834 */
835/* if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize)) */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500836 if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize))
837 {
838 cyNewSize = cxNewSize * cyImgSize / cxImgSize;
839 cxImgPos = MARGIN;
840 cyImgPos = (cyWinSize - cyNewSize) / 2;
841 }
842 else
843 {
844 cxNewSize = cyNewSize * cxImgSize / cyImgSize;
845 cyImgPos = MARGIN;
846 cxImgPos = (cxWinSize - cxNewSize) / 2;
847 }
848
849 pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize);
850 pImg = pStretchedImage;
851
852 for (yNew = 0; yNew < cyNewSize; yNew++)
853 {
854 yOld = yNew * cyImgSize / cyNewSize;
855 for (xNew = 0; xNew < cxNewSize; xNew++)
856 {
857 xOld = xNew * cxImgSize / cxNewSize;
858
859 r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0);
860 g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1);
861 b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2);
862 *pImg++ = r;
863 *pImg++ = g;
864 *pImg++ = b;
865 if (cImgChannels == 4)
866 {
867 a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld)
868 + 3);
869 *pImg++ = a;
870 }
871 }
872 }
873
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500874 /* calculate row-bytes */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500875
876 wImgRowBytes = cImgChannels * cxNewSize;
877 wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
878
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500879 /* copy image to screen */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500880
881 for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++)
882 {
883 if (yWin >= cyWinSize - cyImgPos)
884 break;
885 src = pStretchedImage + yImg * wImgRowBytes;
886 dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
887
888 for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++)
889 {
890 if (xWin >= cxWinSize - cxImgPos)
891 break;
892 r = *src++;
893 g = *src++;
894 b = *src++;
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500895 *dst++ = b; /* note the reverse order */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500896 *dst++ = g;
897 *dst++ = r;
898 if (cImgChannels == 4)
899 {
900 a = *src++;
901 }
902 }
903 }
904
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500905 /* free memory */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500906
907 if (pStretchedImage != NULL)
908 {
909 free (pStretchedImage);
910 pStretchedImage = NULL;
911 }
912
913 }
914
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500915 /* process the image not-stretched */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500916
917 else
918 {
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500919 /* calculate the central position */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500920
921 cxImgPos = (cxWinSize - cxImgSize) / 2;
922 cyImgPos = (cyWinSize - cyImgSize) / 2;
923
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500924 /* check for image larger than window */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500925
926 if (cxImgPos < MARGIN)
927 cxImgPos = MARGIN;
928 if (cyImgPos < MARGIN)
929 cyImgPos = MARGIN;
930
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500931 /* calculate both row-bytes */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500932
933 wImgRowBytes = cImgChannels * cxImgSize;
934 wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
935
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500936 /* copy image to screen */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500937
938 for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++)
939 {
940 if (yWin >= cyWinSize - MARGIN)
941 break;
942 src = pbImage + yImg * wImgRowBytes;
943 dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
944
945 for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++)
946 {
947 if (xWin >= cxWinSize - MARGIN)
948 break;
949 r = *src++;
950 g = *src++;
951 b = *src++;
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500952 *dst++ = b; /* note the reverse order */
Glenn Randers-Pehrsondb66d442000-06-23 21:38:16 -0500953 *dst++ = g;
954 *dst++ = r;
955 if (cImgChannels == 4)
956 {
957 a = *src++;
958 }
959 }
960 }
961 }
962
963 return TRUE;
964}
965
Glenn Randers-Pehrsonef43c172011-09-03 09:53:07 -0500966/*-----------------
967 * end of source
968 *-----------------
969 */