home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / DIBSection.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  9.4 KB  |  371 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   : dibsection.cpp                                                         //
  10. //  Description: KDIBSection class, EMF rendering, AirBrush                          //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define WIN32_LEAN_AND_MEAN
  16.  
  17. #include <windows.h>
  18. #include <assert.h>
  19. #include <tchar.h>
  20. #include <math.h>
  21.  
  22. #include "DIBSection.h"
  23. #include "BitmapInfo.h"
  24.  
  25. // Copy from DIB section color table to DIB color table
  26. UINT KDIBSection::GetColorTable(void)
  27. {
  28.     int width, height;
  29.  
  30.     if ( (GetDepth()>8) || ! Prepare(width, height) ) // create memory DC
  31.         return 0;
  32.  
  33.     return GetDIBColorTable(m_hMemDC, 0, m_nClrUsed, m_pRGBQUAD);
  34. }
  35.  
  36.  
  37. // Copy from DIB's color table to DIB section's color table
  38. UINT KDIBSection::SetColorTable(void)
  39. {
  40.     int width, height;
  41.  
  42.     if ( (GetDepth()>8) || ! Prepare(width, height) ) // create memory DC
  43.         return 0;
  44.  
  45.     return SetDIBColorTable(m_hMemDC, 0, m_nClrUsed, m_pRGBQUAD);
  46. }
  47.  
  48.  
  49. void KDIBSection::DecodeDIBSectionFormat(TCHAR desp[])
  50. {
  51.     DIBSECTION dibsec;
  52.  
  53.     if ( GetObject(m_hBitmap, sizeof(DIBSECTION), & dibsec) )
  54.     {
  55.         KDIB::DecodeDIBFormat(desp);
  56.         _tcscat(desp, _T("   "));
  57.         DecodeDDB(GetBitmap(), desp + _tcslen(desp));
  58.     }
  59.     else
  60.         _tcscpy(desp, _T("Invalid DIB Section"));
  61. }
  62.  
  63.  
  64. BOOL KDIBSection::CreateDIBSection(HDC hDC, CONST BITMAPINFO * pBMI, UINT iUsage, HANDLE hSection, DWORD dwOffset)
  65. {
  66.     PVOID pBits = NULL;
  67.     
  68.     HBITMAP hBmp = ::CreateDIBSection(hDC, pBMI, iUsage, & pBits, hSection, dwOffset);
  69.  
  70.     int typ = GetObjectType(hBmp);
  71.     int size = GetObject(hBmp, 0, NULL);
  72.  
  73.     if ( hBmp )
  74.     {
  75.         ReleaseDDB();    // free the previous object
  76.         ReleaseDIB();    
  77.         
  78.         m_hBitmap = hBmp;    // Use DDB handle to store DIB Section Handle
  79.  
  80. //        MEMORY_BASIC_INFORMATION mbi;
  81. //        VirtualQuery(pBits, & mbi, sizeof(mbi));
  82.  
  83.         int nColor = GetDIBColorCount(pBMI->bmiHeader);
  84.         int nSize  = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColor;
  85.         
  86.         BITMAPINFO * pDIB = (BITMAPINFO *) new BYTE[nSize];
  87.  
  88.         if ( pDIB==NULL )
  89.             return FALSE;
  90.  
  91.         memcpy(pDIB, pBMI, nSize);    // copy header and color table
  92.  
  93.         AttachDIB(pDIB, (PBYTE) pBits, DIB_BMI_NEEDFREE);
  94.         GetColorTable();
  95.         return TRUE;
  96.     }
  97.     else
  98.         return FALSE;
  99. }
  100.  
  101.  
  102. // Search for the largest DIBSection 
  103. HBITMAP LargestDIBSection(BITMAPINFO * pBMI)
  104. {
  105.     HBITMAP hBmp;
  106.  
  107.     int mins = 1;            // 1       pixel
  108.     int maxs = 1024 * 128;    // 16 Giga pixels
  109.  
  110.     while ( true ) // search for largest DDB
  111.     {
  112.         int mid = (mins + maxs)/2;
  113.  
  114.         pBMI->bmiHeader.biWidth = mid;
  115.         pBMI->bmiHeader.biHeight= mid;
  116.  
  117.         hBmp = CreateDIBSection(NULL, pBMI, DIB_RGB_COLORS, NULL, NULL, NULL);
  118.  
  119.         if ( hBmp )
  120.         {
  121.             pBMI->bmiHeader.biWidth = mid+1;
  122.             pBMI->bmiHeader.biHeight= mid+1;
  123.  
  124.             HBITMAP h = CreateDIBSection(NULL, pBMI, DIB_RGB_COLORS, NULL, NULL, NULL);
  125.  
  126.             if ( h==NULL )
  127.                 return hBmp;
  128.  
  129.             DeleteObject(h);
  130.             DeleteObject(hBmp);
  131.  
  132.             mins = mid+1;
  133.         }
  134.         else
  135.             maxs = mid;
  136.     }
  137.  
  138.     return NULL;
  139. }
  140.  
  141.  
  142. // Draw a 3D rectangle frame with color shades
  143. void Frame(HDC hDC, int nFrame, COLORREF crFrame, int left, int top, int right, int bottom)
  144. {
  145.     int red   = GetRValue(crFrame);
  146.     int green = GetGValue(crFrame);
  147.     int blue  = GetBValue(crFrame);
  148.     RECT rect = { left, top, right, bottom };
  149.  
  150.     for (int i=0; i<nFrame; i++)
  151.     {
  152.         HBRUSH hBrush = CreateSolidBrush(RGB(red, green, blue));
  153.         FrameRect(hDC, & rect, hBrush);
  154.         DeleteObject(hBrush);
  155.  
  156.         if ( i<nFrame/2 )
  157.         {
  158.             red   = red   * 19/20;    // darker
  159.             green = green * 19/20;
  160.             blue  = blue  * 19/20;
  161.         }
  162.         else
  163.         {
  164.             red   = red   * 19/18; if ( red>255 )   red  = 255;    // lighter
  165.             green = green * 19/18; if ( green>255 ) green= 255;
  166.             blue  = blue  * 19/18; if ( blue>255 )  blue = 255;
  167.         }
  168.  
  169.         InflateRect(&rect, -1, -1);
  170.     }
  171. }
  172.  
  173.  
  174. // Window contents saver using DIBSECTION
  175. BOOL SaveWindow(HWND hWnd, bool bClient, int nFrame, COLORREF crFrame)
  176. {
  177.     RECT wnd;
  178.  
  179.     if ( bClient )
  180.     {
  181.         if ( ! GetClientRect(hWnd, & wnd) )
  182.             return FALSE;
  183.     }
  184.     else
  185.     {
  186.         if ( ! GetWindowRect(hWnd, & wnd) )
  187.             return FALSE;
  188.     }
  189.  
  190.     KBitmapInfo bmi;
  191.     KDIBSection dibsec;
  192.  
  193.     bmi.SetFormat(wnd.right - wnd.left + nFrame * 2, wnd.bottom - wnd.top + nFrame *2, 24, BI_RGB);
  194.  
  195.     if ( dibsec.CreateDIBSection(NULL, bmi.GetBMI(), DIB_RGB_COLORS, NULL, NULL) )
  196.     {
  197.         int width, height;
  198.         dibsec.Prepare(width, height); // creates memory DC, select dibsec into memDC
  199.  
  200.         if ( nFrame )
  201.         {
  202.             Frame(dibsec.m_hMemDC, nFrame, crFrame, 0, 0, width, height); 
  203.  
  204.             TCHAR Title[128];
  205.             GetWindowText(hWnd, Title, sizeof(Title)/sizeof(Title[0]));
  206.             SetBkMode(dibsec.m_hMemDC, TRANSPARENT);
  207.             SetTextColor(dibsec.m_hMemDC, RGB(0xFF, 0xFF, 0xFF));
  208.             TextOut(dibsec.m_hMemDC, nFrame, (nFrame-20)/2, Title, _tcslen(Title));
  209.         }
  210.  
  211.         HDC hDC;
  212.         if ( bClient )
  213.             hDC = GetDC(hWnd);
  214.         else
  215.             hDC = GetWindowDC(hWnd);
  216.         
  217.         BitBlt(dibsec.m_hMemDC, nFrame, nFrame, width - nFrame * 2, height - nFrame * 2, hDC, 0, 0, SRCCOPY);
  218.         ReleaseDC(hWnd, hDC);
  219.  
  220.         return dibsec.SaveFile(NULL);
  221.     }
  222.     return FALSE;
  223. }
  224.  
  225.  
  226. KTarga24::KTarga24()
  227. {
  228.     m_hFile           = INVALID_HANDLE_VALUE;
  229.     m_hFileMapping = INVALID_HANDLE_VALUE;
  230. }
  231.  
  232.  
  233. KTarga24::~KTarga24()
  234. {
  235.     ReleaseDDB();
  236.     ReleaseDIB();
  237.  
  238.     if ( m_hFileMapping!=INVALID_HANDLE_VALUE )
  239.         CloseHandle(m_hFileMapping);
  240.  
  241.     if ( m_hFile != INVALID_HANDLE_VALUE )
  242.         CloseHandle(m_hFile);
  243. }
  244.  
  245.  
  246. BOOL KTarga24::Create(int width, int height, const TCHAR * pFileName)
  247. {
  248.     if ( width & 3 )    // avoid compatiblity problem with TGA
  249.         return FALSE;
  250.  
  251.     ImageHeader tgaheader;
  252.  
  253.     memset(& tgaheader, 0, sizeof(tgaheader));
  254.     tgaheader.IDLength  = sizeof(tgaheader.ID);
  255.     tgaheader.ImgType   = 2;
  256.     tgaheader.Width     = width;
  257.     tgaheader.Height    = height;
  258.     tgaheader.PixelSize = 24;
  259.     strcpy(tgaheader.ID, "BitmapShop");
  260.  
  261.     m_hFile = CreateFile(pFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 
  262.         NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  263.  
  264.     if ( m_hFile==INVALID_HANDLE_VALUE )
  265.         return FALSE;
  266.  
  267.     int imagesize = (width*3+3)/4*4 * height;
  268.  
  269.     m_hFileMapping = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, 0, sizeof(tgaheader) + imagesize, NULL);
  270.     if ( m_hFileMapping==INVALID_HANDLE_VALUE )
  271.         return FALSE;
  272.  
  273.     DWORD dwWritten = NULL;
  274.     WriteFile(m_hFile, & tgaheader, sizeof(tgaheader), &dwWritten, NULL);
  275.     SetFilePointer(m_hFile, sizeof(tgaheader) + imagesize, 0, FILE_BEGIN);
  276.     SetEndOfFile(m_hFile);
  277.  
  278.     KBitmapInfo bmi;
  279.  
  280.     bmi.SetFormat(width, height, 24, BI_RGB);
  281.  
  282.     return CreateDIBSection(NULL, bmi.GetBMI(), DIB_RGB_COLORS, m_hFileMapping, sizeof(tgaheader));
  283. }
  284.  
  285.  
  286. BOOL RenderEMF(HENHMETAFILE hemf, int width, int height, const TCHAR * tgaFileName)
  287. {
  288.     KTarga24 targa;
  289.  
  290.     int w = (width+3)/4*4;
  291.     
  292.     if ( targa.Create(w, height, tgaFileName) )
  293.     {
  294.         targa.Prepare(w, height);
  295.  
  296.         // DIBSECTION dibsec;
  297.         // GetObject(targa.GetBitmap(), sizeof(DIBSECTION), & dibsec);
  298.  
  299.         BitBlt(targa.m_hMemDC, 0, 0, width, height, NULL, 0, 0, WHITENESS); // clear
  300.         
  301.         RECT rect = { 0, 0, width, height };
  302.  
  303.         for (int h=0; h<=height; h+=128 )
  304.         {
  305.             HRGN hRgn = CreateRectRgn(0, h, width, h+128);
  306.  
  307.             SelectClipRgn(targa.m_hMemDC, hRgn);
  308.             DeleteObject(hRgn);
  309.             
  310.             if ( ! PlayEnhMetaFile(targa.m_hMemDC, hemf, &rect) ) 
  311.                 return FALSE;
  312.         }
  313.      }
  314.     
  315.     return FALSE;
  316. }
  317.  
  318.  
  319. void KAirBrush::Apply(HDC hDC, int x, int y)
  320. {
  321.     BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
  322.  
  323.     AlphaBlend(hDC, x-m_nWidth/2, y-m_nHeight/2, m_nWidth, m_nHeight, m_hMemDC, 0, 0, m_nWidth, m_nHeight, blend);
  324. }
  325.  
  326.  
  327. void KAirBrush::Create(int width, int height, COLORREF color)
  328. {
  329.     Release();
  330.  
  331.     BYTE * pBits;
  332.     BITMAPINFO Bmi = { { sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB } };
  333.  
  334.     m_hBrush  = CreateDIBSection(NULL, & Bmi, DIB_RGB_COLORS, (void **) & pBits, NULL, NULL);
  335.     m_hMemDC  = CreateCompatibleDC(NULL);
  336.     m_hOld    = (HBITMAP) SelectObject(m_hMemDC, m_hBrush);
  337.     m_nWidth  = width;
  338.     m_nHeight = height;
  339.  
  340.     
  341.     // solid color circle, on white background
  342.     {    
  343.         PatBlt(m_hMemDC, 0, 0, width, height, WHITENESS);
  344.  
  345.         HBRUSH hBrush = CreateSolidBrush(color);
  346.         SelectObject(m_hMemDC, hBrush);
  347.         SelectObject(m_hMemDC, GetStockObject(NULL_PEN));
  348.         
  349.         Ellipse(m_hMemDC, 0, 0, width, height);
  350.         
  351.         SelectObject(m_hMemDC, GetStockObject(WHITE_BRUSH));
  352.         DeleteObject(hBrush);
  353.     }
  354.     
  355.     BYTE * pPixel = pBits;
  356.  
  357.     for (int y=0; y<height; y++)
  358.     for (int x=0; x<width;  x++, pPixel+=4)
  359.     {
  360.         int  dis   = (int) ( sqrt( (x-width/2) * (x-width/2) + (y-height/2) * (y-height/2) ) * 255 / (max(width, height)/2) );
  361.  
  362.         BYTE alpha = (BYTE) max(min(255-dis, 255), 0);
  363.  
  364.         pPixel[0] = pPixel[0] * alpha / 255;
  365.         pPixel[1] = pPixel[1] * alpha / 255;
  366.         pPixel[2] = pPixel[2] * alpha / 255;
  367.         pPixel[3] = alpha;
  368.     }
  369. }
  370.  
  371.