home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 32 / PCGAMER32.bin / wing / halftone.c_ / halftone.c
Text File  |  1995-06-20  |  22KB  |  575 lines

  1. /**************************************************************************
  2.  
  3.     HALFTONE.C - A halftoning demo for WinG
  4.  
  5.  **************************************************************************/
  6. /**************************************************************************
  7.  
  8.     (C) Copyright 1994 Microsoft Corp.  All rights reserved.
  9.  
  10.     You have a royalty-free right to use, modify, reproduce and 
  11.     distribute the Sample Files (and/or any modified version) in 
  12.     any way you find useful, provided that you agree that 
  13.     Microsoft has no warranty obligations or liability for any 
  14.     Sample Application Files which are modified. 
  15.  
  16.  **************************************************************************/
  17.  
  18.  
  19. #include <windows.h>
  20. #include <windowsx.h>
  21. #include <commdlg.h>
  22.  
  23. #include <wing.h>
  24.  
  25. #include "halftone.h"
  26. #include "..\utils\utils.h"
  27.  
  28. /*----------------------------------------------------------------------------*\
  29. |                                                                              |
  30. |   g l o b a l   v a r i a b l e s                                            |
  31. |                                                                              |
  32. \*----------------------------------------------------------------------------*/
  33. static  char       szAppName[]="WinG Halftoning Sample";
  34. static  char       szAppFilter[]="Bitmaps\0*.bmp;*.dib\0";
  35. static  HINSTANCE  hInstApp;
  36. static  HWND       hwndApp;
  37. static  HPALETTE   hpalApp;
  38. static  BOOL       fAppActive;
  39. static  BOOL       fCustomDither = TRUE;
  40. static  PDIB       pdibOriginal = 0;
  41. static  PDIB       pdibHalftone = 0;
  42.  
  43. #ifdef WIN32
  44.     #define _export
  45. #endif
  46.  
  47. /*----------------------------------------------------------------------------*\
  48. |                                                                              |
  49. |   f u n c t i o n   d e f i n i t i o n s                                    |
  50. |                                                                              |
  51. \*----------------------------------------------------------------------------*/
  52.  
  53. LONG FAR PASCAL _export  AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
  54. LONG  AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
  55.  
  56. void  AppExit(void);
  57. BOOL  AppIdle(void);
  58. void  AppOpenFile(HWND hwnd, LPSTR szFileName);
  59.  
  60. PDIB  DibHalftoneDIB( PDIB pSource );
  61.  
  62. /*----------------------------------------------------------------------------*\
  63. |   AppAbout( hDlg, uiMessage, wParam, lParam )                                |
  64. |                                                                              |
  65. |   Description:                                                               |
  66. |       This function handles messages belonging to the "About" dialog box.    |
  67. |       The only message that it looks for is WM_COMMAND, indicating the use   |
  68. |       has pressed the "OK" button.  When this happens, it takes down         |
  69. |       the dialog box.                                                        |
  70. |                                                                              |
  71. |   Arguments:                                                                 |
  72. |       hDlg            window handle of about dialog window                   |
  73. |       uiMessage       message number                                         |
  74. |       wParam          message-dependent                                      |
  75. |       lParam          message-dependent                                      |
  76. |                                                                              |
  77. |   Returns:                                                                   |
  78. |       TRUE if message has been processed, else FALSE                         |
  79. |                                                                              |
  80. \*----------------------------------------------------------------------------*/
  81. BOOL FAR PASCAL _export AppAbout(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  82. {
  83.     switch (msg)
  84.     {
  85.         case WM_COMMAND:
  86.           if (LOWORD(wParam) == IDOK)
  87.             {
  88.                 EndDialog(hwnd,TRUE);
  89.             }
  90.             break;
  91.  
  92.         case WM_INITDIALOG:
  93.             return TRUE;
  94.     }
  95.     return FALSE;
  96. }
  97.  
  98. /*----------------------------------------------------------------------------*\
  99. |   AppInit( hInst, hPrev)                                                     |
  100. |                                                                              |
  101. |   Description:                                                               |
  102. |       This is called when the application is first loaded into               |
  103. |       memory.  It performs all initialization that doesn't need to be done   |
  104. |       once per instance.                                                     |
  105. |                                                                              |
  106. |   Arguments:                                                                 |
  107. |       hInstance       instance handle of current instance                    |
  108. |       hPrev           instance handle of previous instance                   |
  109. |                                                                              |
  110. |   Returns:                                                                   |
  111. |       TRUE if successful, FALSE if not                                       |
  112. |                                                                              |
  113. \*----------------------------------------------------------------------------*/
  114. BOOL AppInit(HINSTANCE hInst,HINSTANCE hPrev,int sw,LPSTR szCmdLine)
  115. {
  116.     WNDCLASS cls;
  117.     int      dx,dy;
  118.     HMENU hMenu;
  119.  
  120.     /* Save instance handle for DialogBoxes */
  121.     hInstApp = hInst;
  122.  
  123. // Clear the System Palette so that WinG blting runs at full speed.
  124.     ClearSystemPalette();
  125.  
  126.     if (!hPrev)
  127.     {
  128.         /*
  129.          *  Register a class for the main application window
  130.          */
  131.         cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  132.         cls.hIcon          = LoadIcon(hInst,"AppIcon");
  133.         cls.lpszMenuName   = "AppMenu";
  134.         cls.lpszClassName  = szAppName;
  135.         cls.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  136.         cls.hInstance      = hInst;
  137.         cls.style          = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  138.         cls.lpfnWndProc    = (WNDPROC)AppWndProc;
  139.         cls.cbWndExtra     = 0;
  140.         cls.cbClsExtra     = 0;
  141.  
  142.         if (!RegisterClass(&cls))
  143.             return FALSE;
  144.     }
  145.  
  146.     dx = GetSystemMetrics (SM_CXSCREEN) / 2;
  147.     dy = GetSystemMetrics (SM_CYSCREEN) / 2;
  148.  
  149.   hpalApp = WinGCreateHalftonePalette();
  150.  
  151.     hwndApp = CreateWindow (szAppName,              // Class name
  152.                             szAppName,              // Caption
  153.                             WS_OVERLAPPEDWINDOW,    // Style bits
  154.                             CW_USEDEFAULT, 0,       // Position
  155.                             dx,dy,                  // Size
  156.                             (HWND)NULL,             // Parent window (no parent)
  157.                             (HMENU)NULL,            // use class menu
  158.                             hInst,                  // handle to window instance
  159.                             (LPSTR)NULL             // no params to pass on
  160.                            );
  161.     ShowWindow(hwndApp,sw);
  162.  
  163.   //*** Check the default dither selection
  164.   hMenu = GetMenu(hwndApp);
  165.   CheckMenuItem(hMenu, MENU_WING, fCustomDither ? MF_CHECKED : MF_UNCHECKED);
  166.   CheckMenuItem(hMenu, MENU_GDI, fCustomDither ? MF_UNCHECKED : MF_CHECKED);
  167.  
  168.     if (*szCmdLine)
  169.   AppOpenFile(hwndApp, szCmdLine);
  170.  
  171.     return TRUE;
  172. }
  173.  
  174.  
  175. /*----------------------------------------------------------------------------*\
  176. |   AppExit()                                                                  |
  177. |                                                                              |
  178. |   Description:                                                               |
  179. |     App is just about to exit, cleanup.                                      |
  180. |                                                                              |
  181. \*----------------------------------------------------------------------------*/
  182. void AppExit()
  183. {
  184.   if (hpalApp)
  185.     DeleteObject(hpalApp);
  186.   if (pdibOriginal)
  187.     DibFree(pdibOriginal);
  188.   if (pdibHalftone)
  189.     DibFree(pdibHalftone);
  190. }
  191.  
  192. /*----------------------------------------------------------------------------*\
  193. |   WinMain( hInst, hPrev, lpszCmdLine, cmdShow )                              |
  194. |                                                                              |
  195. |   Description:                                                               |
  196. |       The main procedure for the App.  After initializing, it just goes      |
  197. |       into a message-processing loop until it gets a WM_QUIT message         |
  198. |       (meaning the app was closed).                                          |
  199. |                                                                              |
  200. |   Arguments:                                                                 |
  201. |       hInst           instance handle of this instance of the app            |
  202. |       hPrev           instance handle of previous instance, NULL if first    |
  203. |       szCmdLine       ->null-terminated command line                         |
  204. |       cmdShow         specifies how the window is initially displayed        |
  205. |                                                                              |
  206. |   Returns:                                                                   |
  207. |       The exit code as specified in the WM_QUIT message.                     |
  208. |                                                                              |
  209. \*----------------------------------------------------------------------------*/
  210. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
  211. {
  212.     MSG     msg;
  213.  
  214.     /* Call initialization procedure */
  215.     if (!AppInit(hInst,hPrev,sw,szCmdLine))
  216.       return FALSE;
  217.  
  218.     /*
  219.      * Polling messages from event queue
  220.      */
  221.     for (;;)
  222.     {
  223.         if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
  224.         {
  225.             if (msg.message == WM_QUIT)
  226.                 break;
  227.  
  228.             TranslateMessage(&msg);
  229.             DispatchMessage(&msg);
  230.         }
  231.         else
  232.   {
  233.       if (AppIdle())
  234.             WaitMessage();
  235.         }
  236.     }
  237.  
  238.     AppExit();
  239.     return msg.wParam;
  240. }
  241.  
  242. /*----------------------------------------------------------------------------*\
  243. |   AppIdle()                                                                  |
  244. |                                                                              |
  245. |   Description:                                                               |
  246. |     Place to do idle time stuff.                                             |
  247. |                                                                              |
  248. \*----------------------------------------------------------------------------*/
  249. BOOL AppIdle()
  250. {
  251.     if (fAppActive)
  252.     {
  253.   //
  254.   // we are the foreground app.
  255.   //
  256.   return TRUE;      // nothing to do.
  257.     }
  258.     else
  259.     {
  260.   //
  261.   // we are a background app.
  262.   //
  263.   return TRUE;      // nothing to do.
  264.     }
  265. }
  266.  
  267. /*----------------------------------------------------------------------------*\
  268. |   AppOpenFile()                                                              |
  269. |                                                                              |
  270. |   Description:                                                               |
  271. |     Open a file.                                                             |
  272. |                                                                              |
  273. \*----------------------------------------------------------------------------*/
  274. void AppOpenFile(HWND hwnd, LPSTR szFileName)
  275. {
  276.   HCURSOR hCur = LoadCursor(NULL, IDC_WAIT);
  277.   PDIB pdibNew;
  278.  
  279.   hCur = SetCursor(hCur);
  280.   
  281.   pdibNew = DibOpenFile(szFileName);
  282.  
  283.   if (pdibNew)
  284.   {
  285.     if (pdibOriginal)
  286.       DibFree(pdibOriginal);
  287.     if (pdibHalftone)
  288.       DibFree(pdibHalftone);
  289.  
  290.     pdibOriginal = pdibNew;
  291.     pdibHalftone = DibHalftoneDIB(pdibOriginal);
  292.  
  293.     if (DibBitCount(pdibOriginal) != 24)
  294.     {
  295.       MessageBox(hwnd, "Not a 24-bit DIB!", "Oops", MB_OK);
  296.     }
  297.  
  298.     InvalidateRect(hwnd, NULL, TRUE);
  299.     UpdateWindow(hwnd);
  300.   }
  301.  
  302.   hCur = SetCursor(hCur);
  303. }
  304.  
  305. /*----------------------------------------------------------------------------*\
  306. |   AppPaint(hwnd, hdc)                                                        |
  307. |                                                                              |
  308. |   Description:                                                               |
  309. |       The paint function.                                                    |
  310. |                                                                              |
  311. |   Arguments:                                                                 |
  312. |       hwnd             window painting into                                  |
  313. |       hdc              display context to paint to                           |
  314. |                                                                              |
  315. \*----------------------------------------------------------------------------*/
  316. AppPaint (HWND hwnd, HDC hdc)
  317. {
  318.   if (fCustomDither && pdibHalftone)
  319.   {
  320.     StretchDIBits(hdc,
  321.       0, 0, DibWidth(pdibHalftone), DibHeight(pdibHalftone),
  322.       0, 0, DibWidth(pdibHalftone), DibHeight(pdibHalftone),
  323.       DibPtr(pdibHalftone), DibInfo(pdibHalftone),
  324.       DIB_RGB_COLORS, SRCCOPY);
  325.   }
  326.   else if (pdibOriginal)
  327.   {
  328.     StretchDIBits(hdc,
  329.       0, 0, DibWidth(pdibOriginal), DibHeight(pdibOriginal),
  330.       0, 0, DibWidth(pdibOriginal), DibHeight(pdibOriginal),
  331.       DibPtr(pdibOriginal), DibInfo(pdibOriginal),
  332.       DIB_RGB_COLORS, SRCCOPY);
  333.   }
  334.  
  335.   return TRUE;
  336. }
  337.  
  338. /*----------------------------------------------------------------------------*\
  339. |   AppWndProc( hwnd, uiMessage, wParam, lParam )                              |
  340. |                                                                              |
  341. |   Description:                                                               |
  342. |       The window proc for the app's main (tiled) window.  This processes all |
  343. |       of the parent window's messages.                                       |
  344. |                                                                              |
  345. \*----------------------------------------------------------------------------*/
  346. LONG FAR PASCAL _export AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  347. {
  348.     PAINTSTRUCT ps;
  349.     HDC hdc;
  350.     BOOL f;
  351.  
  352.     switch (msg)
  353.     {
  354.         case WM_CREATE:
  355.             break;
  356.  
  357.         case WM_ACTIVATEAPP:
  358.             fAppActive = (BOOL)wParam;
  359.             break;
  360.  
  361.         case WM_TIMER:
  362.             break;
  363.  
  364.         case WM_ERASEBKGND:
  365.             break;
  366.  
  367.         case WM_INITMENU:
  368.             break;
  369.  
  370.         case WM_COMMAND:
  371.             return AppCommand(hwnd,msg,wParam,lParam);
  372.  
  373.         case WM_DESTROY:
  374.             PostQuitMessage(0);
  375.             break;
  376.  
  377.         case WM_CLOSE:
  378.             break;
  379.  
  380.         case WM_PALETTECHANGED:
  381.             if ((HWND)wParam == hwnd)
  382.                 break;
  383.  
  384.       // fall through to WM_QUERYNEWPALETTE
  385.  
  386.         case WM_QUERYNEWPALETTE:
  387.             hdc = GetDC(hwnd);
  388.  
  389.             if (hpalApp)
  390.                 SelectPalette(hdc, hpalApp, FALSE);
  391.  
  392.             f = RealizePalette(hdc);
  393.             ReleaseDC(hwnd,hdc);
  394.  
  395.             if (f)
  396.                 InvalidateRect(hwnd,NULL,TRUE);
  397.  
  398.             return f;
  399.  
  400.         case WM_PAINT:
  401.             hdc = BeginPaint(hwnd,&ps);
  402.  
  403.             if (hpalApp)
  404.             {
  405.                 SelectPalette(hdc, hpalApp, FALSE);
  406.                 RealizePalette(hdc);
  407.             }
  408.             AppPaint (hwnd,hdc);
  409.             EndPaint(hwnd,&ps);
  410.             return 0L;
  411.     }
  412.     return DefWindowProc(hwnd,msg,wParam,lParam);
  413. }
  414.  
  415. /*----------------------------------------------------------------------------*\
  416. |   AppCommand(hwnd, msg, wParam, lParam )                                     |
  417. |                                                                              |
  418. |   Description:                                                               |
  419. |     Handles WM_COMMAND messages for the main window (hwndApp)                |
  420. |   of the parent window's messages.                                           |
  421. |                                                                              |
  422. \*----------------------------------------------------------------------------*/
  423. LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  424. {
  425.     char achFileName[128];
  426.     OPENFILENAME ofn;
  427.  
  428.     switch(wParam)
  429.     {
  430.         case MENU_ABOUT:
  431.             DialogBox(hInstApp,"AppAbout",hwnd,(DLGPROC)AppAbout);
  432.             break;
  433.  
  434.         case MENU_OPEN:
  435.             achFileName[0] = 0;
  436.  
  437.             /* prompt user for file to open */
  438.             ofn.lStructSize = sizeof(OPENFILENAME);
  439.             ofn.hwndOwner = hwnd;
  440.             ofn.hInstance = NULL;
  441.             ofn.lpstrFilter = szAppFilter;
  442.             ofn.lpstrCustomFilter = NULL;
  443.             ofn.nMaxCustFilter = 0;
  444.             ofn.nFilterIndex = 0;
  445.             ofn.lpstrFile = achFileName;
  446.             ofn.nMaxFile = sizeof(achFileName);
  447.             ofn.lpstrFileTitle = NULL;
  448.             ofn.nMaxFileTitle = 0;
  449.             ofn.lpstrInitialDir = NULL;
  450.             ofn.lpstrTitle = NULL;
  451.             ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  452.             ofn.nFileOffset = 0;
  453.             ofn.nFileExtension = 0;
  454.             ofn.lpstrDefExt = NULL;
  455.             ofn.lCustData = 0;
  456.             ofn.lpfnHook = NULL;
  457.             ofn.lpTemplateName = NULL;
  458.  
  459.             if (GetOpenFileName(&ofn))
  460.             {
  461.                 AppOpenFile(hwnd,achFileName);
  462.             }
  463.  
  464.             break;
  465.  
  466.         case MENU_EXIT:
  467.             PostMessage(hwnd,WM_CLOSE,0,0L);
  468.             break;
  469.  
  470.         case MENU_WING:
  471.         case MENU_GDI:
  472.         {
  473.             HMENU hMenu;
  474.  
  475.             fCustomDither = (wParam == MENU_WING);
  476.  
  477.             hMenu = GetMenu(hwnd);
  478.             CheckMenuItem(hMenu, MENU_WING,
  479.             fCustomDither ? MF_CHECKED : MF_UNCHECKED);
  480.             CheckMenuItem(hMenu, MENU_GDI,
  481.             fCustomDither ? MF_UNCHECKED : MF_CHECKED);
  482.  
  483.             InvalidateRect(hwnd, NULL, FALSE);
  484.             UpdateWindow(hwnd);
  485.         }
  486.         break;
  487.   }
  488.     return 0L;
  489. }
  490.  
  491. /***************************************************************************
  492.   DibHalftoneDIB
  493.  
  494.   Halftone a 24-bit DIB to the 8-bit WinG Halftone Palette
  495. */
  496.  
  497. //*** These tables are defined in httables.c
  498. extern char unsigned  aDividedBy51Rounded[256];
  499. extern char unsigned  aDividedBy51[256];
  500. extern char unsigned  aModulo51[256];
  501. extern char unsigned  aTimes6[6];
  502. extern char unsigned  aTimes36[6];
  503.  
  504. extern char unsigned  aHalftone8x8[64];
  505.  
  506. extern char unsigned  aWinGHalftoneTranslation[216];
  507.  
  508. PDIB DibHalftoneDIB( PDIB pSource )
  509. {
  510.   //*** Create an 8-bit DIB to halftone to
  511.   PDIB pDestination = DibCreate(8,DibWidth(pSource),DibHeight(pSource));
  512.  
  513.   //*** Only work on 24-bit sources
  514.   if(pDestination && hpalApp && (DibBitCount(pSource) == 24))
  515.   {
  516.     long PixelsPerScanline = DibWidth(pSource);
  517.     int Scanline;
  518.  
  519.     //*** Fill in the DIB color table with the halftone palette
  520.     DibSetUsage(pDestination, hpalApp, DIB_RGB_COLORS);
  521.  
  522.     //*** Step through, converting each pixel in each scan line
  523.     //*** to the nearest halftone match
  524.     for(Scanline = 0;Scanline < (int)DibHeight(pSource);Scanline++)
  525.     {
  526.       char unsigned _huge *pSourceScanline =
  527.           (char unsigned _huge *)DibXY(pSource,0,Scanline);
  528.           
  529.       char unsigned _huge *pDestinationScanline =
  530.           (char unsigned _huge *)DibXY(pDestination,0,Scanline);
  531.  
  532.       int Pixel;
  533.  
  534.       for(Pixel = 0;Pixel < (int)DibWidth(pSource);Pixel++)
  535.       {
  536.         //*** This is the meat of the halftoning algorithm:
  537.         //*** Convert an RGB into an index into the halftone palette.
  538.  
  539.         //*** First, extract the raw RGB information
  540.         int Red = pSourceScanline[Pixel*3 + 2];
  541.         int Green = pSourceScanline[Pixel*3 + 1];
  542.         int Blue = pSourceScanline[Pixel*3];
  543.  
  544.         //*** Now, look up each value in the halftone matrix
  545.         //*** using an 8x8 ordered dither.
  546.         char unsigned RedTemp = aDividedBy51[Red]
  547.           + (aModulo51[Red] > aHalftone8x8[(Pixel%8)*8
  548.           + Scanline%8]);
  549.         char unsigned GreenTemp = aDividedBy51[(char unsigned)Green]
  550.           + (aModulo51[Green] > aHalftone8x8[
  551.           (Pixel%8)*8 + Scanline%8]);
  552.         char unsigned BlueTemp = aDividedBy51[(char unsigned)Blue]
  553.           + (aModulo51[Blue] > aHalftone8x8[
  554.           (Pixel%8)*8 +Scanline%8]);
  555.  
  556.         //*** Recombine the halftoned RGB values into a palette index
  557.         char unsigned PaletteIndex =
  558.           RedTemp + aTimes6[GreenTemp] + aTimes36[BlueTemp];
  559.  
  560.         //*** And translate through the WinG Halftone Palette
  561.         //*** translation vector to give the correct value.
  562.         pDestinationScanline[Pixel] = aWinGHalftoneTranslation[PaletteIndex];
  563.       }
  564.     }
  565.   }
  566.   else
  567.   {
  568.     //*** Punt on anything but 24bpp
  569.     DibFree(pDestination);
  570.     pDestination = 0;
  571.   }
  572.  
  573.   return pDestination;
  574. }
  575.