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