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 | |
---|
12 | /* switches */ |
---|
13 | |
---|
14 | /* defines */ |
---|
15 | |
---|
16 | #define PROGNAME "VisualPng" |
---|
17 | #define LONGNAME "Win32 Viewer for PNG-files" |
---|
18 | #define VERSION "1.0 of 2000 June 07" |
---|
19 | |
---|
20 | /* constants */ |
---|
21 | |
---|
22 | #define MARGIN 8 |
---|
23 | |
---|
24 | /* standard includes */ |
---|
25 | |
---|
26 | #include <stdio.h> |
---|
27 | #include <stdlib.h> |
---|
28 | #include <string.h> |
---|
29 | #include <windows.h> |
---|
30 | #include <zlib.h> |
---|
31 | |
---|
32 | /* application includes */ |
---|
33 | |
---|
34 | #include "png.h" |
---|
35 | #include "pngfile.h" |
---|
36 | #include "resource.h" |
---|
37 | |
---|
38 | /* macros */ |
---|
39 | |
---|
40 | /* function prototypes */ |
---|
41 | |
---|
42 | LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); |
---|
43 | BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ; |
---|
44 | |
---|
45 | BOOL CenterAbout (HWND hwndChild, HWND hwndParent); |
---|
46 | |
---|
47 | BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount, |
---|
48 | int *pFileIndex); |
---|
49 | |
---|
50 | BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex, |
---|
51 | PTSTR pstrPrevName, PTSTR pstrNextName); |
---|
52 | |
---|
53 | BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName, |
---|
54 | png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels, |
---|
55 | png_color *pBkgColor); |
---|
56 | |
---|
57 | BOOL 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 | |
---|
62 | BOOL InitBitmap ( |
---|
63 | BYTE *pDiData, int cxWinSize, int cyWinSize); |
---|
64 | |
---|
65 | BOOL FillBitmap ( |
---|
66 | BYTE *pDiData, int cxWinSize, int cyWinSize, |
---|
67 | BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, |
---|
68 | BOOL bStretched); |
---|
69 | |
---|
70 | /* a few global variables */ |
---|
71 | |
---|
72 | static char *szProgName = PROGNAME; |
---|
73 | static char *szAppName = LONGNAME; |
---|
74 | static char *szIconName = PROGNAME; |
---|
75 | static char szCmdFileName [MAX_PATH]; |
---|
76 | |
---|
77 | /* MAIN routine */ |
---|
78 | |
---|
79 | int 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); |
---|
95 | wndclass.hbrBackground = NULL; /* (HBRUSH) GetStockObject (GRAY_BRUSH); */ |
---|
96 | 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 | |
---|
106 | /* if filename given on commandline, store it */ |
---|
107 | 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 | |
---|
115 | /* calculate size of window-borders */ |
---|
116 | 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) + |
---|
122 | 1; /* WvS: don't ask me why? */ |
---|
123 | |
---|
124 | hwnd = CreateWindow (szProgName, szAppName, |
---|
125 | WS_OVERLAPPEDWINDOW, |
---|
126 | CW_USEDEFAULT, CW_USEDEFAULT, |
---|
127 | 512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders, |
---|
128 | /* CW_USEDEFAULT, CW_USEDEFAULT, */ |
---|
129 | 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 | |
---|
147 | LRESULT 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 | |
---|
185 | /* in case we process file given on command-line */ |
---|
186 | |
---|
187 | if (szCmdFileName[0] != '\0') |
---|
188 | { |
---|
189 | strcpy (szImgPathName, szCmdFileName); |
---|
190 | |
---|
191 | /* read the other png-files in the directory for later */ |
---|
192 | /* next/previous commands */ |
---|
193 | |
---|
194 | BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount, |
---|
195 | &iPngFileIndex); |
---|
196 | |
---|
197 | /* load the image from file */ |
---|
198 | |
---|
199 | if (!LoadImageFile (hwnd, szImgPathName, |
---|
200 | &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) |
---|
201 | return 0; |
---|
202 | |
---|
203 | /* invalidate the client area for later update */ |
---|
204 | |
---|
205 | InvalidateRect (hwnd, NULL, TRUE); |
---|
206 | |
---|
207 | /* display the PNG into the DIBitmap */ |
---|
208 | |
---|
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 | |
---|
219 | /* invalidate the client area for later update */ |
---|
220 | |
---|
221 | InvalidateRect (hwnd, NULL, TRUE); |
---|
222 | |
---|
223 | /* display the PNG into the DIBitmap */ |
---|
224 | |
---|
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 | |
---|
247 | /* show the File Open dialog box */ |
---|
248 | |
---|
249 | if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName)) |
---|
250 | return 0; |
---|
251 | |
---|
252 | /* read the other png-files in the directory for later */ |
---|
253 | /* next/previous commands */ |
---|
254 | |
---|
255 | BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount, |
---|
256 | &iPngFileIndex); |
---|
257 | |
---|
258 | /* load the image from file */ |
---|
259 | |
---|
260 | if (!LoadImageFile (hwnd, szImgPathName, |
---|
261 | &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) |
---|
262 | return 0; |
---|
263 | |
---|
264 | /* invalidate the client area for later update */ |
---|
265 | |
---|
266 | InvalidateRect (hwnd, NULL, TRUE); |
---|
267 | |
---|
268 | /* display the PNG into the DIBitmap */ |
---|
269 | |
---|
270 | DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, |
---|
271 | pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); |
---|
272 | |
---|
273 | return 0; |
---|
274 | |
---|
275 | case IDM_FILE_SAVE: |
---|
276 | |
---|
277 | /* show the File Save dialog box */ |
---|
278 | |
---|
279 | if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName)) |
---|
280 | return 0; |
---|
281 | |
---|
282 | /* save the PNG to a disk file */ |
---|
283 | |
---|
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 | |
---|
300 | /* read next entry in the directory */ |
---|
301 | |
---|
302 | if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex, |
---|
303 | NULL, szImgPathName)) |
---|
304 | { |
---|
305 | if (strcmp (szImgPathName, "") == 0) |
---|
306 | return 0; |
---|
307 | |
---|
308 | /* load the image from file */ |
---|
309 | |
---|
310 | if (!LoadImageFile (hwnd, szImgPathName, &pbImage, |
---|
311 | &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) |
---|
312 | return 0; |
---|
313 | |
---|
314 | /* invalidate the client area for later update */ |
---|
315 | |
---|
316 | InvalidateRect (hwnd, NULL, TRUE); |
---|
317 | |
---|
318 | /* display the PNG into the DIBitmap */ |
---|
319 | |
---|
320 | DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, |
---|
321 | pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); |
---|
322 | } |
---|
323 | |
---|
324 | return 0; |
---|
325 | |
---|
326 | case IDM_FILE_PREVIOUS: |
---|
327 | |
---|
328 | /* read previous entry in the directory */ |
---|
329 | |
---|
330 | if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex, |
---|
331 | szImgPathName, NULL)) |
---|
332 | { |
---|
333 | |
---|
334 | if (strcmp (szImgPathName, "") == 0) |
---|
335 | return 0; |
---|
336 | |
---|
337 | /* load the image from file */ |
---|
338 | |
---|
339 | if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize, |
---|
340 | &cyImgSize, &cImgChannels, &bkgColor)) |
---|
341 | return 0; |
---|
342 | |
---|
343 | /* invalidate the client area for later update */ |
---|
344 | |
---|
345 | InvalidateRect (hwnd, NULL, TRUE); |
---|
346 | |
---|
347 | /* display the PNG into the DIBitmap */ |
---|
348 | |
---|
349 | DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, |
---|
350 | pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); |
---|
351 | } |
---|
352 | |
---|
353 | return 0; |
---|
354 | |
---|
355 | case IDM_FILE_EXIT: |
---|
356 | |
---|
357 | /* more cleanup needed... */ |
---|
358 | |
---|
359 | /* free image buffer */ |
---|
360 | |
---|
361 | if (pDib != NULL) |
---|
362 | { |
---|
363 | free (pDib); |
---|
364 | pDib = NULL; |
---|
365 | } |
---|
366 | |
---|
367 | /* free file-list */ |
---|
368 | |
---|
369 | if (pPngFileList != NULL) |
---|
370 | { |
---|
371 | free (pPngFileList); |
---|
372 | pPngFileList = NULL; |
---|
373 | } |
---|
374 | |
---|
375 | /* let's go ... */ |
---|
376 | |
---|
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 | |
---|
388 | /* invalidate the client area for later update */ |
---|
389 | |
---|
390 | InvalidateRect (hwnd, NULL, TRUE); |
---|
391 | |
---|
392 | /* display the PNG into the DIBitmap */ |
---|
393 | |
---|
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 | |
---|
403 | } /* end switch */ |
---|
404 | |
---|
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 | |
---|
431 | BOOL 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 | |
---|
455 | /*--------------- |
---|
456 | * CenterAbout |
---|
457 | *--------------- |
---|
458 | */ |
---|
459 | BOOL 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 | |
---|
466 | /* Get the Height and Width of the child window */ |
---|
467 | GetWindowRect (hwndChild, &rChild); |
---|
468 | wChild = rChild.right - rChild.left; |
---|
469 | hChild = rChild.bottom - rChild.top; |
---|
470 | |
---|
471 | /* Get the Height and Width of the parent window */ |
---|
472 | GetWindowRect (hwndParent, &rParent); |
---|
473 | wParent = rParent.right - rParent.left; |
---|
474 | hParent = rParent.bottom - rParent.top; |
---|
475 | |
---|
476 | /* Get the limits of the 'workarea' */ |
---|
477 | bResult = SystemParametersInfo( |
---|
478 | SPI_GETWORKAREA, /* system parameter to query or set */ |
---|
479 | 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 | |
---|
488 | /* Calculate new X position, then adjust for workarea */ |
---|
489 | 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 | |
---|
496 | /* Calculate new Y position, then adjust for workarea */ |
---|
497 | 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 | |
---|
504 | /* Set it, and return */ |
---|
505 | return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | |
---|
506 | SWP_NOZORDER); |
---|
507 | } |
---|
508 | |
---|
509 | /*---------------- |
---|
510 | * BuildPngList |
---|
511 | *---------------- |
---|
512 | */ |
---|
513 | BOOL 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 | |
---|
528 | /* free previous file-list */ |
---|
529 | |
---|
530 | if (*ppFileList != NULL) |
---|
531 | { |
---|
532 | free (*ppFileList); |
---|
533 | *ppFileList = NULL; |
---|
534 | } |
---|
535 | |
---|
536 | /* extract foldername, filename and search-name */ |
---|
537 | |
---|
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 | |
---|
545 | /* first cycle: count number of files in directory for memory allocation */ |
---|
546 | |
---|
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 | |
---|
559 | /* allocation memory for file-list */ |
---|
560 | |
---|
561 | *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH); |
---|
562 | |
---|
563 | /* second cycle: read directory and store filenames in file-list */ |
---|
564 | |
---|
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 | |
---|
585 | /* finally we must sort the file-list */ |
---|
586 | |
---|
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 | |
---|
599 | /* check if this was the current image that we moved */ |
---|
600 | |
---|
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 | |
---|
613 | /*---------------- |
---|
614 | * SearchPngList |
---|
615 | *---------------- |
---|
616 | */ |
---|
617 | |
---|
618 | BOOL SearchPngList ( |
---|
619 | TCHAR *pFileList, int FileCount, int *pFileIndex, |
---|
620 | PTSTR pstrPrevName, PTSTR pstrNextName) |
---|
621 | { |
---|
622 | if (FileCount > 0) |
---|
623 | { |
---|
624 | /* get previous entry */ |
---|
625 | |
---|
626 | if (pstrPrevName != NULL) |
---|
627 | { |
---|
628 | if (*pFileIndex > 0) |
---|
629 | *pFileIndex -= 1; |
---|
630 | else |
---|
631 | *pFileIndex = FileCount - 1; |
---|
632 | |
---|
633 | strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH)); |
---|
634 | } |
---|
635 | |
---|
636 | /* get next entry */ |
---|
637 | |
---|
638 | if (pstrNextName != NULL) |
---|
639 | { |
---|
640 | if (*pFileIndex < FileCount - 1) |
---|
641 | *pFileIndex += 1; |
---|
642 | else |
---|
643 | *pFileIndex = 0; |
---|
644 | |
---|
645 | strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH)); |
---|
646 | } |
---|
647 | |
---|
648 | return TRUE; |
---|
649 | } |
---|
650 | else |
---|
651 | { |
---|
652 | return FALSE; |
---|
653 | } |
---|
654 | } |
---|
655 | |
---|
656 | /*----------------- |
---|
657 | * LoadImageFile |
---|
658 | *----------------- |
---|
659 | */ |
---|
660 | |
---|
661 | BOOL 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 | |
---|
667 | /* if there's an existing PNG, free the memory */ |
---|
668 | |
---|
669 | if (*ppbImage) |
---|
670 | { |
---|
671 | free (*ppbImage); |
---|
672 | *ppbImage = NULL; |
---|
673 | } |
---|
674 | |
---|
675 | /* Load the entire PNG into memory */ |
---|
676 | |
---|
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 | |
---|
701 | /*---------------- |
---|
702 | * DisplayImage |
---|
703 | *---------------- |
---|
704 | */ |
---|
705 | BOOL 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; |
---|
712 | /* BITMAPFILEHEADER *pbmfh; */ |
---|
713 | 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 | |
---|
719 | /* allocate memory for the Device Independant bitmap */ |
---|
720 | |
---|
721 | wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2; |
---|
722 | |
---|
723 | if (pDib) |
---|
724 | { |
---|
725 | free (pDib); |
---|
726 | pDib = NULL; |
---|
727 | } |
---|
728 | |
---|
729 | if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) + |
---|
730 | wDIRowBytes * cyWinSize))) |
---|
731 | { |
---|
732 | MessageBox (hwnd, TEXT ("Error in displaying the PNG image"), |
---|
733 | szProgName, MB_ICONEXCLAMATION | MB_OK); |
---|
734 | *ppDib = pDib = NULL; |
---|
735 | return FALSE; |
---|
736 | } |
---|
737 | *ppDib = pDib; |
---|
738 | memset (pDib, 0, sizeof(BITMAPINFOHEADER)); |
---|
739 | |
---|
740 | /* initialize the dib-structure */ |
---|
741 | |
---|
742 | pbmih = (BITMAPINFOHEADER *) pDib; |
---|
743 | pbmih->biSize = sizeof(BITMAPINFOHEADER); |
---|
744 | pbmih->biWidth = cxWinSize; |
---|
745 | pbmih->biHeight = -((long) cyWinSize); |
---|
746 | pbmih->biPlanes = 1; |
---|
747 | pbmih->biBitCount = 24; |
---|
748 | pbmih->biCompression = 0; |
---|
749 | pDiData = pDib + sizeof(BITMAPINFOHEADER); |
---|
750 | *ppDiData = pDiData; |
---|
751 | |
---|
752 | /* first fill bitmap with gray and image border */ |
---|
753 | |
---|
754 | InitBitmap (pDiData, cxWinSize, cyWinSize); |
---|
755 | |
---|
756 | /* then fill bitmap with image */ |
---|
757 | |
---|
758 | if (pbImage) |
---|
759 | { |
---|
760 | FillBitmap ( |
---|
761 | pDiData, cxWinSize, cyWinSize, |
---|
762 | pbImage, cxImgSize, cyImgSize, cImgChannels, |
---|
763 | bStretched); |
---|
764 | } |
---|
765 | |
---|
766 | return TRUE; |
---|
767 | } |
---|
768 | |
---|
769 | /*-------------- |
---|
770 | * InitBitmap |
---|
771 | *-------------- |
---|
772 | */ |
---|
773 | BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize) |
---|
774 | { |
---|
775 | BYTE *dst; |
---|
776 | int x, y, col; |
---|
777 | |
---|
778 | /* initialize the background with gray */ |
---|
779 | |
---|
780 | dst = pDiData; |
---|
781 | for (y = 0; y < cyWinSize; y++) |
---|
782 | { |
---|
783 | col = 0; |
---|
784 | for (x = 0; x < cxWinSize; x++) |
---|
785 | { |
---|
786 | /* fill with GRAY */ |
---|
787 | *dst++ = 127; |
---|
788 | *dst++ = 127; |
---|
789 | *dst++ = 127; |
---|
790 | col += 3; |
---|
791 | } |
---|
792 | /* rows start on 4 byte boundaries */ |
---|
793 | while ((col % 4) != 0) |
---|
794 | { |
---|
795 | dst++; |
---|
796 | col++; |
---|
797 | } |
---|
798 | } |
---|
799 | |
---|
800 | return TRUE; |
---|
801 | } |
---|
802 | |
---|
803 | /*-------------- |
---|
804 | * FillBitmap |
---|
805 | *-------------- |
---|
806 | */ |
---|
807 | BOOL FillBitmap ( |
---|
808 | BYTE *pDiData, int cxWinSize, int cyWinSize, |
---|
809 | BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, |
---|
810 | BOOL bStretched) |
---|
811 | { |
---|
812 | BYTE *pStretchedImage; |
---|
813 | BYTE *pImg; |
---|
814 | BYTE *src, *dst; |
---|
815 | BYTE r, g, b, a; |
---|
816 | const int cDIChannels = 3; |
---|
817 | WORD wImgRowBytes; |
---|
818 | WORD wDIRowBytes; |
---|
819 | int cxNewSize, cyNewSize; |
---|
820 | int cxImgPos, cyImgPos; |
---|
821 | int xImg, yImg; |
---|
822 | int xWin, yWin; |
---|
823 | int xOld, yOld; |
---|
824 | int xNew, yNew; |
---|
825 | |
---|
826 | if (bStretched) |
---|
827 | { |
---|
828 | cxNewSize = cxWinSize - 2 * MARGIN; |
---|
829 | cyNewSize = cyWinSize - 2 * MARGIN; |
---|
830 | |
---|
831 | /* stretch the image to it's window determined size */ |
---|
832 | |
---|
833 | /* the following two are mathematically the same, but the first |
---|
834 | * has side-effects because of rounding |
---|
835 | */ |
---|
836 | /* if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize)) */ |
---|
837 | if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize)) |
---|
838 | { |
---|
839 | cyNewSize = cxNewSize * cyImgSize / cxImgSize; |
---|
840 | cxImgPos = MARGIN; |
---|
841 | cyImgPos = (cyWinSize - cyNewSize) / 2; |
---|
842 | } |
---|
843 | else |
---|
844 | { |
---|
845 | cxNewSize = cyNewSize * cxImgSize / cyImgSize; |
---|
846 | cyImgPos = MARGIN; |
---|
847 | cxImgPos = (cxWinSize - cxNewSize) / 2; |
---|
848 | } |
---|
849 | |
---|
850 | pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize); |
---|
851 | pImg = pStretchedImage; |
---|
852 | |
---|
853 | for (yNew = 0; yNew < cyNewSize; yNew++) |
---|
854 | { |
---|
855 | yOld = yNew * cyImgSize / cyNewSize; |
---|
856 | for (xNew = 0; xNew < cxNewSize; xNew++) |
---|
857 | { |
---|
858 | xOld = xNew * cxImgSize / cxNewSize; |
---|
859 | |
---|
860 | r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0); |
---|
861 | g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1); |
---|
862 | b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2); |
---|
863 | *pImg++ = r; |
---|
864 | *pImg++ = g; |
---|
865 | *pImg++ = b; |
---|
866 | if (cImgChannels == 4) |
---|
867 | { |
---|
868 | a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) |
---|
869 | + 3); |
---|
870 | *pImg++ = a; |
---|
871 | } |
---|
872 | } |
---|
873 | } |
---|
874 | |
---|
875 | /* calculate row-bytes */ |
---|
876 | |
---|
877 | wImgRowBytes = cImgChannels * cxNewSize; |
---|
878 | wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2; |
---|
879 | |
---|
880 | /* copy image to screen */ |
---|
881 | |
---|
882 | for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++) |
---|
883 | { |
---|
884 | if (yWin >= cyWinSize - cyImgPos) |
---|
885 | break; |
---|
886 | src = pStretchedImage + yImg * wImgRowBytes; |
---|
887 | dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels; |
---|
888 | |
---|
889 | for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++) |
---|
890 | { |
---|
891 | if (xWin >= cxWinSize - cxImgPos) |
---|
892 | break; |
---|
893 | r = *src++; |
---|
894 | g = *src++; |
---|
895 | b = *src++; |
---|
896 | *dst++ = b; /* note the reverse order */ |
---|
897 | *dst++ = g; |
---|
898 | *dst++ = r; |
---|
899 | if (cImgChannels == 4) |
---|
900 | { |
---|
901 | a = *src++; |
---|
902 | } |
---|
903 | } |
---|
904 | } |
---|
905 | |
---|
906 | /* free memory */ |
---|
907 | |
---|
908 | if (pStretchedImage != NULL) |
---|
909 | { |
---|
910 | free (pStretchedImage); |
---|
911 | pStretchedImage = NULL; |
---|
912 | } |
---|
913 | |
---|
914 | } |
---|
915 | |
---|
916 | /* process the image not-stretched */ |
---|
917 | |
---|
918 | else |
---|
919 | { |
---|
920 | /* calculate the central position */ |
---|
921 | |
---|
922 | cxImgPos = (cxWinSize - cxImgSize) / 2; |
---|
923 | cyImgPos = (cyWinSize - cyImgSize) / 2; |
---|
924 | |
---|
925 | /* check for image larger than window */ |
---|
926 | |
---|
927 | if (cxImgPos < MARGIN) |
---|
928 | cxImgPos = MARGIN; |
---|
929 | if (cyImgPos < MARGIN) |
---|
930 | cyImgPos = MARGIN; |
---|
931 | |
---|
932 | /* calculate both row-bytes */ |
---|
933 | |
---|
934 | wImgRowBytes = cImgChannels * cxImgSize; |
---|
935 | wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2; |
---|
936 | |
---|
937 | /* copy image to screen */ |
---|
938 | |
---|
939 | for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++) |
---|
940 | { |
---|
941 | if (yWin >= cyWinSize - MARGIN) |
---|
942 | break; |
---|
943 | src = pbImage + yImg * wImgRowBytes; |
---|
944 | dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels; |
---|
945 | |
---|
946 | for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++) |
---|
947 | { |
---|
948 | if (xWin >= cxWinSize - MARGIN) |
---|
949 | break; |
---|
950 | r = *src++; |
---|
951 | g = *src++; |
---|
952 | b = *src++; |
---|
953 | *dst++ = b; /* note the reverse order */ |
---|
954 | *dst++ = g; |
---|
955 | *dst++ = r; |
---|
956 | if (cImgChannels == 4) |
---|
957 | { |
---|
958 | a = *src++; |
---|
959 | } |
---|
960 | } |
---|
961 | } |
---|
962 | } |
---|
963 | |
---|
964 | return TRUE; |
---|
965 | } |
---|
966 | |
---|
967 | /*----------------- |
---|
968 | * end of source |
---|
969 | *----------------- |
---|
970 | */ |
---|