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