--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/libpng-1.2.32/contrib/visupng/VisualPng.c Fri Jul 31 15:01:17 2009 +0100
@@ -0,0 +1,961 @@
+//------------------------------------
+// VisualPng.C -- Shows a PNG image
+//------------------------------------
+
+// Copyright 2000, Willem van Schaik. For conditions of distribution and
+// use, see the copyright/license/disclaimer notice in png.h
+
+// switches
+
+// defines
+
+#define PROGNAME "VisualPng"
+#define LONGNAME "Win32 Viewer for PNG-files"
+#define VERSION "1.0 of 2000 June 07"
+
+// constants
+
+#define MARGIN 8
+
+// standard includes
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+
+// application includes
+
+#include "png.h"
+#include "pngfile.h"
+#include "resource.h"
+
+// macros
+
+// function prototypes
+
+LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
+BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
+
+BOOL CenterAbout (HWND hwndChild, HWND hwndParent);
+
+BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
+ int *pFileIndex);
+
+BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex,
+ PTSTR pstrPrevName, PTSTR pstrNextName);
+
+BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName,
+ png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels,
+ png_color *pBkgColor);
+
+BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
+ BYTE **ppDiData, int cxWinSize, int cyWinSize,
+ BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
+ BOOL bStretched);
+
+BOOL InitBitmap (
+ BYTE *pDiData, int cxWinSize, int cyWinSize);
+
+BOOL FillBitmap (
+ BYTE *pDiData, int cxWinSize, int cyWinSize,
+ BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
+ BOOL bStretched);
+
+// a few global variables
+
+static char *szProgName = PROGNAME;
+static char *szAppName = LONGNAME;
+static char *szIconName = PROGNAME;
+static char szCmdFileName [MAX_PATH];
+
+// MAIN routine
+
+int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ PSTR szCmdLine, int iCmdShow)
+{
+ HACCEL hAccel;
+ HWND hwnd;
+ MSG msg;
+ WNDCLASS wndclass;
+ int ixBorders, iyBorders;
+
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = LoadIcon (hInstance, szIconName) ;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = NULL; // (HBRUSH) GetStockObject (GRAY_BRUSH);
+ wndclass.lpszMenuName = szProgName;
+ wndclass.lpszClassName = szProgName;
+
+ if (!RegisterClass (&wndclass))
+ {
+ MessageBox (NULL, TEXT ("Error: this program requires Windows NT!"),
+ szProgName, MB_ICONERROR);
+ return 0;
+ }
+
+ // if filename given on commandline, store it
+ if ((szCmdLine != NULL) && (*szCmdLine != '\0'))
+ if (szCmdLine[0] == '"')
+ strncpy (szCmdFileName, szCmdLine + 1, strlen(szCmdLine) - 2);
+ else
+ strcpy (szCmdFileName, szCmdLine);
+ else
+ strcpy (szCmdFileName, "");
+
+ // calculate size of window-borders
+ ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) +
+ GetSystemMetrics (SM_CXDLGFRAME));
+ iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) +
+ GetSystemMetrics (SM_CYDLGFRAME)) +
+ GetSystemMetrics (SM_CYCAPTION) +
+ GetSystemMetrics (SM_CYMENUSIZE) +
+ 1; /* WvS: don't ask me why? */
+
+ hwnd = CreateWindow (szProgName, szAppName,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ 512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders,
+// CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, hInstance, NULL);
+
+ ShowWindow (hwnd, iCmdShow);
+ UpdateWindow (hwnd);
+
+ hAccel = LoadAccelerators (hInstance, szProgName);
+
+ while (GetMessage (&msg, NULL, 0, 0))
+ {
+ if (!TranslateAccelerator (hwnd, hAccel, &msg))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+ return msg.wParam;
+}
+
+LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
+ LPARAM lParam)
+{
+ static HINSTANCE hInstance ;
+ static HDC hdc;
+ static PAINTSTRUCT ps;
+ static HMENU hMenu;
+
+ static BITMAPFILEHEADER *pbmfh;
+ static BITMAPINFOHEADER *pbmih;
+ static BYTE *pbImage;
+ static int cxWinSize, cyWinSize;
+ static int cxImgSize, cyImgSize;
+ static int cImgChannels;
+ static png_color bkgColor = {127, 127, 127};
+
+ static BOOL bStretched = TRUE;
+
+ static BYTE *pDib = NULL;
+ static BYTE *pDiData = NULL;
+
+ static TCHAR szImgPathName [MAX_PATH];
+ static TCHAR szTitleName [MAX_PATH];
+
+ static TCHAR *pPngFileList = NULL;
+ static int iPngFileCount;
+ static int iPngFileIndex;
+
+ BOOL bOk;
+
+ switch (message)
+ {
+ case WM_CREATE:
+ hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
+ PngFileInitialize (hwnd);
+
+ strcpy (szImgPathName, "");
+
+ // in case we process file given on command-line
+
+ if (szCmdFileName[0] != '\0')
+ {
+ strcpy (szImgPathName, szCmdFileName);
+
+ // read the other png-files in the directory for later
+ // next/previous commands
+
+ BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
+ &iPngFileIndex);
+
+ // load the image from file
+
+ if (!LoadImageFile (hwnd, szImgPathName,
+ &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
+ return 0;
+
+ // invalidate the client area for later update
+
+ InvalidateRect (hwnd, NULL, TRUE);
+
+ // display the PNG into the DIBitmap
+
+ DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
+ pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
+ }
+
+ return 0;
+
+ case WM_SIZE:
+ cxWinSize = LOWORD (lParam);
+ cyWinSize = HIWORD (lParam);
+
+ // invalidate the client area for later update
+
+ InvalidateRect (hwnd, NULL, TRUE);
+
+ // display the PNG into the DIBitmap
+
+ DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
+ pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
+
+ return 0;
+
+ case WM_INITMENUPOPUP:
+ hMenu = GetMenu (hwnd);
+
+ if (pbImage)
+ EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_ENABLED);
+ else
+ EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_GRAYED);
+
+ return 0;
+
+ case WM_COMMAND:
+ hMenu = GetMenu (hwnd);
+
+ switch (LOWORD (wParam))
+ {
+ case IDM_FILE_OPEN:
+
+ // show the File Open dialog box
+
+ if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName))
+ return 0;
+
+ // read the other png-files in the directory for later
+ // next/previous commands
+
+ BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount,
+ &iPngFileIndex);
+
+ // load the image from file
+
+ if (!LoadImageFile (hwnd, szImgPathName,
+ &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
+ return 0;
+
+ // invalidate the client area for later update
+
+ InvalidateRect (hwnd, NULL, TRUE);
+
+ // display the PNG into the DIBitmap
+
+ DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
+ pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
+
+ return 0;
+
+ case IDM_FILE_SAVE:
+
+ // show the File Save dialog box
+
+ if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName))
+ return 0;
+
+ // save the PNG to a disk file
+
+ SetCursor (LoadCursor (NULL, IDC_WAIT));
+ ShowCursor (TRUE);
+
+ bOk = PngSaveImage (szImgPathName, pDiData, cxWinSize, cyWinSize,
+ bkgColor);
+
+ ShowCursor (FALSE);
+ SetCursor (LoadCursor (NULL, IDC_ARROW));
+
+ if (!bOk)
+ MessageBox (hwnd, TEXT ("Error in saving the PNG image"),
+ szProgName, MB_ICONEXCLAMATION | MB_OK);
+ return 0;
+
+ case IDM_FILE_NEXT:
+
+ // read next entry in the directory
+
+ if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
+ NULL, szImgPathName))
+ {
+ if (strcmp (szImgPathName, "") == 0)
+ return 0;
+
+ // load the image from file
+
+ if (!LoadImageFile (hwnd, szImgPathName, &pbImage,
+ &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor))
+ return 0;
+
+ // invalidate the client area for later update
+
+ InvalidateRect (hwnd, NULL, TRUE);
+
+ // display the PNG into the DIBitmap
+
+ DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
+ pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
+ }
+
+ return 0;
+
+ case IDM_FILE_PREVIOUS:
+
+ // read previous entry in the directory
+
+ if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex,
+ szImgPathName, NULL))
+ {
+
+ if (strcmp (szImgPathName, "") == 0)
+ return 0;
+
+ // load the image from file
+
+ if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize,
+ &cyImgSize, &cImgChannels, &bkgColor))
+ return 0;
+
+ // invalidate the client area for later update
+
+ InvalidateRect (hwnd, NULL, TRUE);
+
+ // display the PNG into the DIBitmap
+
+ DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
+ pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
+ }
+
+ return 0;
+
+ case IDM_FILE_EXIT:
+
+ // more cleanup needed...
+
+ // free image buffer
+
+ if (pDib != NULL)
+ {
+ free (pDib);
+ pDib = NULL;
+ }
+
+ // free file-list
+
+ if (pPngFileList != NULL)
+ {
+ free (pPngFileList);
+ pPngFileList = NULL;
+ }
+
+ // let's go ...
+
+ exit (0);
+
+ return 0;
+
+ case IDM_OPTIONS_STRETCH:
+ bStretched = !bStretched;
+ if (bStretched)
+ CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_CHECKED);
+ else
+ CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED);
+
+ // invalidate the client area for later update
+
+ InvalidateRect (hwnd, NULL, TRUE);
+
+ // display the PNG into the DIBitmap
+
+ DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize,
+ pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched);
+
+ return 0;
+
+ case IDM_HELP_ABOUT:
+ DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ;
+ return 0;
+
+ } // end switch
+
+ break;
+
+ case WM_PAINT:
+ hdc = BeginPaint (hwnd, &ps);
+
+ if (pDib)
+ SetDIBitsToDevice (hdc, 0, 0, cxWinSize, cyWinSize, 0, 0,
+ 0, cyWinSize, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS);
+
+ EndPaint (hwnd, &ps);
+ return 0;
+
+ case WM_DESTROY:
+ if (pbmfh)
+ {
+ free (pbmfh);
+ pbmfh = NULL;
+ }
+
+ PostQuitMessage (0);
+ return 0;
+ }
+
+ return DefWindowProc (hwnd, message, wParam, lParam);
+}
+
+BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_INITDIALOG :
+ ShowWindow (hDlg, SW_HIDE);
+ CenterAbout (hDlg, GetWindow (hDlg, GW_OWNER));
+ ShowWindow (hDlg, SW_SHOW);
+ return TRUE ;
+
+ case WM_COMMAND :
+ switch (LOWORD (wParam))
+ {
+ case IDOK :
+ case IDCANCEL :
+ EndDialog (hDlg, 0) ;
+ return TRUE ;
+ }
+ break ;
+ }
+ return FALSE ;
+}
+
+//---------------
+// CenterAbout
+//---------------
+
+BOOL CenterAbout (HWND hwndChild, HWND hwndParent)
+{
+ RECT rChild, rParent, rWorkArea;
+ int wChild, hChild, wParent, hParent;
+ int xNew, yNew;
+ BOOL bResult;
+
+ // Get the Height and Width of the child window
+ GetWindowRect (hwndChild, &rChild);
+ wChild = rChild.right - rChild.left;
+ hChild = rChild.bottom - rChild.top;
+
+ // Get the Height and Width of the parent window
+ GetWindowRect (hwndParent, &rParent);
+ wParent = rParent.right - rParent.left;
+ hParent = rParent.bottom - rParent.top;
+
+ // Get the limits of the 'workarea'
+ bResult = SystemParametersInfo(
+ SPI_GETWORKAREA, // system parameter to query or set
+ sizeof(RECT),
+ &rWorkArea,
+ 0);
+ if (!bResult) {
+ rWorkArea.left = rWorkArea.top = 0;
+ rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
+ rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
+ }
+
+ // Calculate new X position, then adjust for workarea
+ xNew = rParent.left + ((wParent - wChild) /2);
+ if (xNew < rWorkArea.left) {
+ xNew = rWorkArea.left;
+ } else if ((xNew+wChild) > rWorkArea.right) {
+ xNew = rWorkArea.right - wChild;
+ }
+
+ // Calculate new Y position, then adjust for workarea
+ yNew = rParent.top + ((hParent - hChild) /2);
+ if (yNew < rWorkArea.top) {
+ yNew = rWorkArea.top;
+ } else if ((yNew+hChild) > rWorkArea.bottom) {
+ yNew = rWorkArea.bottom - hChild;
+ }
+
+ // Set it, and return
+ return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE |
+ SWP_NOZORDER);
+}
+
+//----------------
+// BuildPngList
+//----------------
+
+BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount,
+ int *pFileIndex)
+{
+ static TCHAR szImgPathName [MAX_PATH];
+ static TCHAR szImgFileName [MAX_PATH];
+ static TCHAR szImgFindName [MAX_PATH];
+
+ WIN32_FIND_DATA finddata;
+ HANDLE hFind;
+
+ static TCHAR szTmp [MAX_PATH];
+ BOOL bOk;
+ int i, ii;
+ int j, jj;
+
+ // free previous file-list
+
+ if (*ppFileList != NULL)
+ {
+ free (*ppFileList);
+ *ppFileList = NULL;
+ }
+
+ // extract foldername, filename and search-name
+
+ strcpy (szImgPathName, pstrPathName);
+ strcpy (szImgFileName, strrchr (pstrPathName, '\\') + 1);
+
+ strcpy (szImgFindName, szImgPathName);
+ *(strrchr (szImgFindName, '\\') + 1) = '\0';
+ strcat (szImgFindName, "*.png");
+
+ // first cycle: count number of files in directory for memory allocation
+
+ *pFileCount = 0;
+
+ hFind = FindFirstFile(szImgFindName, &finddata);
+ bOk = (hFind != (HANDLE) -1);
+
+ while (bOk)
+ {
+ *pFileCount += 1;
+ bOk = FindNextFile(hFind, &finddata);
+ }
+ FindClose(hFind);
+
+ // allocation memory for file-list
+
+ *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH);
+
+ // second cycle: read directory and store filenames in file-list
+
+ hFind = FindFirstFile(szImgFindName, &finddata);
+ bOk = (hFind != (HANDLE) -1);
+
+ i = 0;
+ ii = 0;
+ while (bOk)
+ {
+ strcpy (*ppFileList + ii, szImgPathName);
+ strcpy (strrchr(*ppFileList + ii, '\\') + 1, finddata.cFileName);
+
+ if (strcmp(pstrPathName, *ppFileList + ii) == 0)
+ *pFileIndex = i;
+
+ ii += MAX_PATH;
+ i++;
+
+ bOk = FindNextFile(hFind, &finddata);
+ }
+ FindClose(hFind);
+
+ // finally we must sort the file-list
+
+ for (i = 0; i < *pFileCount - 1; i++)
+ {
+ ii = i * MAX_PATH;
+ for (j = i+1; j < *pFileCount; j++)
+ {
+ jj = j * MAX_PATH;
+ if (strcmp (*ppFileList + ii, *ppFileList + jj) > 0)
+ {
+ strcpy (szTmp, *ppFileList + jj);
+ strcpy (*ppFileList + jj, *ppFileList + ii);
+ strcpy (*ppFileList + ii, szTmp);
+
+ // check if this was the current image that we moved
+
+ if (*pFileIndex == i)
+ *pFileIndex = j;
+ else
+ if (*pFileIndex == j)
+ *pFileIndex = i;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+//----------------
+// SearchPngList
+//----------------
+
+BOOL SearchPngList (
+ TCHAR *pFileList, int FileCount, int *pFileIndex,
+ PTSTR pstrPrevName, PTSTR pstrNextName)
+{
+ if (FileCount > 0)
+ {
+ // get previous entry
+
+ if (pstrPrevName != NULL)
+ {
+ if (*pFileIndex > 0)
+ *pFileIndex -= 1;
+ else
+ *pFileIndex = FileCount - 1;
+
+ strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH));
+ }
+
+ // get next entry
+
+ if (pstrNextName != NULL)
+ {
+ if (*pFileIndex < FileCount - 1)
+ *pFileIndex += 1;
+ else
+ *pFileIndex = 0;
+
+ strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH));
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//-----------------
+// LoadImageFile
+//-----------------
+
+BOOL LoadImageFile (HWND hwnd, PTSTR pstrPathName,
+ png_byte **ppbImage, int *pxImgSize, int *pyImgSize,
+ int *piChannels, png_color *pBkgColor)
+{
+ static TCHAR szTmp [MAX_PATH];
+
+ // if there's an existing PNG, free the memory
+
+ if (*ppbImage)
+ {
+ free (*ppbImage);
+ *ppbImage = NULL;
+ }
+
+ // Load the entire PNG into memory
+
+ SetCursor (LoadCursor (NULL, IDC_WAIT));
+ ShowCursor (TRUE);
+
+ PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels,
+ pBkgColor);
+
+ ShowCursor (FALSE);
+ SetCursor (LoadCursor (NULL, IDC_ARROW));
+
+ if (*ppbImage != NULL)
+ {
+ sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1);
+ SetWindowText (hwnd, szTmp);
+ }
+ else
+ {
+ MessageBox (hwnd, TEXT ("Error in loading the PNG image"),
+ szProgName, MB_ICONEXCLAMATION | MB_OK);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//----------------
+// DisplayImage
+//----------------
+
+BOOL DisplayImage (HWND hwnd, BYTE **ppDib,
+ BYTE **ppDiData, int cxWinSize, int cyWinSize,
+ BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
+ BOOL bStretched)
+{
+ BYTE *pDib = *ppDib;
+ BYTE *pDiData = *ppDiData;
+ // BITMAPFILEHEADER *pbmfh;
+ BITMAPINFOHEADER *pbmih;
+ WORD wDIRowBytes;
+ png_color bkgBlack = {0, 0, 0};
+ png_color bkgGray = {127, 127, 127};
+ png_color bkgWhite = {255, 255, 255};
+
+ // allocate memory for the Device Independant bitmap
+
+ wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2;
+
+ if (pDib)
+ {
+ free (pDib);
+ pDib = NULL;
+ }
+
+ if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) +
+ wDIRowBytes * cyWinSize)))
+ {
+ MessageBox (hwnd, TEXT ("Error in displaying the PNG image"),
+ szProgName, MB_ICONEXCLAMATION | MB_OK);
+ *ppDib = pDib = NULL;
+ return FALSE;
+ }
+ *ppDib = pDib;
+ memset (pDib, 0, sizeof(BITMAPINFOHEADER));
+
+ // initialize the dib-structure
+
+ pbmih = (BITMAPINFOHEADER *) pDib;
+ pbmih->biSize = sizeof(BITMAPINFOHEADER);
+ pbmih->biWidth = cxWinSize;
+ pbmih->biHeight = -((long) cyWinSize);
+ pbmih->biPlanes = 1;
+ pbmih->biBitCount = 24;
+ pbmih->biCompression = 0;
+ pDiData = pDib + sizeof(BITMAPINFOHEADER);
+ *ppDiData = pDiData;
+
+ // first fill bitmap with gray and image border
+
+ InitBitmap (pDiData, cxWinSize, cyWinSize);
+
+ // then fill bitmap with image
+
+ if (pbImage)
+ {
+ FillBitmap (
+ pDiData, cxWinSize, cyWinSize,
+ pbImage, cxImgSize, cyImgSize, cImgChannels,
+ bStretched);
+ }
+
+ return TRUE;
+}
+
+//--------------
+// InitBitmap
+//--------------
+
+BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize)
+{
+ BYTE *dst;
+ int x, y, col;
+
+ // initialize the background with gray
+
+ dst = pDiData;
+ for (y = 0; y < cyWinSize; y++)
+ {
+ col = 0;
+ for (x = 0; x < cxWinSize; x++)
+ {
+ // fill with GRAY
+ *dst++ = 127;
+ *dst++ = 127;
+ *dst++ = 127;
+ col += 3;
+ }
+ // rows start on 4 byte boundaries
+ while ((col % 4) != 0)
+ {
+ dst++;
+ col++;
+ }
+ }
+
+ return TRUE;
+}
+
+//--------------
+// FillBitmap
+//--------------
+
+BOOL FillBitmap (
+ BYTE *pDiData, int cxWinSize, int cyWinSize,
+ BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels,
+ BOOL bStretched)
+{
+ BYTE *pStretchedImage;
+ BYTE *pImg;
+ BYTE *src, *dst;
+ BYTE r, g, b, a;
+ const int cDIChannels = 3;
+ WORD wImgRowBytes;
+ WORD wDIRowBytes;
+ int cxNewSize, cyNewSize;
+ int cxImgPos, cyImgPos;
+ int xImg, yImg;
+ int xWin, yWin;
+ int xOld, yOld;
+ int xNew, yNew;
+
+ if (bStretched)
+ {
+ cxNewSize = cxWinSize - 2 * MARGIN;
+ cyNewSize = cyWinSize - 2 * MARGIN;
+
+ // stretch the image to it's window determined size
+
+ // the following two are the same, but the first has side-effects
+ // because of rounding
+// if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize))
+ if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize))
+ {
+ cyNewSize = cxNewSize * cyImgSize / cxImgSize;
+ cxImgPos = MARGIN;
+ cyImgPos = (cyWinSize - cyNewSize) / 2;
+ }
+ else
+ {
+ cxNewSize = cyNewSize * cxImgSize / cyImgSize;
+ cyImgPos = MARGIN;
+ cxImgPos = (cxWinSize - cxNewSize) / 2;
+ }
+
+ pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize);
+ pImg = pStretchedImage;
+
+ for (yNew = 0; yNew < cyNewSize; yNew++)
+ {
+ yOld = yNew * cyImgSize / cyNewSize;
+ for (xNew = 0; xNew < cxNewSize; xNew++)
+ {
+ xOld = xNew * cxImgSize / cxNewSize;
+
+ r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0);
+ g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1);
+ b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2);
+ *pImg++ = r;
+ *pImg++ = g;
+ *pImg++ = b;
+ if (cImgChannels == 4)
+ {
+ a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld)
+ + 3);
+ *pImg++ = a;
+ }
+ }
+ }
+
+ // calculate row-bytes
+
+ wImgRowBytes = cImgChannels * cxNewSize;
+ wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
+
+ // copy image to screen
+
+ for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++)
+ {
+ if (yWin >= cyWinSize - cyImgPos)
+ break;
+ src = pStretchedImage + yImg * wImgRowBytes;
+ dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
+
+ for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++)
+ {
+ if (xWin >= cxWinSize - cxImgPos)
+ break;
+ r = *src++;
+ g = *src++;
+ b = *src++;
+ *dst++ = b; /* note the reverse order */
+ *dst++ = g;
+ *dst++ = r;
+ if (cImgChannels == 4)
+ {
+ a = *src++;
+ }
+ }
+ }
+
+ // free memory
+
+ if (pStretchedImage != NULL)
+ {
+ free (pStretchedImage);
+ pStretchedImage = NULL;
+ }
+
+ }
+
+ // process the image not-stretched
+
+ else
+ {
+ // calculate the central position
+
+ cxImgPos = (cxWinSize - cxImgSize) / 2;
+ cyImgPos = (cyWinSize - cyImgSize) / 2;
+
+ // check for image larger than window
+
+ if (cxImgPos < MARGIN)
+ cxImgPos = MARGIN;
+ if (cyImgPos < MARGIN)
+ cyImgPos = MARGIN;
+
+ // calculate both row-bytes
+
+ wImgRowBytes = cImgChannels * cxImgSize;
+ wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2;
+
+ // copy image to screen
+
+ for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++)
+ {
+ if (yWin >= cyWinSize - MARGIN)
+ break;
+ src = pbImage + yImg * wImgRowBytes;
+ dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels;
+
+ for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++)
+ {
+ if (xWin >= cxWinSize - MARGIN)
+ break;
+ r = *src++;
+ g = *src++;
+ b = *src++;
+ *dst++ = b; /* note the reverse order */
+ *dst++ = g;
+ *dst++ = r;
+ if (cImgChannels == 4)
+ {
+ a = *src++;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+//-----------------
+// end of source
+//-----------------