1
//------------------------------------
2
// VisualPng.C -- Shows a PNG image
3
//------------------------------------
5
// Copyright 2000, Willem van Schaik.
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
1
/*------------------------------------
2
* VisualPng.C -- Shows a PNG image
3
*------------------------------------
5
* Copyright 2000, Willem van Schaik.
7
* This code is released under the libpng license.
8
* For conditions of distribution and use, see the disclaimer
15
16
#define PROGNAME "VisualPng"
16
17
#define LONGNAME "Win32 Viewer for PNG-files"
17
18
#define VERSION "1.0 of 2000 June 07"
24
/* standard includes */
26
27
#include <stdlib.h>
27
28
#include <string.h>
28
29
#include <windows.h>
30
// application includes
32
/* application includes */
33
35
#include "pngfile.h"
34
36
#include "resource.h"
38
// function prototypes
40
/* function prototypes */
40
42
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
41
43
BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
65
67
BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
68
// a few global variables
70
/* a few global variables */
70
72
static char *szProgName = PROGNAME;
71
73
static char *szAppName = LONGNAME;
72
74
static char *szIconName = PROGNAME;
73
75
static char szCmdFileName [MAX_PATH];
77
79
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
78
80
PSTR szCmdLine, int iCmdShow)
90
92
wndclass.hInstance = hInstance;
91
93
wndclass.hIcon = LoadIcon (hInstance, szIconName) ;
92
94
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
93
wndclass.hbrBackground = NULL; // (HBRUSH) GetStockObject (GRAY_BRUSH);
95
wndclass.hbrBackground = NULL; /* (HBRUSH) GetStockObject (GRAY_BRUSH); */
94
96
wndclass.lpszMenuName = szProgName;
95
97
wndclass.lpszClassName = szProgName;
111
113
strcpy (szCmdFileName, "");
113
// calculate size of window-borders
115
/* calculate size of window-borders */
114
116
ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) +
115
117
GetSystemMetrics (SM_CXDLGFRAME));
116
118
iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) +
117
119
GetSystemMetrics (SM_CYDLGFRAME)) +
118
120
GetSystemMetrics (SM_CYCAPTION) +
119
121
GetSystemMetrics (SM_CYMENUSIZE) +
120
1; /* WvS: don't ask me why? */
122
1; /* WvS: don't ask me why? */
122
124
hwnd = CreateWindow (szProgName, szAppName,
123
125
WS_OVERLAPPEDWINDOW,
124
126
CW_USEDEFAULT, CW_USEDEFAULT,
125
127
512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders,
126
// CW_USEDEFAULT, CW_USEDEFAULT,
128
/* CW_USEDEFAULT, CW_USEDEFAULT, */
127
129
NULL, NULL, hInstance, NULL);
129
131
ShowWindow (hwnd, iCmdShow);
181
183
strcpy (szImgPathName, "");
183
// in case we process file given on command-line
185
/* in case we process file given on command-line */
185
187
if (szCmdFileName[0] != '\0')
187
189
strcpy (szImgPathName, szCmdFileName);
189
// read the other png-files in the directory for later
190
// next/previous commands
191
/* read the other png-files in the directory for later */
192
/* next/previous commands */
192
194
BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
195
// load the image from file
197
/* load the image from file */
197
199
if (!LoadImageFile (hwnd, szImgPathName,
198
200
&pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
201
// invalidate the client area for later update
203
/* invalidate the client area for later update */
203
205
InvalidateRect (hwnd, NULL, TRUE);
205
// display the PNG into the DIBitmap
207
/* display the PNG into the DIBitmap */
207
209
DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
208
210
pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
214
216
cxWinSize = LOWORD (lParam);
215
217
cyWinSize = HIWORD (lParam);
217
// invalidate the client area for later update
219
/* invalidate the client area for later update */
219
221
InvalidateRect (hwnd, NULL, TRUE);
221
// display the PNG into the DIBitmap
223
/* display the PNG into the DIBitmap */
223
225
DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
224
226
pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
243
245
case IDM_FILE_OPEN:
245
// show the File Open dialog box
247
/* show the File Open dialog box */
247
249
if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName))
250
// read the other png-files in the directory for later
251
// next/previous commands
252
/* read the other png-files in the directory for later */
253
/* next/previous commands */
253
255
BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
256
// load the image from file
258
/* load the image from file */
258
260
if (!LoadImageFile (hwnd, szImgPathName,
259
261
&pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
262
// invalidate the client area for later update
264
/* invalidate the client area for later update */
264
266
InvalidateRect (hwnd, NULL, TRUE);
266
// display the PNG into the DIBitmap
268
/* display the PNG into the DIBitmap */
268
270
DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
269
271
pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
273
275
case IDM_FILE_SAVE:
275
// show the File Save dialog box
277
/* show the File Save dialog box */
277
279
if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName))
280
// save the PNG to a disk file
282
/* save the PNG to a disk file */
282
284
SetCursor (LoadCursor (NULL, IDC_WAIT));
283
285
ShowCursor (TRUE);
296
298
case IDM_FILE_NEXT:
298
// read next entry in the directory
300
/* read next entry in the directory */
300
302
if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
301
303
NULL, szImgPathName))
303
305
if (strcmp (szImgPathName, "") == 0)
306
// load the image from file
308
/* load the image from file */
308
310
if (!LoadImageFile (hwnd, szImgPathName, &pbImage,
309
311
&cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
312
// invalidate the client area for later update
314
/* invalidate the client area for later update */
314
316
InvalidateRect (hwnd, NULL, TRUE);
316
// display the PNG into the DIBitmap
318
/* display the PNG into the DIBitmap */
318
320
DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
319
321
pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
324
326
case IDM_FILE_PREVIOUS:
326
// read previous entry in the directory
328
/* read previous entry in the directory */
328
330
if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
329
331
szImgPathName, NULL))
332
334
if (strcmp (szImgPathName, "") == 0)
335
// load the image from file
337
/* load the image from file */
337
339
if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize,
338
340
&cyImgSize, &cImgChannels, &bkgColor))
341
// invalidate the client area for later update
343
/* invalidate the client area for later update */
343
345
InvalidateRect (hwnd, NULL, TRUE);
345
// display the PNG into the DIBitmap
347
/* display the PNG into the DIBitmap */
347
349
DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
348
350
pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
384
386
CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED);
386
// invalidate the client area for later update
388
/* invalidate the client area for later update */
388
390
InvalidateRect (hwnd, NULL, TRUE);
390
// display the PNG into the DIBitmap
392
/* display the PNG into the DIBitmap */
392
394
DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
393
395
pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
464
// Get the Height and Width of the child window
466
/* Get the Height and Width of the child window */
465
467
GetWindowRect (hwndChild, &rChild);
466
468
wChild = rChild.right - rChild.left;
467
469
hChild = rChild.bottom - rChild.top;
469
// Get the Height and Width of the parent window
471
/* Get the Height and Width of the parent window */
470
472
GetWindowRect (hwndParent, &rParent);
471
473
wParent = rParent.right - rParent.left;
472
474
hParent = rParent.bottom - rParent.top;
474
// Get the limits of the 'workarea'
476
/* Get the limits of the 'workarea' */
475
477
bResult = SystemParametersInfo(
476
SPI_GETWORKAREA, // system parameter to query or set
478
SPI_GETWORKAREA, /* system parameter to query or set */
499
501
yNew = rWorkArea.bottom - hChild;
502
// Set it, and return
504
/* Set it, and return */
503
505
return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE |
511
513
BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
555
557
FindClose(hFind);
557
// allocation memory for file-list
559
/* allocation memory for file-list */
559
561
*ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH);
561
// second cycle: read directory and store filenames in file-list
563
/* second cycle: read directory and store filenames in file-list */
563
565
hFind = FindFirstFile(szImgFindName, &finddata);
564
566
bOk = (hFind != (HANDLE) -1);
619
622
if (FileCount > 0)
621
// get previous entry
624
/* get previous entry */
623
626
if (pstrPrevName != NULL)
625
628
if (*pFileIndex > 0)
626
629
*pFileIndex -= 1;
628
631
*pFileIndex = FileCount - 1;
630
633
strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH));
635
638
if (pstrNextName != NULL)
637
640
if (*pFileIndex < FileCount - 1)
638
641
*pFileIndex += 1;
642
645
strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH));
701
705
BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
702
706
BYTE **ppDiData, int cxWinSize, int cyWinSize,
703
707
BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
706
710
BYTE *pDib = *ppDib;
707
711
BYTE *pDiData = *ppDiData;
708
// BITMAPFILEHEADER *pbmfh;
712
/* BITMAPFILEHEADER *pbmfh; */
709
713
BITMAPINFOHEADER *pbmih;
710
714
WORD wDIRowBytes;
711
715
png_color bkgBlack = {0, 0, 0};
712
716
png_color bkgGray = {127, 127, 127};
713
717
png_color bkgWhite = {255, 255, 255};
715
// allocate memory for the Device Independant bitmap
719
/* allocate memory for the Device Independant bitmap */
717
721
wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2;
745
749
pDiData = pDib + sizeof(BITMAPINFOHEADER);
746
750
*ppDiData = pDiData;
748
// first fill bitmap with gray and image border
752
/* first fill bitmap with gray and image border */
750
754
InitBitmap (pDiData, cxWinSize, cyWinSize);
752
// then fill bitmap with image
756
/* then fill bitmap with image */
824
828
cxNewSize = cxWinSize - 2 * MARGIN;
825
829
cyNewSize = cyWinSize - 2 * MARGIN;
827
// stretch the image to it's window determined size
831
/* stretch the image to it's window determined size */
829
// the following two are the same, but the first has side-effects
830
// because of rounding
831
// if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize))
833
/* the following two are mathematically the same, but the first
834
* has side-effects because of rounding
836
/* if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize)) */
832
837
if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize))
834
839
cyNewSize = cxNewSize * cyImgSize / cxImgSize;
911
// process the image not-stretched
916
/* process the image not-stretched */
915
// calculate the central position
920
/* calculate the central position */
917
922
cxImgPos = (cxWinSize - cxImgSize) / 2;
918
923
cyImgPos = (cyWinSize - cyImgSize) / 2;
920
// check for image larger than window
925
/* check for image larger than window */
922
927
if (cxImgPos < MARGIN)
923
928
cxImgPos = MARGIN;
924
929
if (cyImgPos < MARGIN)
925
930
cyImgPos = MARGIN;
927
// calculate both row-bytes
932
/* calculate both row-bytes */
929
934
wImgRowBytes = cImgChannels * cxImgSize;
930
935
wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
932
// copy image to screen
937
/* copy image to screen */
934
939
for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++)