home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / FWGraphx / Sources / FWWinDIB.cpp < prev   
Encoding:
Text File  |  1995-11-08  |  20.3 KB  |  743 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWWinDIB.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifdef FW_BUILD_WIN
  13.  
  14. #ifndef FWWINDIB_H
  15. #include "FWWinDIB.h"
  16. #endif
  17.  
  18. #ifndef FWMEMMGR_H
  19. #include "FWMemMgr.h"
  20. #endif
  21.  
  22. #ifndef FWMEMHLP_H
  23. #include "FWMemHlp.h"
  24. #endif
  25.  
  26. #ifndef FWBITMAP_H
  27. #include "FWBitmap.h"
  28. #endif
  29.  
  30. #ifndef FWSTRMRW_H
  31. #include "FWStrmRW.h"
  32. #endif
  33.  
  34. #ifndef FWCOLOR_H
  35. #include "FWColor.h"
  36. #endif
  37.  
  38. //----------------------------------------------------------------------------------------
  39. //    Local helper functions
  40. //----------------------------------------------------------------------------------------
  41.  
  42. static DWORD RoundToDWord(DWORD number)
  43. {
  44.     return ((number + 31) & (~31)) / 8;
  45. }
  46.  
  47. //----------------------------------------------------------------------------------------
  48. //    FW_CPrivWinDIB::ConvertToBitmap
  49. //----------------------------------------------------------------------------------------
  50.  
  51. HBITMAP FW_CPrivWinDIB::ConvertToBitmap(HDIB dib, HPALETTE hPal)
  52. {
  53.     // we will use the screen device as the source for color depth information
  54.     HDC dc = ::GetDC(NULL);
  55.     
  56.     // select the palette, if any
  57.     HPALETTE hPalOld = NULL;
  58.     if (hPal != NULL)
  59.     {
  60.         hPalOld = ::SelectPalette(dc, hPal, FALSE);
  61.         ::RealizePalette(dc);
  62.     }
  63.  
  64.     // lock DIB bits
  65.     FW_CAcquireLockedSystemHandle lock(dib);
  66.     const BITMAPINFO* biPtr = (BITMAPINFO*)lock.GetPointer();
  67.     const BITMAPINFOHEADER* bmiHeader = &biPtr->bmiHeader;
  68.  
  69.     // determine bitmap dimensions
  70.     short width, height;
  71.     if(bmiHeader->biSize == sizeof(BITMAPCOREHEADER))
  72.     {
  73.         // this is an OS/2 bitmap
  74.         const BITMAPCOREHEADER* bcHeader = (const BITMAPCOREHEADER*) bmiHeader;
  75.         width = bcHeader->bcWidth;
  76.         height = bcHeader->bcHeight;
  77.     }
  78.     else
  79.     {
  80.         width = bmiHeader->biWidth;
  81.         height = bmiHeader->biHeight;
  82.     }
  83.  
  84.     // get the pixel buffer and perform the conversion
  85.     PixelBufferPtr pixelBuffer  = GetPixelBuffer(biPtr);
  86.     HBITMAP bitmapHandle  = ::CreateDIBitmap(dc, bmiHeader, CBM_INIT, pixelBuffer, biPtr, DIB_RGB_COLORS);
  87.  
  88.     // clean up
  89.     if (hPalOld != NULL)
  90.         ::SelectPalette(dc, hPalOld, TRUE);
  91.  
  92.     ::ReleaseDC(NULL, dc);
  93.     
  94.     // check errors and return
  95.     if(bitmapHandle == 0)
  96.         FW_Failure(FW_xMemoryExhausted);
  97.  
  98.     return bitmapHandle;
  99. }
  100.  
  101. //----------------------------------------------------------------------------------------
  102. // FW_CPrivWinDIB::ConvertFromBitmap
  103. //----------------------------------------------------------------------------------------
  104.  
  105. FW_CPrivWinDIB::HDIB FW_CPrivWinDIB::ConvertFromBitmap(
  106.         HBITMAP        bitmapHandle,
  107.         short        bitDepth    /* = 0 */,
  108.         HPALETTE    hPal         /* = NULL */)
  109. {
  110.     BITMAPINFOHEADER bmiHeader;
  111.  
  112.     // get information about the DDB
  113.     BITMAP bitmapInfo;
  114.     ::GetObject(bitmapHandle, sizeof(bitmapInfo), &bitmapInfo);
  115.     
  116.     // Determine bit depth
  117.     if(bitDepth == 0)
  118.         bitDepth = bitmapInfo.bmPlanes * bitmapInfo.bmBitsPixel;
  119.         
  120.     FW_ASSERT(bitDepth == 1 || bitDepth == 4 || bitDepth == 8 || bitDepth == 16 || bitDepth == 24);
  121.     
  122.     // Initilaize the header
  123.     PrivInitHeader(bmiHeader, bitmapInfo.bmWidth, bitmapInfo.bmHeight, bitDepth);
  124.  
  125.     // allocate memory for the header and the palette
  126.     unsigned long paletteSize = GetPaletteSize(&bmiHeader);
  127.     unsigned long memSize = bmiHeader.biSize + paletteSize;
  128.     FW_CAcquireTemporarySystemHandle dibMemory(memSize);
  129.     BITMAPINFO* biPtr = (BITMAPINFO*)dibMemory.GetPointer();
  130.     
  131.     // stick the header in
  132.     biPtr->bmiHeader = bmiHeader;
  133.  
  134.     // get image size from the video driver, by calling GetDIBits with NULL
  135.     // parameter for the storage
  136.     HDC hdc = ::GetDC(NULL);
  137.     HPALETTE hPalOld = NULL;
  138.     if (hPal != NULL)
  139.     {
  140.         hPalOld = ::SelectPalette(hdc, hPal, FALSE);
  141.         ::RealizePalette(hdc);
  142.     }
  143.  
  144.     ::GetDIBits(hdc, bitmapHandle, 0, bmiHeader.biHeight, NULL, biPtr, DIB_RGB_COLORS);
  145.  
  146.     bmiHeader = biPtr->bmiHeader;
  147.  
  148.     // for RGB bitmaps, it is valid for biSizeImage to be 0,
  149.     // so we need to calculate it outselves
  150.     if (bmiHeader.biSizeImage == 0)
  151.     {
  152.         bmiHeader.biSizeImage = RoundToDWord(bitmapInfo.bmWidth *
  153.             bitmapInfo.bmPlanes * bitmapInfo.bmBitsPixel) * bitmapInfo.bmHeight;
  154.     }
  155.  
  156.     // reallocate the buffer to hold the bits
  157.     memSize = bmiHeader.biSize + paletteSize + bmiHeader.biSizeImage;
  158.     FW_TRY
  159.     {
  160.         dibMemory.Resize(memSize);
  161.     }
  162.     FW_CATCH_BEGIN
  163.     FW_CATCH_EVERYTHING()
  164.     {
  165.         if (hPalOld != NULL)
  166.         {
  167.             ::SelectPalette(hdc, hPalOld, FALSE);
  168.             ::RealizePalette(hdc);
  169.         }
  170.  
  171.         ::ReleaseDC(NULL, hdc);
  172.         FW_THROW_SAME();
  173.     }
  174.     FW_CATCH_END
  175.  
  176.     biPtr = (BITMAPINFO*) dibMemory.GetPointer();
  177.     
  178.     // now get the bits by calling GetDIBits again, this time with a non-NULL pixel buffer
  179.     PixelBufferPtr pixelBuffer = GetPixelBuffer(biPtr);
  180.     ::GetDIBits(hdc, bitmapHandle, 0, bmiHeader.biHeight, pixelBuffer, biPtr, DIB_RGB_COLORS);
  181.  
  182.     // clean up and return the handle
  183.     if (hPalOld != NULL)
  184.     {
  185.         ::SelectPalette(hdc, hPalOld, FALSE);
  186.         ::RealizePalette(hdc);
  187.     }
  188.     ::ReleaseDC(NULL, hdc);
  189.     dibMemory.Orphan();
  190.     return (HDIB) dibMemory.GetPlatformHandle();
  191. }
  192.  
  193. //----------------------------------------------------------------------------------------
  194. //    FW_CPrivWinDIB::GetPalette
  195. //----------------------------------------------------------------------------------------
  196.  
  197. HPALETTE FW_CPrivWinDIB::GetPalette(HDIB dib)
  198. {
  199.     FW_CAcquireLockedSystemHandle lock(dib);
  200.     const BITMAPINFOHEADER* bmiHeader = (const BITMAPINFOHEADER*) lock.GetPointer();
  201.     
  202.     // It only makes sense to support palettes for 8-bit DIBs.
  203.     // For Windows, I also check ClrImportant and ClrUsed which
  204.     // both may be set in HiColor or TrueColor DIBs.
  205.     
  206.     // RGBQUAD and RGBTRIPLE both begin with 3 BYTE's that specify
  207.     // Blue, Green and Red components in that exact order
  208.  
  209.     // ----- Determine color count
  210.     short colorCount, colorStep;
  211.     LOGPALETTE* pLogPal = NULL;
  212.     BYTE* colorTable;
  213.  
  214.     if (bmiHeader->biSize == sizeof(BITMAPINFOHEADER))
  215.     {
  216.         // Windows DIB
  217.         colorCount = bmiHeader->biClrImportant;
  218.         
  219.         if (colorCount == 0)
  220.             colorCount = bmiHeader->biClrUsed;
  221.             
  222.         if (colorCount == 0)
  223.             colorCount = bmiHeader->biBitCount == 8 ? 256 : 0;
  224.             
  225.         colorStep = sizeof(RGBQUAD);
  226.         colorTable = (BYTE*) (bmiHeader + 1);
  227.     }
  228.     else
  229.     {
  230.         // OS/2 DIB
  231.         const BITMAPCOREHEADER* bcHeader = (const BITMAPCOREHEADER*) bmiHeader;
  232.         colorCount = bcHeader->bcBitCount == 8 ? 256 : 0;
  233.  
  234.         colorStep = sizeof(RGBTRIPLE);
  235.         colorTable = (BYTE*) (bcHeader + 1);
  236.     }
  237.  
  238.     // Create a palette
  239.     HPALETTE hPal = NULL;
  240.     if (colorCount != 0)
  241.     {
  242.         pLogPal = (LOGPALETTE*) new char[sizeof(LOGPALETTE) + colorCount * sizeof(PALETTEENTRY)];
  243.         pLogPal->palVersion = 0x300;
  244.         pLogPal->palNumEntries = colorCount;
  245.  
  246.         for (short i = 0; i < colorCount; ++ i, colorTable += colorStep)
  247.         {
  248.             pLogPal->palPalEntry[i].peBlue    = colorTable[0];
  249.             pLogPal->palPalEntry[i].peGreen    = colorTable[1];
  250.             pLogPal->palPalEntry[i].peRed    = colorTable[2];
  251.             pLogPal->palPalEntry[i].peFlags    = 0;
  252.         }
  253.     
  254.         hPal = ::CreatePalette(pLogPal);
  255.         
  256.         delete[] (char*) pLogPal;
  257.     }
  258.  
  259.     return hPal;
  260. }
  261.  
  262. //----------------------------------------------------------------------------------------
  263. //    FW_CPrivWinDIB::GetPaletteSize
  264. //----------------------------------------------------------------------------------------
  265.  
  266. unsigned long FW_CPrivWinDIB::GetPaletteSize(const BITMAPINFOHEADER* bmiHeader)
  267. {
  268.     short bits;                // bitmap depth, in bits
  269.     short numColors = 0;    // number of colors
  270.     short colorEntrySize;    // size of each color entry in the palette
  271.     
  272.     if(bmiHeader->biSize == sizeof(BITMAPCOREHEADER))
  273.     {
  274.         // OS/2 bitmap header
  275.         const BITMAPCOREHEADER* bcHeader = (const BITMAPCOREHEADER*) bmiHeader;
  276.         bits = bcHeader->bcBitCount;
  277.         colorEntrySize = sizeof(RGBTRIPLE);
  278.     }
  279.     else
  280.     {
  281.         numColors = bmiHeader->biClrUsed;
  282.         bits = bmiHeader->biBitCount;
  283.         colorEntrySize = sizeof(RGBQUAD);
  284.     }
  285.     
  286.     if(numColors == 0)
  287.     {
  288.         switch(bits)
  289.         {
  290.             case 1:
  291.                 numColors = 2;
  292.                 break;
  293.             case 4:
  294.                 numColors = 16;
  295.                 break;
  296.             case 8:
  297.                 numColors = 256;
  298.                 break;
  299.             default:
  300.                 numColors = 0;
  301.                 break;
  302.         }
  303.     }
  304.     
  305.     return colorEntrySize * numColors;
  306. }
  307.  
  308. //----------------------------------------------------------------------------------------
  309. //    FW_CPrivWinDIB::GetPixelBuffer
  310. //----------------------------------------------------------------------------------------
  311.  
  312. FW_CPrivWinDIB::PixelBufferPtr FW_CPrivWinDIB::GetPixelBuffer(const BITMAPINFO* biPtr)
  313. {
  314.     const BITMAPINFOHEADER* bmiHeader = &biPtr->bmiHeader;
  315.     unsigned long paletteSize = GetPaletteSize(bmiHeader);
  316.     
  317.     return (PixelBufferPtr) biPtr + paletteSize + bmiHeader->biSize;
  318. }
  319.  
  320. //----------------------------------------------------------------------------------------
  321. // FW_CPrivWinDIB::LoadFromStream
  322. //----------------------------------------------------------------------------------------
  323.  
  324. FW_CPrivWinDIB::HDIB FW_CPrivWinDIB::LoadFromStream(const FW_CReadableStream& stream, FW_Boolean bFileHeader)
  325. {
  326.     // read the header first
  327.     if (bFileHeader)
  328.     {
  329.         BITMAPFILEHEADER bmfh;
  330.         stream.Read((void*) &bmfh, sizeof(bmfh));
  331.     
  332.         // verify the header
  333.         if(bmfh.bfType != kWinBitmapFileSignature || bmfh.bfSize == 0)
  334.             FW_Failure(FW_xInvalidBitmapData);
  335.     }
  336.     
  337.     // Start reading the DIB header
  338.     FW_Boolean bIsWindowsBitmap;
  339.  
  340.     BITMAPINFOHEADER bmih;
  341.     BITMAPCOREHEADER bmch;
  342.     
  343.     int bitDepth;
  344.     int colorCount;
  345.     int width, height;
  346.     int headerSize;
  347.     int paletteSize;
  348.     
  349.     stream.Read((void*) &bmih.biSize, sizeof(bmih.biSize));
  350.     
  351.     if(bmih.biSize == sizeof(BITMAPINFOHEADER))                // Windows bitmap
  352.     {
  353.         stream.Read((void*) &bmih.biWidth, sizeof(bmih) - sizeof(bmih.biSize));
  354.         bIsWindowsBitmap = TRUE;
  355.  
  356.         width        = bmih.biWidth;
  357.         height        = bmih.biHeight;
  358.         headerSize    = sizeof(bmih);
  359.     }
  360.     else if(bmih.biSize == sizeof(BITMAPCOREHEADER))        // OS/2 bitmap
  361.     {
  362.         bmch.bcSize = bmih.biSize;
  363.         stream.Read((void* )&bmch.bcWidth, sizeof(bmch) - sizeof(bmch.bcSize));
  364.         bIsWindowsBitmap = FALSE;
  365.         
  366.         width        = bmch.bcWidth;
  367.         height        = bmch.bcHeight;
  368.         headerSize    = sizeof(bmch);
  369.     }
  370.     else
  371.         FW_Failure(FW_xInvalidBitmapData);
  372.         
  373.     PrivGetColorInfo(bmih, bitDepth, colorCount, paletteSize);
  374.         
  375.     // Determine the image size
  376.     short rowBytes = ((width * bitDepth + 31) & ~31) / 8;
  377.     long bitsSize = height * rowBytes;
  378.  
  379.     // allocate memory for the DIB
  380.     FW_CAcquireTemporarySystemHandle dibMemory(headerSize + paletteSize + bitsSize);
  381.     BITMAPINFOHEADER* biPtr = (BITMAPINFOHEADER*) dibMemory.GetPointer();
  382.     BITMAPCOREHEADER* bcPtr = (BITMAPCOREHEADER*) dibMemory.GetPointer();
  383.  
  384.     // Stick the header in
  385.     void* palettePtr;
  386.     if(bIsWindowsBitmap)
  387.     {
  388.         *biPtr = bmih;
  389.         palettePtr = biPtr + 1;
  390.     }
  391.     else
  392.     {
  393.         *bcPtr = bmch;
  394.         palettePtr = bcPtr + 1;
  395.     }
  396.     
  397.     // Read the palette
  398.     if(paletteSize != 0)
  399.         stream.Read(palettePtr, paletteSize);
  400.  
  401.     // Read the bits
  402.     void* bitsPtr = (char*) palettePtr + paletteSize;
  403.     stream.Read(bitsPtr, bitsSize);
  404.  
  405.     // Clean up and return
  406.     dibMemory.Orphan();
  407.     return (HDIB) dibMemory.GetPlatformHandle();
  408. }
  409.  
  410. //----------------------------------------------------------------------------------------
  411. // FW_CPrivWinDIB::SaveToStream
  412. //----------------------------------------------------------------------------------------
  413.  
  414. void FW_CPrivWinDIB::SaveToStream(const FW_CWritableStream& stream, HDIB dib, FW_Boolean bFileHeader)
  415. {
  416.     // lock DIB bits
  417.     FW_CAcquireLockedSystemHandle lock(dib);
  418.     BITMAPINFO* biPtr = (BITMAPINFO*) lock.GetPointer();
  419.     BITMAPINFOHEADER* bmiHeader = &biPtr->bmiHeader;
  420.     
  421.     unsigned long headerSize;
  422.     unsigned long imageSize;
  423.  
  424.     if(bmiHeader->biSize == sizeof(BITMAPCOREHEADER))
  425.     {
  426.         // this is an OS/2 bitmap
  427.         const BITMAPCOREHEADER* bcHeader = (const BITMAPCOREHEADER*) bmiHeader;
  428.         headerSize = bcHeader->bcSize;
  429.         imageSize = RoundToDWord(bcHeader->bcWidth *
  430.             bcHeader->bcPlanes * bcHeader->bcBitCount) * bcHeader->bcHeight;
  431.     }
  432.     else
  433.     {
  434.         // this is a Windows bitmap
  435.         headerSize = bmiHeader->biSize;
  436.         imageSize = bmiHeader->biSizeImage;
  437.     }
  438.  
  439.     // calculate file size and image offset
  440.     unsigned long paletteSize = GetPaletteSize(bmiHeader);
  441.     unsigned long fullSize = paletteSize + headerSize + imageSize;
  442.  
  443.     // Write the file header
  444.     if(bFileHeader)
  445.     {
  446.         BITMAPFILEHEADER bmfh;
  447.         bmfh.bfType            = kWinBitmapFileSignature;
  448.         bmfh.bfSize            = fullSize + sizeof(BITMAPFILEHEADER);
  449.         bmfh.bfReserved1    = 0;
  450.         bmfh.bfReserved2    = 0;
  451.         bmfh.bfOffBits        = paletteSize + headerSize + sizeof(BITMAPFILEHEADER);
  452.  
  453.         stream.Write((void*) &bmfh, sizeof(BITMAPFILEHEADER));
  454.     }
  455.     
  456.     // Write the bits
  457.     stream.Write((void*) biPtr, fullSize);
  458. }
  459.  
  460. //----------------------------------------------------------------------------------------
  461. // FW_CPrivWinDIB::Free
  462. //----------------------------------------------------------------------------------------
  463.  
  464. void FW_CPrivWinDIB::Free(HDIB dib)
  465. {
  466.     FW_CMemoryManager::FreeSystemHandle(dib);
  467. }
  468.  
  469. //----------------------------------------------------------------------------------------
  470. // FW_CPrivWinDIB::CreateDIB
  471. //----------------------------------------------------------------------------------------
  472.  
  473. FW_CPrivWinDIB::HDIB FW_CPrivWinDIB::CreateDIB(short bitDepth, short width, short height,
  474.                             short nbColors, const FW_CColor* colorTable,
  475.                             const void* pixels /* = NULL */)
  476. {
  477.     FW_ASSERT(bitDepth == 1 || bitDepth == 4 || bitDepth == 8);
  478.  
  479.     // Calculate the sizes
  480.     unsigned short colorCount = 1 << bitDepth;
  481.     unsigned long paletteSize = colorCount * sizeof(RGBQUAD);
  482.     unsigned long imageSize = RoundToDWord(width * bitDepth) * height;
  483.     unsigned long size = sizeof(BITMAPINFOHEADER) + paletteSize + imageSize;
  484.  
  485.     FW_ASSERT(nbColors <= colorCount);
  486.     
  487.     // Allocate DIB memory
  488.     FW_CAcquireTemporarySystemHandle dibMemory(size);
  489.     BITMAPINFO* biPtr = (BITMAPINFO*)dibMemory.GetPointer();
  490.  
  491.     // Initiliaze the header
  492.     PrivInitHeader(biPtr->bmiHeader, width, height, bitDepth);
  493.     biPtr->bmiHeader.biClrImportant = nbColors;
  494.  
  495.     // Copy the color table
  496.     for(int i = 0; i < nbColors; i ++)
  497.         biPtr->bmiColors[i] = colorTable[i];
  498.  
  499.     if(nbColors != colorCount)
  500.         ::memset(biPtr->bmiColors + nbColors, 0, sizeof(RGBQUAD) * (colorCount - nbColors));
  501.         
  502.     // Copy the bits
  503.     if(pixels != NULL)
  504.     {
  505.         PixelBufferPtr pixelBuffer = GetPixelBuffer(biPtr);
  506.         FW_CMemoryManager::CopyMemory(pixels, pixelBuffer, imageSize);
  507.     }
  508.  
  509.     dibMemory.Orphan();
  510.     return (HDIB) dibMemory.GetPlatformHandle();
  511. }
  512.  
  513.  
  514. //----------------------------------------------------------------------------------------
  515. // FW_CPrivWinDIB::CreateCopy
  516. //----------------------------------------------------------------------------------------
  517.  
  518. FW_CPrivWinDIB::HDIB FW_CPrivWinDIB::CreateCopy(HDIB dib)
  519. {
  520.     FW_ASSERT(dib != NULL);
  521.     return (HDIB) FW_CMemoryManager::CopySystemHandle(dib);
  522. }
  523.  
  524. //----------------------------------------------------------------------------------------
  525. // FW_CPrivWinDIB::GetColorTable
  526. //----------------------------------------------------------------------------------------
  527.                         
  528. unsigned short FW_CPrivWinDIB::GetColorTable(HDIB dib, FW_CColor*& colors)
  529. {
  530.     colors = NULL;
  531.     
  532.     FW_CAcquireLockedSystemHandle lock(dib);
  533.     const BITMAPINFO* bmi = (const BITMAPINFO*) lock.GetPointer();
  534.     
  535.     int i, bitDepth, colorCount, paletteSize;
  536.     PrivGetColorInfo(bmi->bmiHeader, bitDepth, colorCount, paletteSize);
  537.  
  538.     if(bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  539.     {
  540.         // this is an OS/2 bitmap
  541.         const BITMAPCOREINFO* bmci = (const BITMAPCOREINFO*) bmi;
  542.         if(colorCount != 0)
  543.         {
  544.             colors = new FW_CColor[colorCount];
  545.             for(i = 0; i < colorCount; i ++)
  546.                 colors[i] = bmci->bmciColors[i];
  547.         }
  548.     }
  549.     else
  550.     {
  551.         // this is a Windows bitmap
  552.         if(bmi->bmiHeader.biClrImportant != 0)
  553.             colorCount = bmi->bmiHeader.biClrImportant;
  554.  
  555.         if(colorCount != 0)
  556.         {
  557.             colors = new FW_CColor[colorCount];
  558.             for(i = 0; i < colorCount; i ++)
  559.                 colors[i] = bmi->bmiColors[i];
  560.         }
  561.     }
  562.  
  563.     return colorCount;
  564. }
  565.  
  566. //----------------------------------------------------------------------------------------
  567. // FW_CPrivWinDIB::PrivInitHeader
  568. //----------------------------------------------------------------------------------------
  569.                         
  570. void FW_CPrivWinDIB::PrivInitHeader(BITMAPINFOHEADER& header, int width, int height, int bitDepth)
  571. {
  572.     header.biSize = sizeof(BITMAPINFOHEADER);
  573.     header.biWidth = width;
  574.     header.biHeight = height;
  575.     header.biPlanes = 1;
  576.     header.biBitCount = bitDepth;
  577.     header.biCompression = BI_RGB;
  578.     header.biSizeImage = 0;
  579.     header.biXPelsPerMeter = 0;
  580.     header.biYPelsPerMeter = 0;
  581.     header.biClrUsed = 0;
  582.     header.biClrImportant = 0;
  583. }
  584.  
  585. //----------------------------------------------------------------------------------------
  586. // FW_CPrivWinDIB::PrivGetColorInfo
  587. //----------------------------------------------------------------------------------------
  588.  
  589. void FW_CPrivWinDIB::PrivGetColorInfo(
  590.     const BITMAPINFOHEADER& biHeader,
  591.     int& bitDepth,        
  592.     int& colorCount,
  593.     int& paletteSize)
  594. {
  595.     if(biHeader.biSize == sizeof(BITMAPINFOHEADER))
  596.     {
  597.         bitDepth    = biHeader.biBitCount;
  598.         colorCount    = biHeader.biClrUsed != 0  ? biHeader.biClrUsed :
  599.                         biHeader.biBitCount == 24 ? 0 : 1 << biHeader.biBitCount;
  600.         paletteSize    = colorCount * sizeof(RGBQUAD);
  601.     }
  602.     else
  603.     {
  604.         const BITMAPCOREHEADER& bcHeader = (const BITMAPCOREHEADER&) biHeader;
  605.         bitDepth    = bcHeader.bcBitCount;
  606.         colorCount    = bcHeader.bcBitCount == 24 ? 0 : 1 << bcHeader.bcBitCount;
  607.         paletteSize    = colorCount * sizeof(RGBTRIPLE);
  608.     }
  609. }
  610.  
  611. //========================================================================================
  612. // class FW_CPrivWinBitmap
  613. //========================================================================================
  614.  
  615. //----------------------------------------------------------------------------------------
  616. // FW_CPrivWinBitmap::GetColorDepth
  617. //----------------------------------------------------------------------------------------
  618.                         
  619. short FW_CPrivWinBitmap::GetColorDepth(HBITMAP hBitmap)
  620. {
  621.     BITMAP bm;
  622.     ::GetObject(hBitmap, sizeof(bm), &bm);
  623.  
  624.     if(bm.bmPlanes != 1)
  625.         return bm.bmPlanes;
  626.         
  627.     return bm.bmBitsPixel;
  628. }
  629.  
  630. //----------------------------------------------------------------------------------------
  631. // FW_CPrivWinBitmap::CopyImage
  632. //----------------------------------------------------------------------------------------
  633.                         
  634. void FW_CPrivWinBitmap::CopyImage(
  635.         HBITMAP hBmpDst, HPALETTE hPalDst, const RECT& rectDst,
  636.         HBITMAP hBmpSrc, HPALETTE hPalSrc, const RECT& rectSrc,
  637.         short options)
  638. {
  639.     FW_ASSERT(hBmpSrc != NULL);
  640.     FW_ASSERT(hBmpDst != NULL);
  641.     
  642.     HDC hDCDst = ::CreateCompatibleDC(NULL);
  643.     HDC hDCSrc = ::CreateCompatibleDC(NULL);
  644.     
  645.     if(hDCDst != NULL && hDCSrc != NULL)
  646.     {
  647.         HBITMAP hBmpDstOld = (HBITMAP) ::SelectObject(hDCDst, hBmpDst);
  648.         HBITMAP hBmpSrcOld = (HBITMAP) ::SelectObject(hDCSrc, hBmpSrc);
  649.         
  650.         if(hBmpDstOld != NULL && hBmpSrcOld != NULL)
  651.         {
  652.             // Select the palettes
  653.             HPALETTE hPalOldDst = NULL;
  654.             if (hPalDst != NULL)
  655.             {
  656.                 hPalOldDst = ::SelectPalette(hDCDst, hPalDst, FALSE);
  657.                 ::RealizePalette(hDCDst);
  658.             }
  659.         
  660.             HPALETTE hPalOldSrc = NULL;
  661.             if (hPalSrc != NULL)
  662.             {
  663.                 hPalOldSrc = ::SelectPalette(hDCSrc, hPalSrc, FALSE);
  664.                 ::RealizePalette(hDCSrc);
  665.             }
  666.  
  667.             if(options == kScale)
  668.             {
  669.                 // Stretch the bits
  670.                 ::StretchBlt(
  671.                     hDCDst,
  672.                         rectDst.left, rectDst.top,
  673.                         rectDst.right - rectDst.left, rectDst.bottom - rectDst.top,
  674.                     hDCSrc,
  675.                         rectSrc.left, rectSrc.top,
  676.                         rectSrc.right - rectSrc.left, rectSrc.bottom - rectSrc.top,
  677.                     SRCCOPY);
  678.             }
  679.             else
  680.             {
  681.                 // Determine the size of image we can copy
  682.                 short copyWidth = rectSrc.right - rectSrc.left;
  683.                 if(copyWidth > rectDst.right - rectDst.left)
  684.                     copyWidth = rectDst.right - rectDst.left;
  685.  
  686.                 short copyHeight = rectSrc.bottom - rectSrc.top;
  687.                 if(copyHeight > rectDst.bottom - rectDst.top)
  688.                     copyHeight = rectDst.bottom - rectDst.top;
  689.                 
  690.                 // Copy the bits
  691.                 ::BitBlt(
  692.                     hDCDst,
  693.                         rectDst.left, rectDst.top,
  694.                         copyWidth, copyHeight,
  695.                     hDCSrc,
  696.                         rectSrc.left, rectSrc.top,
  697.                     SRCCOPY);
  698.                 
  699.                 // Erase any space to the right of the copied image piece
  700.                 if(copyWidth < rectDst.right - rectDst.left)
  701.                     ::PatBlt(
  702.                         hDCDst,
  703.                             rectDst.left + copyWidth,
  704.                             rectDst.top,
  705.                             rectDst.right - rectDst.left - copyWidth,
  706.                             rectDst.bottom - rectDst.top,
  707.                             WHITENESS);
  708.                 
  709.                 // Erase any space to the bottom of the copied image piece
  710.                 if(copyHeight < rectDst.bottom - rectDst.top)
  711.                     ::PatBlt(
  712.                         hDCDst,
  713.                             rectDst.left,
  714.                             rectDst.top + copyHeight,
  715.                             rectDst.right - rectDst.left,
  716.                             rectDst.bottom - rectDst.top - copyHeight,
  717.                             WHITENESS);
  718.             }
  719.             
  720.             // Clean up the palettes
  721.             if (hPalOldDst != NULL)
  722.                 ::SelectPalette(hDCDst, hPalOldDst, FALSE);
  723.  
  724.             if (hPalOldSrc != NULL)
  725.                 ::SelectPalette(hDCSrc, hPalOldSrc, FALSE);
  726.         }
  727.  
  728.         if(hBmpDstOld != NULL)
  729.             ::SelectObject(hDCDst, hBmpDstOld);
  730.             
  731.         if(hBmpSrcOld != NULL)
  732.             ::SelectObject(hDCSrc, hBmpSrcOld);
  733.     }
  734.     
  735.     if(hDCDst != NULL)
  736.         ::DeleteDC(hDCDst);
  737.  
  738.     if(hDCSrc != NULL)
  739.         ::DeleteDC(hDCSrc);
  740. }
  741.  
  742. #endif
  743.