home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Hits 1995 June / Image.iso / demos / woodruff / wing / halftone.c_ / halftone.c
Encoding:
C/C++ Source or Header  |  1994-06-20  |  20.2 KB  |  576 lines

  1. /*
  2.  *    HALFTONE.C
  3.  *
  4.  *    (C) Copyright Microsoft Corp. 1994.  All rights reserved.
  5.  *
  6.  *    You have a royalty-free right to use, modify, reproduce and 
  7.  *    distribute the Sample Files (and/or any modified version) in 
  8.  *    any way you find useful, provided that you agree that 
  9.  *    Microsoft has no warranty obligations or liability for any 
  10.  *    Sample Application Files which are modified. 
  11.  */
  12.  
  13.  
  14. #include <windows.h>
  15. #include <windowsx.h>
  16. #include <commdlg.h>
  17.  
  18. #include <wing.h>
  19.  
  20. #include "halftone.h"
  21. #include "dib.h"
  22.  
  23. /*----------------------------------------------------------------------------*\
  24. |                                                                              |
  25. |   g l o b a l   v a r i a b l e s                                            |
  26. |                                                                              |
  27. \*----------------------------------------------------------------------------*/
  28. static    char    szAppName[]="WinG Halftoning Sample";
  29. static    char    szAppFilter[]="Bitmaps\0*.bmp;*.dib\0";
  30.  
  31. static  HINSTANCE hInstApp;
  32. static  HWND      hwndApp;
  33. static    HPALETTE  hpalApp;
  34. static    BOOL      fAppActive;
  35.  
  36. static BOOL fCustomDither = TRUE;
  37.  
  38. static PDIB pdibOriginal = 0;
  39. static PDIB pdibHalftone = 0;
  40.  
  41. #ifdef WIN32
  42.     #define _export
  43. #endif
  44.  
  45. /*----------------------------------------------------------------------------*\
  46. |                                                                              |
  47. |   f u n c t i o n   d e f i n i t i o n s                                    |
  48. |                                                                              |
  49. \*----------------------------------------------------------------------------*/
  50.  
  51. LONG FAR PASCAL _export AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
  52. LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
  53.  
  54. void AppExit(void);
  55. BOOL AppIdle(void);
  56. void AppOpenFile(HWND hwnd, LPSTR szFileName);
  57.  
  58. PDIB DibHalftoneDIB( PDIB pSource );
  59.  
  60. /*----------------------------------------------------------------------------*\
  61. |   AppAbout( hDlg, uiMessage, wParam, lParam )                                |
  62. |                                                                              |
  63. |   Description:                                                               |
  64. |       This function handles messages belonging to the "About" dialog box.    |
  65. |       The only message that it looks for is WM_COMMAND, indicating the use   |
  66. |       has pressed the "OK" button.  When this happens, it takes down         |
  67. |       the dialog box.                                                        |
  68. |                                                                              |
  69. |   Arguments:                                                                 |
  70. |       hDlg            window handle of about dialog window                   |
  71. |       uiMessage       message number                                         |
  72. |       wParam          message-dependent                                      |
  73. |       lParam          message-dependent                                      |
  74. |                                                                              |
  75. |   Returns:                                                                   |
  76. |       TRUE if message has been processed, else FALSE                         |
  77. |                                                                              |
  78. \*----------------------------------------------------------------------------*/
  79. BOOL FAR PASCAL _export AppAbout(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  80. {
  81.     switch (msg)
  82.     {
  83.         case WM_COMMAND:
  84.         if (LOWORD(wParam) == IDOK)
  85.             {
  86.                 EndDialog(hwnd,TRUE);
  87.             }
  88.             break;
  89.  
  90.         case WM_INITDIALOG:
  91.             return TRUE;
  92.     }
  93.     return FALSE;
  94. }
  95.  
  96. /*----------------------------------------------------------------------------*\
  97. |   AppInit( hInst, hPrev)                                                     |
  98. |                                                                              |
  99. |   Description:                                                               |
  100. |       This is called when the application is first loaded into               |
  101. |       memory.  It performs all initialization that doesn't need to be done   |
  102. |       once per instance.                                                     |
  103. |                                                                              |
  104. |   Arguments:                                                                 |
  105. |       hInstance       instance handle of current instance                    |
  106. |       hPrev           instance handle of previous instance                   |
  107. |                                                                              |
  108. |   Returns:                                                                   |
  109. |       TRUE if successful, FALSE if not                                       |
  110. |                                                                              |
  111. \*----------------------------------------------------------------------------*/
  112. BOOL AppInit(HINSTANCE hInst,HINSTANCE hPrev,int sw,LPSTR szCmdLine)
  113. {
  114.     WNDCLASS cls;
  115.     int      dx,dy;
  116.       HMENU hMenu;
  117.  
  118.     /* Save instance handle for DialogBoxs */
  119.     hInstApp = hInst;
  120.  
  121.     if (!hPrev)
  122.     {
  123.         /*
  124.          *  Register a class for the main application window
  125.          */
  126.         cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  127.         cls.hIcon          = LoadIcon(hInst,"AppIcon");
  128.         cls.lpszMenuName   = "AppMenu";
  129.         cls.lpszClassName  = szAppName;
  130.         cls.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  131.         cls.hInstance      = hInst;
  132.         cls.style          = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  133.         cls.lpfnWndProc    = (WNDPROC)AppWndProc;
  134.         cls.cbWndExtra     = 0;
  135.         cls.cbClsExtra     = 0;
  136.  
  137.         if (!RegisterClass(&cls))
  138.             return FALSE;
  139.     }
  140.  
  141.     dx = GetSystemMetrics (SM_CXSCREEN) / 2;
  142.     dy = GetSystemMetrics (SM_CYSCREEN) / 2;
  143.  
  144.     hpalApp = WinGCreateHalftonePalette();
  145.  
  146.     hwndApp = CreateWindow (szAppName,    // Class name
  147.                             szAppName,              // Caption
  148.                             WS_OVERLAPPEDWINDOW,    // Style bits
  149.                             CW_USEDEFAULT, 0,       // Position
  150.                 dx,dy,            // Size
  151.                             (HWND)NULL,             // Parent window (no parent)
  152.                             (HMENU)NULL,            // use class menu
  153.                             hInst,                  // handle to window instance
  154.                             (LPSTR)NULL             // no params to pass on
  155.                            );
  156.     ShowWindow(hwndApp,sw);
  157.  
  158.     //*** Check the default dither selection
  159.     hMenu = GetMenu(hwndApp);
  160.     CheckMenuItem(hMenu, MENU_WING, fCustomDither ? MF_CHECKED : MF_UNCHECKED);
  161.     CheckMenuItem(hMenu, MENU_GDI, fCustomDither ? MF_UNCHECKED : MF_CHECKED);
  162.  
  163.     if (*szCmdLine)
  164.     AppOpenFile(hwndApp, szCmdLine);
  165.  
  166.     return TRUE;
  167. }
  168.  
  169.  
  170. /*----------------------------------------------------------------------------*\
  171. |   AppExit()                                       |
  172. |                                                                              |
  173. |   Description:                                                               |
  174. |    app is just about to exit, cleanup                       |
  175. |                                                                              |
  176. \*----------------------------------------------------------------------------*/
  177. void AppExit()
  178. {
  179.     if (hpalApp)
  180.         DeleteObject(hpalApp);
  181.     if (pdibOriginal)
  182.         DibFree(pdibOriginal);
  183.     if (pdibHalftone)
  184.         DibFree(pdibHalftone);
  185. }
  186.  
  187. /*----------------------------------------------------------------------------*\
  188. |   WinMain( hInst, hPrev, lpszCmdLine, cmdShow )                              |
  189. |                                                                              |
  190. |   Description:                                                               |
  191. |       The main procedure for the App.  After initializing, it just goes      |
  192. |       into a message-processing loop until it gets a WM_QUIT message         |
  193. |       (meaning the app was closed).                                          |
  194. |                                                                              |
  195. |   Arguments:                                                                 |
  196. |       hInst           instance handle of this instance of the app            |
  197. |       hPrev           instance handle of previous instance, NULL if first    |
  198. |       szCmdLine       ->null-terminated command line                         |
  199. |       cmdShow         specifies how the window is initially displayed        |
  200. |                                                                              |
  201. |   Returns:                                                                   |
  202. |       The exit code as specified in the WM_QUIT message.                     |
  203. |                                                                              |
  204. \*----------------------------------------------------------------------------*/
  205. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
  206. {
  207.     MSG     msg;
  208.  
  209.     /* Call initialization procedure */
  210.     if (!AppInit(hInst,hPrev,sw,szCmdLine))
  211.     return FALSE;
  212.  
  213.     /*
  214.      * Polling messages from event queue
  215.      */
  216.     for (;;)
  217.     {
  218.         if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
  219.         {
  220.             if (msg.message == WM_QUIT)
  221.                 break;
  222.  
  223.             TranslateMessage(&msg);
  224.             DispatchMessage(&msg);
  225.         }
  226.         else
  227.     {
  228.         if (AppIdle())
  229.                 WaitMessage();
  230.         }
  231.     }
  232.  
  233.     AppExit();
  234.     return msg.wParam;
  235. }
  236.  
  237. /*----------------------------------------------------------------------------*\
  238. |   AppIdle()                                       |
  239. |                                                                              |
  240. |   Description:                                                               |
  241. |    place to do idle time stuff.                           |
  242. |                                                                              |
  243. |   Returns:                                       |
  244. |    RETURN TRUE IF YOU HAVE NOTHING TO DO OTHERWISE YOUR APP WILL BE A     |
  245. |    CPU PIG!                                   |
  246. \*----------------------------------------------------------------------------*/
  247. BOOL AppIdle()
  248. {
  249.     if (fAppActive)
  250.     {
  251.     //
  252.     // we are the foreground app.
  253.     //
  254.     return TRUE;        // nothing to do.
  255.     }
  256.     else
  257.     {
  258.     //
  259.     // we are a background app.
  260.     //
  261.     return TRUE;        // nothing to do.
  262.     }
  263. }
  264.  
  265. /*----------------------------------------------------------------------------*\
  266. |   AppOpenFile()                                   |
  267. |                                                                              |
  268. |   Description:                                                               |
  269. |    open a file stupid                               |
  270. |                                                                              |
  271. \*----------------------------------------------------------------------------*/
  272. void AppOpenFile(HWND hwnd, LPSTR szFileName)
  273. {
  274.     HCURSOR hCur = LoadCursor(NULL, IDC_WAIT);
  275.     PDIB pdibNew;
  276.  
  277.     hCur = SetCursor(hCur);
  278.     
  279.     pdibNew = DibOpenFile(szFileName);
  280.  
  281.     if (pdibNew)
  282.     {
  283.         if (pdibOriginal)
  284.             DibFree(pdibOriginal);
  285.         if (pdibHalftone)
  286.             DibFree(pdibHalftone);
  287.  
  288.         pdibOriginal = pdibNew;
  289.         pdibHalftone = DibHalftoneDIB(pdibOriginal);
  290.  
  291.         if (DibBitCount(pdibOriginal) != 24)
  292.         {
  293.             MessageBox(hwnd, "Not a 24-bit DIB!", "Oops", MB_OK);
  294.         }
  295.  
  296.         InvalidateRect(hwnd, NULL, TRUE);
  297.         UpdateWindow(hwnd);
  298.     }
  299.  
  300.     hCur = SetCursor(hCur);
  301. }
  302.  
  303. /*----------------------------------------------------------------------------*\
  304. |   AppPaint(hwnd, hdc)                                                        |
  305. |                                                                              |
  306. |   Description:                                                               |
  307. |       The paint function.  Right now this does nothing.                      |
  308. |                                                                              |
  309. |   Arguments:                                                                 |
  310. |       hwnd             window painting into                                  |
  311. |       hdc              display context to paint to                           |
  312. |                                                                              |
  313. |   Returns:                                                                   |
  314. |       nothing                                                                |
  315. |                                                                              |
  316. \*----------------------------------------------------------------------------*/
  317. AppPaint (HWND hwnd, HDC hdc)
  318. {
  319.     if (fCustomDither && pdibHalftone)
  320.     {
  321.         StretchDIBits(hdc,
  322.             0, 0, DibWidth(pdibHalftone), DibHeight(pdibHalftone),
  323.             0, 0, DibWidth(pdibHalftone), DibHeight(pdibHalftone),
  324.             DibPtr(pdibHalftone), DibInfo(pdibHalftone),
  325.             DIB_RGB_COLORS, SRCCOPY);
  326.     }
  327.     else if (pdibOriginal)
  328.     {
  329.         StretchDIBits(hdc,
  330.             0, 0, DibWidth(pdibOriginal), DibHeight(pdibOriginal),
  331.             0, 0, DibWidth(pdibOriginal), DibHeight(pdibOriginal),
  332.             DibPtr(pdibOriginal), DibInfo(pdibOriginal),
  333.             DIB_RGB_COLORS, SRCCOPY);
  334.     }
  335.  
  336.     return TRUE;
  337. }
  338.  
  339. /*----------------------------------------------------------------------------*\
  340. |   AppWndProc( hwnd, uiMessage, wParam, lParam )                              |
  341. |                                                                              |
  342. |   Description:                                                               |
  343. |       The window proc for the app's main (tiled) window.  This processes all |
  344. |       of the parent window's messages.                                       |
  345. |                                                                              |
  346. \*----------------------------------------------------------------------------*/
  347. LONG FAR PASCAL _export AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
  348. {
  349.     PAINTSTRUCT ps;
  350.     HDC hdc;
  351.     BOOL f;
  352.  
  353.     switch (msg)
  354.     {
  355.         case WM_CREATE:
  356.         break;
  357.  
  358.         case WM_ACTIVATEAPP:
  359.         fAppActive = (BOOL)wParam;
  360.         break;
  361.  
  362.         case WM_TIMER:
  363.             break;
  364.  
  365.         case WM_ERASEBKGND:
  366.             break;
  367.  
  368.         case WM_INITMENU:
  369.             break;
  370.  
  371.         case WM_COMMAND:
  372.             return AppCommand(hwnd,msg,wParam,lParam);
  373.  
  374.     case WM_DESTROY:
  375.             PostQuitMessage(0);
  376.             break;
  377.  
  378.         case WM_CLOSE:
  379.         break;
  380.  
  381.         case WM_PALETTECHANGED:
  382.         if ((HWND)wParam == hwnd)
  383.         break;
  384.  
  385.         // fall through to WM_QUERYNEWPALETTE
  386.  
  387.     case WM_QUERYNEWPALETTE:
  388.         hdc = GetDC(hwnd);
  389.  
  390.         if (hpalApp)
  391.         SelectPalette(hdc, hpalApp, FALSE);
  392.  
  393.         f = RealizePalette(hdc);
  394.         ReleaseDC(hwnd,hdc);
  395.  
  396.         if (f)
  397.         InvalidateRect(hwnd,NULL,TRUE);
  398.  
  399.         return f;
  400.  
  401.         case WM_PAINT:
  402.             hdc = BeginPaint(hwnd,&ps);
  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,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. 
  576.