Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

964 lines
26 KiB

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