home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_12 / Imaging / Imaging.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-24  |  13.8 KB  |  567 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : imaging.cpp                                                         //
  10. //  Description: Image Processing Demostration Program, Chapter 12                   //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define _WIN32_WINNT 0x0500
  16. #define NOCRYPT
  17.  
  18. #include <windows.h>
  19. #include <assert.h>
  20. #include <tchar.h>
  21. #include <math.h>
  22.  
  23. #include "..\..\include\wingraph.h"
  24.  
  25. #include "Resource.h"
  26.  
  27.  
  28. class KDIBView : public KScrollCanvas
  29. {
  30.     typedef enum { GAP = 16 };
  31.  
  32.     virtual void    OnDraw(HDC hDC, const RECT * rcPaint);
  33.     virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  34.     void            GetWndClassEx(WNDCLASSEX & wc);
  35.     
  36.     HMENU            m_hViewMenu;
  37.     int                m_nViewOpt;
  38.     HWND            m_hFrame;
  39.  
  40. public:
  41.  
  42.     KImage            m_DIB;
  43.  
  44.     KDIBView(void)
  45.     {
  46.         m_hViewMenu = NULL;
  47.         m_nViewOpt  = IDM_VIEW_STRETCHDIBITS;
  48.     }
  49.  
  50.     bool Initialize(const TCHAR * pFileName, HINSTANCE hInstance, KStatusWindow * pStatus, HWND hFrame)
  51.     {
  52.         m_hFrame = hFrame;
  53.  
  54.         if ( m_DIB.LoadFile(pFileName) )
  55.         {
  56.             SetSize(m_DIB.GetWidth()  + GAP*2,
  57.                     m_DIB.GetHeight() + GAP*2, 5, 5);
  58.  
  59.             m_hInst   = hInstance;
  60.             m_pStatus = pStatus;
  61.  
  62.             RegisterClass(_T("DIBView"), hInstance);
  63.             
  64.             return true;
  65.         }
  66.         else
  67.             return false;
  68.     }
  69.  
  70.     bool Initialize(BITMAPINFO * pDIB, HINSTANCE hInstance, KStatusWindow * pStatus, HWND hFrame)
  71.     {
  72.         m_hFrame = hFrame;
  73.  
  74.         if ( m_DIB.AttachDIB(pDIB, NULL, DIB_BMI_NEEDFREE) )
  75.         {
  76.             SetSize(m_DIB.GetWidth()  + GAP*2,
  77.                     m_DIB.GetHeight() + GAP*2, 5, 5);
  78.  
  79.             m_hInst   = hInstance;
  80.             m_pStatus = pStatus;
  81.  
  82.             RegisterClass(_T("DIBView"), hInstance);
  83.             
  84.             return true;
  85.         }
  86.         else
  87.             return false;
  88.     }
  89.  
  90.     bool GetTitle(const TCHAR * pFileName, TCHAR * pTitle)
  91.     {
  92.         if ( pFileName )
  93.         {
  94.             wsprintf(pTitle, "%s, %d x %d pixel, %d bits", pFileName,
  95.                 m_DIB.GetWidth(), m_DIB.GetHeight(), m_DIB.GetDepth());
  96.  
  97.             return true;
  98.         }
  99.         else
  100.             return false;
  101.     }
  102.  
  103.     void CreateNewView(BITMAPINFO * pDIB, TCHAR * pTitle);
  104. };
  105.  
  106.  
  107. void KDIBView::GetWndClassEx(WNDCLASSEX & wc)
  108. {
  109.     memset(& wc, 0, sizeof(wc));
  110.  
  111.     wc.cbSize         = sizeof(WNDCLASSEX);
  112.     wc.style          = CS_HREDRAW | CS_VREDRAW;
  113.     wc.lpfnWndProc    = WindowProc;
  114.     wc.cbClsExtra     = 0;
  115.     wc.cbWndExtra     = 0;       
  116.     wc.hInstance      = NULL;
  117.     wc.hIcon          = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_IMAGE));
  118.     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  119.     wc.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH); // (COLOR_GRAYTEXT + 1);
  120.     wc.lpszMenuName   = NULL;
  121.     wc.lpszClassName  = NULL;
  122.     wc.hIconSm        = NULL;
  123. }
  124.  
  125.  
  126. // Let the main frame window handle it
  127. void KDIBView::CreateNewView(BITMAPINFO * pDIB, TCHAR * pTitle)
  128. {
  129.     if ( pDIB )
  130.         SendMessage(m_hFrame, WM_USER, (WPARAM) pDIB, (LPARAM) pTitle);
  131. }
  132.  
  133.  
  134. LRESULT KDIBView::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  135. {
  136.     switch( uMsg )
  137.     {
  138.         case WM_CREATE:
  139.             m_hWnd        = hWnd;
  140.             m_hViewMenu = LoadMenu(m_hInst, MAKEINTRESOURCE(IDR_DIBVIEW));
  141.             return 0;
  142.  
  143.         case WM_PAINT:
  144.             return KScrollCanvas::WndProc(hWnd, uMsg, wParam, lParam);
  145.  
  146.         case WM_SIZE:
  147.         case WM_HSCROLL:
  148.         case WM_VSCROLL:
  149.         {
  150.             LRESULT lr = KScrollCanvas::WndProc(hWnd, uMsg, wParam, lParam);
  151.  
  152.             int nMin, nMax, nPos;
  153.  
  154.             GetScrollRange(m_hWnd, SB_VERT, &nMin, &nMax);
  155.  
  156.             nPos = GetScrollPos(m_hWnd, SB_VERT);
  157.  
  158.             TCHAR mess[32];
  159.             wsprintf(mess, "%d %d %d", nMin, nPos, nMax);
  160.             m_pStatus->SetText(0, mess);
  161.  
  162.             return lr;
  163.         }
  164.  
  165.         case WM_COMMAND:
  166.             switch ( LOWORD(wParam) )
  167.             {
  168.                 case IDM_COLOR_GREYSCALE:
  169.                     m_DIB.ToGreyScale();
  170.                     InvalidateRect(hWnd, NULL, TRUE);
  171.                     return 0;
  172.  
  173.                 case IDM_COLOR_LIGHTEN:
  174.                     m_DIB.Lighten();
  175.                     InvalidateRect(hWnd, NULL, TRUE);
  176.                     return 0;
  177.  
  178.                 case IDM_COLOR_GAMMA22:
  179.                     m_DIB.GammaCorrect(2.2, 2.2, 2.2);
  180.                     InvalidateRect(hWnd, NULL, TRUE);
  181.                     return 0;
  182.  
  183.                 case IDM_COLOR_SPLITRGB:
  184.                     CreateNewView(m_DIB.SplitChannel(TakeRed),   "Red Channel");
  185.                     CreateNewView(m_DIB.SplitChannel(TakeGreen), "Green Channel");
  186.                     CreateNewView(m_DIB.SplitChannel(TakeBlue),  "Blue Channel");
  187.                     return 0;
  188.  
  189.                 case IDM_COLOR_SPLITHLS:
  190.                     CreateNewView(m_DIB.SplitChannel(TakeH),  "Hue Channel");
  191.                     CreateNewView(m_DIB.SplitChannel(TakeL),  "Lightness Channel");
  192.                     CreateNewView(m_DIB.SplitChannel(TakeS),  "Saturation Channel");
  193.                     return 0;
  194.  
  195.                 case IDM_COLOR_SPLITKCMY:
  196.                     CreateNewView(m_DIB.SplitChannel(TakeK),  "Black Channel");
  197.                     CreateNewView(m_DIB.SplitChannel(TakeC),  "Cyan Channel");
  198.                     CreateNewView(m_DIB.SplitChannel(TakeM),  "Magenta Channel");
  199.                     CreateNewView(m_DIB.SplitChannel(TakeY),  "Yellow Channel");
  200.                     return 0;
  201.  
  202.                 case IDM_COLOR_SMOOTH:
  203.                     {
  204.                         m_DIB.Convolution(StockFilters[FILTER_SMOOTH]);
  205.                         InvalidateRect(hWnd, NULL, TRUE);
  206.                     }
  207.                     return 0;
  208.  
  209.                 case IDM_COLOR_GUASIANSMOOTH:
  210.                     {
  211.                         m_DIB.Convolution(StockFilters[FILTER_GUASSIANSMOOTH]);
  212.                         InvalidateRect(hWnd, NULL, TRUE);
  213.                     }
  214.                     return 0;
  215.  
  216.                 case IDM_COLOR_SHARPENING:
  217.                     {
  218.                         m_DIB.Convolution(StockFilters[FILTER_SHARPENING]);
  219.                         InvalidateRect(hWnd, NULL, TRUE);
  220.                     }
  221.                     return 0;
  222.  
  223.                 case IDM_COLOR_LAPLASIAN:
  224.                     {
  225.                         m_DIB.Convolution(StockFilters[FILTER_LAPLASION]);
  226.                         InvalidateRect(hWnd, NULL, TRUE);
  227.                     }
  228.                     return 0;
  229.  
  230.                 case IDM_COLOR_EMBOSS135:
  231.                     {
  232.                         m_DIB.Convolution(StockFilters[FILTER_EMBOSS135]);
  233.                         InvalidateRect(hWnd, NULL, TRUE);
  234.                     }
  235.                     return 0;
  236.  
  237.                 case IDM_COLOR_EMBOSS90:
  238.                     {
  239.                         m_DIB.Convolution(StockFilters[FILTER_EMBOSS90]);
  240.                         InvalidateRect(hWnd, NULL, TRUE);
  241.                     }
  242.                     return 0;
  243.  
  244.                 case IDM_VIEW_STRETCHDIBITS:
  245.                 case IDM_VIEW_MASKRED:
  246.                 case IDM_VIEW_ROTATEGDI:
  247.                 case IDM_VIEW_ROTATE:
  248.                 case IDM_VIEW_ROTATE24:
  249.                 case IDM_VIEW_FILTERS1:
  250.                 case IDM_VIEW_FILTERS2:
  251.                 case IDM_VIEW_FILTERS3:
  252.                     if ( LOWORD(wParam)!= m_nViewOpt )
  253.                     {
  254.                         m_nViewOpt = LOWORD(wParam);
  255.  
  256.                         switch ( LOWORD(wParam) )
  257.                         {
  258.                             case IDM_VIEW_STRETCHDIBITS:
  259.                             case IDM_VIEW_MASKRED:
  260.                                 SetSize(m_DIB.GetWidth() + GAP*2, m_DIB.GetHeight() + GAP*2, 5, 5, true);
  261.                                 break;
  262.  
  263.                             case IDM_VIEW_ROTATEGDI:
  264.                             case IDM_VIEW_ROTATE:
  265.                             case IDM_VIEW_ROTATE24:
  266.                                 SetSize(m_DIB.GetWidth()*2 + GAP*3, m_DIB.GetHeight()*2 + GAP*3, 5, 5, true);
  267.                                 break;
  268.  
  269.                             case IDM_VIEW_FILTERS1:
  270.                             case IDM_VIEW_FILTERS2:
  271.                             case IDM_VIEW_FILTERS3:
  272.                                 SetSize(m_DIB.GetWidth()*3 + GAP*2, m_DIB.GetHeight()*2 + GAP*3, 5, 5, true);
  273.                         }
  274.  
  275.                         InvalidateRect(hWnd, NULL, TRUE);
  276.                     }
  277.                     return 0;
  278.  
  279.                 case IDM_VIEW_DIBHEXDUMP:
  280.                     SendMessage(GetParent(GetParent(hWnd)), WM_USER+1, (WPARAM) & m_DIB, 0);    
  281.             }
  282.             return 0;
  283.  
  284.         default:
  285.             return CommonMDIChildProc(hWnd, uMsg, wParam, lParam, m_hViewMenu, 3);
  286.     }
  287. }
  288.  
  289.  
  290. void TestDIBTransform(HDC hDC, int x, int y, int w, int h, KDIB * pSrc, int method)
  291. {
  292.     KAffine affine;
  293.  
  294.     affine.Rotate(-15);
  295.  
  296.     HBITMAP hBitmap = pSrc->TransformBitmap(& affine.m_xm, RGB(0xFF, 0xFF, 0), method);
  297.  
  298.     assert(hBitmap);
  299.     HDC hMemDC = CreateCompatibleDC(hDC);
  300.     SelectObject(hMemDC, hBitmap);
  301.     
  302.     BITMAP bmp;
  303.  
  304.     GetObject(hBitmap, sizeof(BITMAP), & bmp);
  305.     BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0, SRCCOPY);
  306.     DeleteObject(hMemDC);
  307.     DeleteObject(hBitmap);
  308. }
  309.  
  310.  
  311. void TestFilters(HDC hDC, int x, int y, int w, int h, KImage & dib, int nFilterID[], int scale)
  312. {
  313.     BYTE * pTemp = new BYTE[dib.m_nImageSize];
  314.     memcpy(pTemp, dib.GetBits(), dib.m_nImageSize);    //save pixel array
  315.  
  316.     SetBkMode(hDC, TRANSPARENT);
  317.     SetTextColor(hDC, 0); // RGB(0xFF, 0xFF, 0xFF));
  318.  
  319.     for (int i=0; i<4; i++)
  320.     {
  321.         int xx = x + (w*scale + 120) * ( i % 2);
  322.         int yy = y + (h*scale + 10) * ( i / 2);
  323.  
  324.         int filter = nFilterID[i];
  325.  
  326.         if ( StockFilters[filter] )
  327.         {
  328.             dib.Convolution(StockFilters[filter]);
  329.  
  330.             StockFilters[filter]->DescribeFilter(hDC, xx + w*scale + 5, yy + 5);
  331.         }
  332.  
  333.         StretchDIBits(hDC, xx, yy, 
  334.             w*scale, h*scale, 0, 0, w, h, dib.GetBits(), dib.GetBMI(), DIB_RGB_COLORS, SRCCOPY);
  335.         
  336.         memcpy(dib.GetBits(), pTemp, dib.m_nImageSize); // restore pixel array
  337.     }
  338.  
  339.     delete pTemp;
  340. }
  341.  
  342. extern DWORD dibtick;
  343.  
  344. void KDIBView::OnDraw(HDC hDC, const RECT * rcPaint)
  345. {
  346.     DWORD tm = GetTickCount();
  347.     
  348.     dibtick = 0;
  349.     int w = m_DIB.GetWidth();
  350.     int h = m_DIB.GetHeight();
  351.  
  352.     switch ( m_nViewOpt )
  353.     {
  354.         case IDM_VIEW_MASKRED:
  355.             {
  356.                 HDC     hMemDC = CreateCompatibleDC(NULL);
  357.                 HBITMAP hBmp = ChannelSplit(m_DIB.GetBMI(), m_DIB.GetBits(), RGB(0xFF, 0, 0), hMemDC);
  358.  
  359.                 BitBlt(hDC, GAP, GAP, w, h, hMemDC, 0, 0, SRCCOPY);
  360.                 DeleteObject(hBmp);
  361.                 DeleteObject(hMemDC);
  362.             }
  363.             break;
  364.  
  365.         case IDM_VIEW_STRETCHDIBITS:
  366.             m_DIB.DrawDIB(hDC, GAP,   GAP,    w, h, 0, 0,  w,  h, SRCCOPY);
  367.             break;
  368.  
  369.         case IDM_VIEW_ROTATEGDI:
  370.             TestDIBTransform(hDC, GAP, GAP, w, h, & m_DIB, KDIB::method_gdi);
  371.             break;
  372.  
  373.         case IDM_VIEW_ROTATE:
  374.             TestDIBTransform(hDC, GAP, GAP, w, h, & m_DIB, KDIB::method_direct);
  375.             break;
  376.  
  377.         case IDM_VIEW_ROTATE24:
  378.             TestDIBTransform(hDC, GAP, GAP, w, h, & m_DIB, KDIB::method_24bpp);
  379.             break;
  380.  
  381.         case IDM_VIEW_FILTERS1:
  382.             {
  383.                 int id[] = { 0, 1, 2, 3 };
  384.  
  385.                 TestFilters(hDC, GAP, GAP, w, h, m_DIB, id, 3);
  386.             }
  387.             break;
  388.  
  389.         case IDM_VIEW_FILTERS2:
  390.             {
  391.                 int id[] = { 0, 4, 5, 6 };
  392.  
  393.                 TestFilters(hDC, GAP, GAP, w, h, m_DIB, id, 1);
  394.             }
  395.             break;
  396.  
  397.         case IDM_VIEW_FILTERS3:
  398.             {
  399.                 int id[] = { 0, 7, 8, 9 };
  400.  
  401.                 TestFilters(hDC, GAP, GAP, w, h, m_DIB, id, 2);
  402.             }
  403.             break;
  404.  
  405.     }
  406.     RestoreDC(hDC, -1);
  407.  
  408.     tm = GetTickCount() - tm;
  409.  
  410.     if ( dibtick )
  411.         tm = dibtick;
  412.  
  413.     TCHAR mess[32];
  414.     wsprintf(mess, "Time %d ms", tm);
  415.     m_pStatus->SetText(1, mess);
  416. }
  417.  
  418. const int Translate[] =
  419. {
  420.     IDM_FILE_CLOSE,
  421.     IDM_FILE_EXIT,
  422.     IDM_WINDOW_TILE,
  423.     IDM_WINDOW_CASCADE,
  424.     IDM_WINDOW_ARRANGE,
  425.     IDM_WINDOW_CLOSEALL
  426. };
  427.  
  428.  
  429. class KMyMDIFRame : public KMDIFrame
  430. {
  431.     int                m_nCount;
  432.  
  433.     void CreateMDIChild(KScrollCanvas * canvas, const TCHAR * klass, const TCHAR * filename, const TCHAR * title)
  434.     {
  435.         MDICREATESTRUCT mdic;
  436.  
  437.         TCHAR Temp[MAX_PATH];
  438.  
  439.         if ( ! canvas->GetTitle(filename, Temp) )
  440.         {
  441.             m_nCount ++;
  442.             wsprintf(Temp, title, m_nCount);
  443.         }
  444.  
  445.         mdic.szClass = klass;
  446.         mdic.szTitle = Temp;
  447.         mdic.hOwner  = m_hInst;
  448.         mdic.x       = CW_USEDEFAULT;
  449.         mdic.y       = CW_USEDEFAULT;
  450.         mdic.cx      = CW_USEDEFAULT;
  451.         mdic.cy      = CW_USEDEFAULT;
  452.         mdic.style   = WS_VISIBLE | WS_BORDER;
  453.         mdic.lParam  = (LPARAM) canvas;
  454.  
  455.         SendMessage(m_hMDIClient, WM_MDICREATE, 0, (LPARAM) & mdic);
  456.     }
  457.  
  458.     void CreateDIBView(const TCHAR * pFileName)
  459.     {
  460.         KDIBView * pDIBView = new KDIBView();
  461.  
  462.         if ( pDIBView )
  463.             if ( pDIBView->Initialize(pFileName, m_hInst, m_pStatus, m_hWnd) )
  464.                 CreateMDIChild(pDIBView, _T("DIBView"), pFileName, _T("DIB %d"));
  465.             else
  466.                 delete pDIBView;
  467.     }
  468.  
  469.     void CreateDIBView(BITMAPINFO * pDIB, const TCHAR * pTitle)
  470.     {
  471.         KDIBView * pDIBView = new KDIBView();
  472.  
  473.         if ( pDIBView )
  474.             if ( pDIBView->Initialize(pDIB, m_hInst, m_pStatus, m_hWnd) )
  475.                 CreateMDIChild(pDIBView, _T("DIBView"), pTitle, _T("DIB %d"));
  476.             else
  477.                 delete pDIBView;
  478.     }
  479.  
  480.  
  481.     virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam)
  482.     {
  483.         switch ( LOWORD(wParam) )
  484.         {
  485. //            case IDM_FILE_NEW:
  486. //                CreateDIBView(NULL);
  487. //                return TRUE;
  488.  
  489.             case IDM_FILE_OPEN:
  490.             {
  491.                 KFileDialog fo;
  492.  
  493.                 if ( fo.GetOpenFileName(m_hWnd, "bmp", "Bitmap Files") )
  494.                     CreateDIBView(fo.m_TitleName);
  495.                 
  496.                 return TRUE;
  497.             }
  498.         }
  499.  
  500.         return FALSE;
  501.     }
  502.  
  503.     virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  504.     {
  505.         LRESULT lr = KMDIFrame::WndProc(hWnd, uMsg, wParam, lParam);
  506.  
  507.         if ( uMsg == WM_USER )
  508.         {
  509.             CreateDIBView((BITMAPINFO *) wParam, (const TCHAR *) lParam);
  510.         }
  511.  
  512. //        if ( uMsg == WM_CREATE )
  513. //        {
  514. //            SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); 
  515. //            SetLayeredWindowAttributes(m_hWnd, 0, 0xC0, LWA_ALPHA);
  516. //        }
  517.  
  518.         return lr;
  519.     }
  520.  
  521.     void GetWndClassEx(WNDCLASSEX & wc)
  522.     {
  523.         KMDIFrame::GetWndClassEx(wc);
  524.  
  525.         wc.hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_IMAGE));
  526.     }
  527.  
  528.  
  529. public:
  530.     KMyMDIFRame(HINSTANCE hInstance, const TBBUTTON * pButtons, int nCount,
  531.         KToolbar * pToolbar, KStatusWindow * pStatus) :
  532.         KMDIFrame(hInstance, pButtons, nCount, pToolbar, pStatus, Translate)
  533.     {
  534.         m_nCount = 0;
  535.     }
  536. };
  537.  
  538. const TBBUTTON tbButtons[] =
  539. {
  540. //    { STD_FILENEW,     IDM_FILE_NEW,   TBSTATE_ENABLED, TBSTYLE_BUTTON, { 0, 0 }, IDS_FILENEW,  0 },
  541.     { STD_FILEOPEN,  IDM_FILE_OPEN,  TBSTATE_ENABLED, TBSTYLE_BUTTON, { 0, 0 }, IDS_FILEOPEN, 0 }
  542. };
  543.  
  544.  
  545. int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nShow)
  546. {
  547.     KToolbar      toolbar;
  548.     KStatusWindow status;
  549.  
  550.     KMyMDIFRame frame(hInst, tbButtons, 1, & toolbar, & status);
  551.  
  552.     TCHAR title[MAX_PATH];
  553.  
  554.     _tcscpy(title, "Imaging");
  555.  
  556.     frame.CreateEx(0, _T("ClassName"), title,
  557.         WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  558.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
  559.         NULL, LoadMenu(hInst, MAKEINTRESOURCE(IDR_MAIN)), hInst);
  560.     
  561.     frame.ShowWindow(nShow);
  562.     frame.UpdateWindow();
  563.  
  564.     frame.MessageLoop();
  565.  
  566.     return 0;
  567. }