1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213 |
- #include "stdafx.h"
- #include "DIBSectionLite.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // Standard colours
- PALETTEENTRY CDIBSectionLite::ms_StdColours[] = {
- { 0x00, 0x00, 0x00, 0 }, // First 2 will be palette for monochrome bitmaps
- { 0xFF, 0xFF, 0xFF, 0 },
- { 0x00, 0x00, 0xFF, 0 }, // First 16 will be palette for 16 colour bitmaps
- { 0x00, 0xFF, 0x00, 0 },
- { 0x00, 0xFF, 0xFF, 0 },
- { 0xFF, 0x00, 0x00, 0 },
- { 0xFF, 0x00, 0xFF, 0 },
- { 0xFF, 0xFF, 0x00, 0 },
- { 0x00, 0x00, 0x80, 0 },
- { 0x00, 0x80, 0x00, 0 },
- { 0x00, 0x80, 0x80, 0 },
- { 0x80, 0x00, 0x00, 0 },
- { 0x80, 0x00, 0x80, 0 },
- { 0x80, 0x80, 0x00, 0 },
- { 0x80, 0x80, 0x80, 0 },
- { 0xC0, 0xC0, 0xC0, 0 },
- };
- /////////////////////////////////////////////////////////////////////////////
- // CDIBSectionLite static functions
- // --- In?: nBitsPerPixel - bits per pixel
- // --- Out :
- // --- Returns :The number of colours for this colour depth
- // --- Effect : Returns the number of color table entries given the number
- // of bits per pixel of a bitmap
- int CDIBSectionLite::NumColorEntries(int nBitsPerPixel)
- {
- int nColors = 0;
- switch (nBitsPerPixel)
- {
- case 1: nColors = 2; break;
- case 4: nColors = 16; break;
- case 8: nColors = 256; break;
- case 16:
- case 24:
- case 32: nColors = 0; break; // 16,24 or 32 bpp have no color table
- default:
- ASSERT(FALSE);
- }
- return nColors;
- }
- // --- In?: nWidth - image width in pixels
- // nBitsPerPixel - bits per pixel
- // --- Out :
- // --- Returns : Returns the number of storage bytes needed for each scanline
- // in the bitmap
- // --- Effect :
- int CDIBSectionLite::BytesPerLine(int nWidth, int nBitsPerPixel)
- {
- int nBytesPerLine = nWidth * nBitsPerPixel;
- nBytesPerLine = ( (nBytesPerLine + 31) & (~31) ) / 8;
- return nBytesPerLine;
- }
- // --- In?: palette - reference to a palette object which will be filled
- // nNumColours - number of colour entries to fill
- // --- Out :
- // --- Returns : TRUE on success, false otherwise
- // --- Effect : Creates a halftone color palette independant of screen color depth.
- // palette will be filled with the colors, and nNumColours is the No.
- // of colors to file. If nNumColoursis 0 or > 256, then 256 colors are used.
- BOOL CDIBSectionLite::CreateHalftonePalette(CPalette& palette, int nNumColours)
- {
- palette.DeleteObject();
- int nNumStandardColours = sizeof(ms_StdColours) / sizeof(ms_StdColours[0]);
- int nIndex = 0;
- int nNumEntries = nNumColours;
- if (nNumEntries <= 0 || nNumEntries > 256)
- nNumEntries = 256;
- PALETTEINFO PalInfo;
- PalInfo.palNumEntries = (WORD) nNumEntries;
- // The standard colours (16)
- for (int i = 0; i < nNumStandardColours; i++)
- {
- if (nIndex >= nNumEntries) break;
- memcpy( &(PalInfo.palPalEntry[nIndex]), &(ms_StdColours[i]), sizeof(PALETTEENTRY) );
- nIndex++;
- }
- // A colour cube (6 divisions = 216)
- for (int blue = 0; blue <= 5; blue++)
- for (int green = 0; green <= 5; green++)
- for (int red = 0; red <= 5; red++)
- {
- if (nIndex >= nNumEntries)
- break;
- PalInfo.palPalEntry[nIndex].peRed = (BYTE) ((red*255)/5);
- PalInfo.palPalEntry[nIndex].peGreen = (BYTE) ((green*255)/5);
- PalInfo.palPalEntry[nIndex].peBlue = (BYTE) ((blue*255)/5);
- PalInfo.palPalEntry[nIndex].peFlags = 0;
- nIndex++;
- }
- // A grey scale (24 divisions)
- for (int grey = 0; grey <= 23; grey++)
- {
- if (nIndex >= nNumEntries)
- break;
- PalInfo.palPalEntry[nIndex].peRed = (BYTE) (grey*255/23);
- PalInfo.palPalEntry[nIndex].peGreen = (BYTE) (grey*255/23);
- PalInfo.palPalEntry[nIndex].peBlue = (BYTE) (grey*255/23);
- PalInfo.palPalEntry[nIndex].peFlags = 0;
- nIndex++;
- }
- return palette.CreatePalette((LPLOGPALETTE) PalInfo);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CDIBSectionLite
- CDIBSectionLite::CDIBSectionLite()
- {
- m_hBitmap = NULL;
- m_bDither = FALSE;
- m_hDrawDib = NULL;
- m_ppvBits = NULL;
- m_pdwBits = NULL;
- DeleteObject(); // This will initialise to a known state - ie. empty
- }
- CDIBSectionLite::~CDIBSectionLite()
- {
- DeleteObject();
- }
- // --- In?:
- // --- Out :
- // --- Returns :
- // --- Effect : Resets the object to an empty state, and frees all memory used.
- void CDIBSectionLite::DeleteObject()
- {
- if (m_hBitmap)
- {
- ::DeleteObject(m_hBitmap);
- m_hBitmap = NULL;
- }
- if ( m_pdwBits)
- {
- delete []m_pdwBits;
- m_pdwBits = NULL;
- }
-
- m_ppvBits = NULL;
- memset(&m_DIBinfo, 0, sizeof(m_DIBinfo));
- if (m_hDrawDib)
- {
- DrawDibClose(m_hDrawDib);
- m_hDrawDib = NULL;
- }
- m_iColorDataType = DIB_RGB_COLORS;
- m_iColorTableSize = 0;
- }
- void CDIBSectionLite::ClearObject()
- {
- //#if 0
- // if (m_hBitmap)
- // ::DeleteObject(m_hBitmap);
- // m_hBitmap = NULL;
- // m_ppvBits = NULL;
- //
- // memset(&m_DIBinfo, 0, sizeof(m_DIBinfo));
- //
- // if (m_hDrawDib)
- // DrawDibClose(m_hDrawDib);
- // m_hDrawDib = NULL;
- //#endif
- if ( m_hBitmap != NULL )
- {
- ::DeleteObject(m_hBitmap);
- m_hBitmap = NULL;
- }
- #if 0
- if ( m_ppvBits != NULL )
- {
- DWORD *dwAry = (DWORD*)m_ppvBits;
- delete []dwAry;
- m_ppvBits = NULL;
- }
- #else
- m_ppvBits = NULL;
- #endif
- memset(&m_DIBinfo, 0, sizeof(m_DIBinfo));
- if (m_hDrawDib)
- {
- DrawDibClose(m_hDrawDib);
- m_hDrawDib = NULL;
- }
- m_iColorDataType = DIB_RGB_COLORS;
- m_iColorTableSize = 0;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CDIBSectionLite diagnostics
- #ifdef _DEBUG
- void CDIBSectionLite::AssertValid() const
- {
- ASSERT(m_hBitmap);
- DIBSECTION ds;
- DWORD dwSize = GetObject( m_hBitmap, sizeof(DIBSECTION), &ds );
- ASSERT(dwSize == sizeof(DIBSECTION));
- ASSERT(0 <= m_iColorTableSize && m_iColorTableSize <= 256);
- CObject::AssertValid();
- }
- void CDIBSectionLite::Dump(CDumpContext& dc) const
- {
- CObject::Dump(dc);
- }
- #endif //_DEBUG
- // --- In?: bDither - whether or not dithering should be enabled
- // --- Out :
- // --- Returns : TRUE on success
- // --- Effect : Turns dithering on by using the DrawDib functions instead of
- // the GDI functions
- BOOL CDIBSectionLite::SetDither(BOOL bDither)
- {
- BOOL bResult = TRUE;
- // Check for a no-change op.
- if ( (m_bDither == bDither) &&
- ((m_hDrawDib && bDither) || (!m_hDrawDib && !bDither)) )
- return bResult;
- if (m_hDrawDib != NULL)
- {
- DrawDibClose(m_hDrawDib);
- m_hDrawDib = NULL;
- }
- if (bDither)
- {
- if ( (m_hDrawDib = DrawDibOpen()) == NULL )
- bResult = FALSE;
- }
- m_bDither = (m_hDrawDib != NULL);
- return bResult;
- }
- // --- In?:
- // --- Out :
- // --- Returns : TRUE if dithering is used
- // --- Effect : Returns whether or not the DrawDib functions (and hence dithering)
- // is being used.
- BOOL CDIBSectionLite::GetDither()
- {
- return (m_bDither && (m_hDrawDib != NULL));
- }
- /////////////////////////////////////////////////////////////////////////////
- // CDIBSectionLite operations
- // --- In?: pDC - Pointer to a device context
- // ptDest - point at which the topleft corner of the image is drawn
- // bForceBackground - Specifies whether the palette is forced to be
- // a background palette
- // --- Out :
- // --- Returns : TRUE on success
- // --- Effect : Draws the image 1:1 on the device context
- BOOL CDIBSectionLite::Draw(CDC* pDC, CPoint ptDest, BOOL bForceBackground )
- {
- if (!m_hBitmap)
- return FALSE;
- CSize size = GetSize();
- CPoint SrcOrigin = CPoint(0,0);
- BOOL bResult = FALSE;
- if (GetDither() && GetBitCount() >= 8)
- {
- DrawDibSetPalette( m_hDrawDib, (HPALETTE)m_Palette);
- DrawDibRealize( m_hDrawDib, pDC->GetSafeHdc(), bForceBackground);
- bResult = DrawDibDraw(m_hDrawDib, pDC->GetSafeHdc(),
- ptDest.x, ptDest.y, size.cx, size.cy,
- GetBitmapInfoHeader(), GetDIBits(),
- SrcOrigin.x, SrcOrigin.y, size.cx, size.cy,
- 0/*DDF_HALFTONE*/);
- }
- else
- {
- CPalette* pOldPalette = NULL;
- if (m_Palette.m_hObject && UsesPalette(pDC))
- {
- pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground);
- pDC->RealizePalette();
- }
- bResult = SetDIBitsToDevice(pDC->GetSafeHdc(),
- ptDest.x, ptDest.y,
- size.cx, size.cy,
- SrcOrigin.x, SrcOrigin.y,
- SrcOrigin.y, size.cy - SrcOrigin.y,
- GetDIBits(), GetBitmapInfo(),
- m_iColorDataType);
- if (pOldPalette)
- pDC->SelectPalette(pOldPalette, FALSE);
- }
- return bResult;
- }
- // --- In?: pDC - Pointer to a device context
- // ptDest - point at which the topleft corner of the image is drawn
- // size - size to stretch the image
- // bForceBackground - Specifies whether the palette is forced to be
- // a background palette
- // --- Out :
- // --- Returns : TRUE on success
- // --- Effect : Stretch draws the image to the desired size on the device context
- BOOL CDIBSectionLite::Stretch(CDC* pDC, CPoint ptDest, CSize size, BOOL bForceBackground )
- {
- if (!m_hBitmap)
- return FALSE;
- CSize imagesize = GetSize();
- CPoint SrcOrigin = CPoint(0,0);
- BOOL bResult = FALSE;
- if (GetDither() && GetBitCount() >= 8)
- {
- DrawDibSetPalette( m_hDrawDib, (HPALETTE)m_Palette);
- DrawDibRealize( m_hDrawDib, pDC->GetSafeHdc(), bForceBackground);
- bResult = DrawDibDraw(m_hDrawDib, pDC->GetSafeHdc(),
- ptDest.x, ptDest.y, size.cx, size.cy,
- GetBitmapInfoHeader(), GetDIBits(),
- SrcOrigin.x, SrcOrigin.y, imagesize.cx, imagesize.cy,
- 0/*DDF_HALFTONE*/);
- }
- else
- {
- CPalette* pOldPalette = NULL;
- if (m_Palette.m_hObject && UsesPalette(pDC))
- {
- pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground);
- pDC->RealizePalette();
- }
- pDC->SetStretchBltMode(COLORONCOLOR);
- bResult = StretchDIBits(pDC->GetSafeHdc(),
- ptDest.x, ptDest.y,
- size.cx, size.cy,
- SrcOrigin.x, SrcOrigin.y,
- imagesize.cx, imagesize.cy,
- GetDIBits(), GetBitmapInfo(),
- m_iColorDataType, SRCCOPY);
- if (pOldPalette)
- pDC->SelectPalette(pOldPalette, FALSE);
- }
- return bResult;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Setting the bitmap...
- // --- In?: nIDResource - resource ID
- // --- Out :
- // --- Returns : Returns TRUE on success, FALSE otherwise
- // --- Effect : Initialises the bitmap from a resource. If failure, then object is
- // initialised back to an empty bitmap.
- BOOL CDIBSectionLite::SetBitmap(UINT nIDResource)
- {
- return SetBitmap(MAKEINTRESOURCE(nIDResource));
- }
- // --- In?: lpszResourceName - resource name
- // --- Out :
- // --- Returns : Returns TRUE on success, FALSE otherwise
- // --- Effect : Initialises the bitmap from a resource. If failure, then object is
- // initialised back to an empty bitmap.
- BOOL CDIBSectionLite::SetBitmap(LPCTSTR lpszResourceName)
- {
- HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetResourceHandle(),
- lpszResourceName,
- IMAGE_BITMAP,
- 0,0,
- LR_CREATEDIBSECTION);
- if (!hBmp) return FALSE;
- BOOL bResult = SetBitmap(hBmp);
- ::DeleteObject(hBmp);
- return bResult;
- }
- // --- In?: lpBitmapInfo - pointer to a BITMAPINFO structure
- // lpBits - pointer to image bits
- // --- Out :
- // --- Returns : Returns TRUE on success, FALSE otherwise
- // --- Effect : Initialises the bitmap using the information in lpBitmapInfo to determine
- // the dimensions and colours, and the then sets the bits from the bits in
- // lpBits. If failure, then object is initialised back to an empty bitmap.
- BOOL CDIBSectionLite::SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits)
- {
- //DeleteObject(); //Z.t注释
- if (!lpBitmapInfo || !lpBits)
- return FALSE;
- HDC hDC = NULL;
- try {
- BITMAPINFOHEADER& bmih = lpBitmapInfo->bmiHeader;
- // Compute the number of colours in the colour table
- m_iColorTableSize = NumColorEntries(bmih.biBitCount);
- DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD);
- // Copy over BITMAPINFO contents
- memcpy(&m_DIBinfo, lpBitmapInfo, dwBitmapInfoSize);
- // Should now have all the info we need to create the sucker.
- //TRACE(_T("Width %d, Height %d, Bits/pixel %d, Image Size %d\n"),
- // bmih.biWidth, bmih.biHeight, bmih.biBitCount, bmih.biSizeImage);
- // Create a DC which will be used to get DIB, then create DIBsection
- hDC = ::GetDC(NULL);
- if (!hDC)
- {
- TRACE0("Unable to get DC\n");
- AfxThrowResourceException();
- }
- m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo,
- m_iColorDataType, &m_ppvBits, NULL, 0);
- ::ReleaseDC(NULL, hDC);
- if (!m_hBitmap)
- {
- TRACE0("CreateDIBSection failed\n");
- AfxThrowResourceException();
- }
- DWORD dwImageSize = m_DIBinfo.bmiHeader.biSizeImage;
- if (dwImageSize == 0)
- {
- int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth,
- lpBitmapInfo->bmiHeader.biBitCount);
- dwImageSize = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight;
- }
- // Flush the GDI batch queue
- GdiFlush();
- memcpy(m_ppvBits, lpBits, dwImageSize);
- if (!CreatePalette())
- {
- TRACE0("Unable to create palette\n");
- AfxThrowResourceException();
- }
- }
- catch (CException *e)
- {
- e->Delete();
- _ShowLastError();
- if (hDC)
- ::ReleaseDC(NULL, hDC);
- DeleteObject();
- return FALSE;
- }
- return TRUE;
- }
- // --- In?: hBitmap - handle to image
- // pPalette - optional palette to use when setting image
- // --- Out :
- // --- Returns : Returns TRUE on success, FALSE otherwise
- // --- Effect : Initialises the bitmap from the HBITMAP supplied. If failure, then
- // object is initialised back to an empty bitmap.
- BOOL CDIBSectionLite::SetBitmap(HBITMAP hBitmap, CPalette* pPalette /*= NULL*/)
- {
- //DeleteObject(); //Z.t注释
- if (!hBitmap)
- return FALSE;
- // Get dimensions of bitmap
- BITMAP bm;
- if (!::GetObject(hBitmap, sizeof(bm),(LPVOID)&bm))
- return FALSE;
- bm.bmHeight = abs(bm.bmHeight);
- CWindowDC dc(NULL);
- CPalette* pOldPalette = NULL;
- try {
- m_iColorTableSize = NumColorEntries(bm.bmBitsPixel);
- // Initialize the BITMAPINFOHEADER in m_DIBinfo
- BITMAPINFOHEADER& bih = m_DIBinfo.bmiHeader;
- bih.biSize = sizeof(BITMAPINFOHEADER);
- bih.biWidth = bm.bmWidth;
- bih.biHeight = bm.bmHeight;
- bih.biPlanes = 1; // Must always be 1 according to docs
- bih.biBitCount = bm.bmBitsPixel;
- bih.biCompression = BI_RGB;
- bih.biSizeImage = BytesPerLine(bm.bmWidth, bm.bmBitsPixel) * bm.bmHeight;
- bih.biXPelsPerMeter = 0;
- bih.biYPelsPerMeter = 0;
- bih.biClrUsed = 0;
- bih.biClrImportant = 0;
- // calls GetDIBits with NULL bits pointer to fill in the BITMAPINFOHEADER data
- if (!::GetDIBits(dc.m_hDC, hBitmap, 0, bm.bmHeight, NULL, m_DIBinfo, m_iColorDataType))
- {
- TRACE0("Unable to GetDIBits\n");
- AfxThrowResourceException();
- }
- // If the driver did not fill in the biSizeImage field, then compute it
- // Each scan line of the image is aligned on a DWORD (32bit) boundary
- if (bih.biSizeImage == 0)
- bih.biSizeImage = BytesPerLine(bih.biWidth, bih.biBitCount) * bih.biHeight;
- if (pPalette)
- SetPalette(pPalette);
- else
- CreateHalftonePalette(m_Palette, m_iColorTableSize);
- if (m_Palette.GetSafeHandle())
- {
- pOldPalette = dc.SelectPalette(&m_Palette, FALSE);
- dc.RealizePalette();
- }
- // Create it!
- m_hBitmap = CreateDIBSection(dc.m_hDC,
- (const BITMAPINFO*) m_DIBinfo,
- m_iColorDataType,
- &m_ppvBits,
- NULL, 0);
- if (pOldPalette)
- dc.SelectPalette(pOldPalette, FALSE);
- pOldPalette = NULL;
- if (!m_hBitmap)
- {
- TRACE0("Unable to CreateDIBSection\n");
- AfxThrowResourceException();
- }
- // Need to copy the supplied bitmap onto the newly created DIBsection
- CDC memDC, CopyDC;
- if (!CopyDC.CreateCompatibleDC(&dc) || !memDC.CreateCompatibleDC(&dc))
- {
- TRACE0("Unable to create compatible DC's\n");
- AfxThrowResourceException();
- }
- if (m_Palette.GetSafeHandle())
- {
- memDC.SelectPalette(&m_Palette, FALSE); memDC.RealizePalette();
- CopyDC.SelectPalette(&m_Palette, FALSE); CopyDC.RealizePalette();
- }
- GdiFlush();
- HBITMAP hOldMemBitmap = (HBITMAP) SelectObject(memDC.m_hDC, hBitmap);
- HBITMAP hOldCopyBitmap = (HBITMAP) SelectObject(CopyDC.m_hDC, m_hBitmap);
- CopyDC.BitBlt(0,0, bm.bmWidth, bm.bmHeight, &memDC, 0,0, SRCCOPY);
- SelectObject(memDC.m_hDC, hOldMemBitmap);
- SelectObject(CopyDC.m_hDC, hOldCopyBitmap);
- if (m_Palette.GetSafeHandle())
- {
- memDC.SelectStockObject(DEFAULT_PALETTE);
- CopyDC.SelectStockObject(DEFAULT_PALETTE);
- }
- }
- catch (CException *e)
- {
- e->Delete();
- _ShowLastError();
- if (pOldPalette)
- dc.SelectPalette(pOldPalette, FALSE);
- DeleteObject();
- return FALSE;
- }
- return TRUE;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Persistance...
- // --- In?: lpszFileName - image filename
- // --- Out :
- // --- Returns : Returns TRUE on success, FALSE otherwise
- // --- Effect : Loads the bitmap from a bitmap file with the name lpszFileName.
- // If failure, then object is initialised back to an empty bitmap.
- BOOL CDIBSectionLite::Load(LPCTSTR lpszFileName)
- {
- CFile file;
- if (!file.Open(lpszFileName, CFile::modeRead))
- return FALSE;
- // Get the current file position.
- DWORD dwFileStart = file.GetPosition();
- // The first part of the file contains the file header.
- // This will tell us if it is a bitmap, how big the header is, and how big
- // the file is. The header size in the file header includes the color table.
- BITMAPFILEHEADER BmpFileHdr;
- int nBytes;
- nBytes = file.Read(&BmpFileHdr, sizeof(BmpFileHdr));
- if (nBytes != sizeof(BmpFileHdr))
- {
- TRACE0("Failed to read file header\n");
- return FALSE;
- }
- // Check that we have the magic 'BM' at the start.
- if (BmpFileHdr.bfType != DS_BITMAP_FILEMARKER)
- {
- TRACE0("Not a bitmap file\n");
- return FALSE;
- }
- // Read the header (assuming it's a DIB).
- DIBINFO BmpInfo;
- nBytes = file.Read(&BmpInfo, sizeof(BITMAPINFOHEADER));
- if (nBytes != sizeof(BITMAPINFOHEADER))
- {
- TRACE0("Failed to read BITMAPINFOHEADER\n");
- return FALSE;
- }
- // Check that we have a real Windows DIB file.
- if (BmpInfo.bmiHeader.biSize != sizeof(BITMAPINFOHEADER))
- {
- TRACE0(" File is not a Windows DIB\n");
- return FALSE;
- }
- // See how big the color table is in the file (if there is one).
- int nColors = NumColorEntries(BmpInfo.bmiHeader.biBitCount);
- if (nColors > 0)
- {
- // Read the color table from the file.
- int nColorTableSize = nColors * sizeof(RGBQUAD);
- nBytes = file.Read(BmpInfo.ColorTable(), nColorTableSize);
- if (nBytes != nColorTableSize)
- {
- TRACE0("Failed to read color table\n");
- return FALSE;
- }
- }
- // So how big the bitmap surface is.
- int nBitsSize = BmpFileHdr.bfSize - BmpFileHdr.bfOffBits;
- // Allocate the memory for the bits and read the bits from the file.
- BYTE* pBits = (BYTE*) malloc(nBitsSize);
- if (!pBits)
- {
- TRACE0("Out of memory for DIB bits\n");
- return FALSE;
- }
- // Seek to the bits in the file.
- file.Seek(dwFileStart + BmpFileHdr.bfOffBits, CFile::begin);
- // read the bits
- nBytes = file.Read(pBits, nBitsSize);
- if (nBytes != nBitsSize)
- {
- TRACE0("Failed to read bits\n");
- free(pBits);
- return FALSE;
- }
- // Everything went OK.
- BmpInfo.bmiHeader.biSizeImage = nBitsSize;
- if (!SetBitmap((LPBITMAPINFO) BmpInfo, pBits))
- {
- TRACE0("Failed to set bitmap info\n");
- free(pBits);
- return FALSE;
- }
- free(pBits);
- return TRUE;
- }
- // --- In?: lpszFileName - image filename
- // --- Out :
- // --- Returns : Returns TRUE on success, FALSE otherwise
- // --- Effect : Saves the image to file.
- BOOL CDIBSectionLite::Save(LPCTSTR lpszFileName)
- {
- BITMAPFILEHEADER hdr;
- LPBITMAPINFOHEADER lpbi = GetBitmapInfoHeader();
- if (!lpbi || !lpszFileName)
- return FALSE;
- CFile file;
- if (!file.Open(lpszFileName, CFile::modeWrite|CFile::modeCreate))
- return FALSE;
- DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD);
- DWORD dwFileHeaderSize = dwBitmapInfoSize + sizeof(hdr);
- // Fill in the fields of the file header
- hdr.bfType = DS_BITMAP_FILEMARKER;
- hdr.bfSize = dwFileHeaderSize + lpbi->biSizeImage;
- hdr.bfReserved1 = 0;
- hdr.bfReserved2 = 0;
- hdr.bfOffBits = dwFileHeaderSize;
- // Write the file header
- file.Write(&hdr, sizeof(hdr));
- // Write the DIB header
- file.Write(lpbi, dwBitmapInfoSize);
- // Write DIB bits
- file.Write(GetDIBits(), lpbi->biSizeImage);
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CDIBSectionLite palette stuff
- // --- In?:
- // --- Out :
- // --- Returns : TRUE on success
- // --- Effect : Creates the palette from the DIBSection's color table. Assumes
- // m_iColorTableSize has been set and the DIBsection m_hBitmap created
- BOOL CDIBSectionLite::CreatePalette()
- {
- m_Palette.DeleteObject();
- if (!m_hBitmap)
- return FALSE;
- // Create a 256 color halftone palette if there is no color table in the DIBSection
- if (m_iColorTableSize == 0)
- return CreateHalftonePalette(m_Palette, 256);
- HDC hDC = ::GetDC(NULL);
- if (!hDC)
- return FALSE;
- // Get space for the colour entries
- RGBQUAD *pRGB = new RGBQUAD[m_iColorTableSize];
- if (!pRGB)
- {
- ReleaseDC(NULL, hDC);
- return CreateHalftonePalette(m_Palette, m_iColorTableSize);
- }
- // Create a memory DC compatible with the current DC
- CDC MemDC;
- MemDC.CreateCompatibleDC(CDC::FromHandle(hDC));
- if (!MemDC.GetSafeHdc())
- {
- delete [] pRGB;
- ::ReleaseDC(NULL, hDC);
- return CreateHalftonePalette(m_Palette, m_iColorTableSize);
- }
- ::ReleaseDC(NULL, hDC);
- HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap);
- if (!hOldBitmap)
- {
- delete [] pRGB;
- return CreateHalftonePalette(m_Palette, m_iColorTableSize);
- }
- // Get the colours used.
- int nColours = ::GetDIBColorTable(MemDC.GetSafeHdc(), 0, m_iColorTableSize, pRGB);
- // Clean up
- ::SelectObject(MemDC.GetSafeHdc(), hOldBitmap);
- if (!nColours) // No colours retrieved => the bitmap in the DC is not a DIB section
- {
- delete [] pRGB;
- return CreateHalftonePalette(m_Palette, m_iColorTableSize);
- }
- // Create and fill a LOGPALETTE structure with the colours used.
- PALETTEINFO PaletteInfo;
- PaletteInfo.palNumEntries = (WORD) m_iColorTableSize;
- int i ;
- for ( i = 0; i < nColours; i++)
- {
- PaletteInfo.palPalEntry[i].peRed = pRGB[i].rgbRed;
- PaletteInfo.palPalEntry[i].peGreen = pRGB[i].rgbGreen;
- PaletteInfo.palPalEntry[i].peBlue = pRGB[i].rgbBlue;
- PaletteInfo.palPalEntry[i].peFlags = 0;
- }
- for (; i < (int) m_iColorTableSize; i++)
- {
- PaletteInfo.palPalEntry[i].peRed = 0;
- PaletteInfo.palPalEntry[i].peGreen = 0;
- PaletteInfo.palPalEntry[i].peBlue = 0;
- PaletteInfo.palPalEntry[i].peFlags = 0;
- }
- if ( pRGB )
- {
- delete [] pRGB;
- pRGB = NULL;
- }
- // Create Palette!
- return m_Palette.CreatePalette(&PaletteInfo);
- }
- // --- In?: pPalette - new palette to use
- // --- Out :
- // --- Returns : TRUE on success
- // --- Effect : Sets the current palette used by the image from the supplied CPalette,
- // and sets the color table in the DIBSection
- BOOL CDIBSectionLite::SetPalette(CPalette* pPalette)
- {
- m_Palette.DeleteObject();
- if (!pPalette)
- return FALSE;
- UINT nColours = pPalette->GetEntryCount();
- if (nColours <= 0 || nColours > 256)
- return FALSE;
- // Get palette entries
- PALETTEINFO pi;
- pi.palNumEntries = (WORD) pPalette->GetPaletteEntries(0, nColours, (LPPALETTEENTRY) pi);
- // TODO: If pi.palNumEntries < m_iColorTableSize, then fill in blanks with 0's
- return SetLogPalette(&pi);
- }
- // --- In?: pLogPalette - new palette to use
- // --- Out :
- // --- Returns : TRUE on success
- // --- Effect : Sets the current palette used by the image from the supplied LOGPALETTE
- BOOL CDIBSectionLite::SetLogPalette(LOGPALETTE* pLogPalette)
- {
- ASSERT(pLogPalette->palVersion == (WORD) 0x300);
- UINT nColours = pLogPalette->palNumEntries;
- if (nColours <= 0 || nColours > 256)
- {
- CreatePalette();
- return FALSE;
- }
- // Create new palette
- m_Palette.DeleteObject();
- if (!m_Palette.CreatePalette(pLogPalette))
- {
- CreatePalette();
- return FALSE;
- }
- if (m_iColorTableSize == 0)
- return TRUE;
- // Set the DIB colours
- RGBQUAD RGBquads[256];
- for (UINT i = 0; i < nColours; i++)
- {
- RGBquads[i].rgbRed = pLogPalette->palPalEntry[i].peRed;
- RGBquads[i].rgbGreen = pLogPalette->palPalEntry[i].peGreen;
- RGBquads[i].rgbBlue = pLogPalette->palPalEntry[i].peBlue;
- RGBquads[i].rgbReserved = 0;
- }
- return FillDIBColorTable(nColours, RGBquads);
- }
- void CDIBSectionLite::CreateGradientBmp (COLORREF clrBack,COLORREF clrStart,COLORREF clrEnd,int iWidth,int iHeight,int iDirection)
- {
- RECT rectFill; // Rectangle for filling band
- float fStep; // How wide is each band?
- CBrush brush; // Brush to fill in the bar
- CBitmap ourNewBitmap;
- CWindowDC dc(NULL);
- CDC tempDC;
- CDC tempDC1;
- tempDC.CreateCompatibleDC(&dc);
- tempDC1.CreateCompatibleDC(&dc);
- ourNewBitmap.CreateDiscardableBitmap(&dc,iWidth,iHeight);
- //ourNewBitmap.CreateBitmap(iWidth,iHeight,3,32,NULL);
- CBitmap* pOldBitmap = tempDC.SelectObject(&ourNewBitmap);
- // First find out the largest color distance between the start and end colors. This distance
- // will determine how many steps we use to carve up the client region and the size of each
- // gradient rect.
- int r, g, b; // First distance, then starting value
- float rStep, gStep, bStep; // Step size for each color
- // Get the color differences
- r = (GetRValue(clrEnd) - GetRValue(clrStart));
- g = (GetGValue(clrEnd) - GetGValue(clrStart));
- b = (GetBValue(clrEnd) - GetBValue(clrStart));
- // Make the number of steps equal to the greatest distance
- int nSteps = max(abs(r), max(abs(g), abs(b)));
- // Determine how large each band should be in order to cover the
- // client with nSteps bands (one for every color intensity level)
- if(iDirection == BMGRADIENT_DIRECTION_HORZ)
- fStep = (float)iWidth / (float)nSteps;
- else if(iDirection == BMGRADIENT_DIRECTION_VERT)
- fStep = (float)iHeight / (float)nSteps;
- // Calculate the step size for each color
- rStep = r/(float)nSteps;
- gStep = g/(float)nSteps;
- bStep = b/(float)nSteps;
- // Reset the colors to the starting position
- r = GetRValue(clrStart);
- g = GetGValue(clrStart);
- b = GetBValue(clrStart);
- // Start filling bands
- for (int iOnBand = 0; iOnBand < nSteps; iOnBand++)
- {
- // Set the rect we will fill with the gradient
- if(iDirection == BMGRADIENT_DIRECTION_HORZ)
- {
- ::SetRect(&rectFill,
- (int)(iOnBand * fStep), // Upper left X
- 0, // Upper left Y
- (int)((iOnBand+1) * fStep), // Lower right X
- iHeight+1); // Lower right Y
- }
- else if(iDirection == BMGRADIENT_DIRECTION_VERT)
- {
- ::SetRect(&rectFill,
- 0, // Upper left X
- (iOnBand * fStep), // Upper left Y
- iWidth, // Lower right X
- (int)((iOnBand+1) * fStep)); // Lower right Y
- }
- // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth
- VERIFY(brush.CreateSolidBrush(RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)));
- tempDC.FillRect(&rectFill,&brush);
- VERIFY(brush.DeleteObject());
- // If we are past the maximum for the current position we need to get out of the loop.
- // Before we leave, we repaint the remainder of the client area with the background color.
- if(iDirection == BMGRADIENT_DIRECTION_HORZ)
- {
- if (rectFill.right > iWidth)
- {
- ::SetRect(&rectFill, rectFill.right, 0, iWidth, iHeight);
- VERIFY(brush.CreateSolidBrush(clrBack));
- tempDC.FillRect(&rectFill, &brush);
- VERIFY(brush.DeleteObject());
- return;
- }
- }
- else if(iDirection == BMGRADIENT_DIRECTION_VERT)
- {
- if (rectFill.right > iHeight)
- {
- ::SetRect(&rectFill, rectFill.right, 0, iWidth, iHeight);
- VERIFY(brush.CreateSolidBrush(clrBack));
- tempDC.FillRect(&rectFill, &brush);
- VERIFY(brush.DeleteObject());
- return;
- }
- }
- }
- // Create a 32 bit bitmap
- #if 1
- m_pdwBits = new DWORD[iWidth*iHeight];
- m_ppvBits = m_pdwBits;
- #else
- m_ppvBits = new DWORD[iWidth*iHeight];
- #endif
- BITMAPINFO bih;
- // create DIB Section
- bih.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bih.bmiHeader.biWidth = iWidth;
- bih.bmiHeader.biHeight = iHeight;
- bih.bmiHeader.biPlanes = 1;
- bih.bmiHeader.biBitCount = 32;
- bih.bmiHeader.biCompression = BI_RGB;
- bih.bmiHeader.biSizeImage = 0;
- bih.bmiHeader.biXPelsPerMeter = 0;
- bih.bmiHeader.biYPelsPerMeter = 0;
- bih.bmiHeader.biClrUsed = 0;
- bih.bmiHeader.biClrImportant = 0;
- SetBitmap(&bih,m_ppvBits);
- DWORD* pLine = (DWORD*)GetDIBits();
- // Copy the bits into our 32 bit dib..
- for(int i=0;i<iHeight;i++)
- {
- for(int j=0;j<iWidth;j++)
- {
- pLine[(i*iWidth)+j] = FixColorRef(tempDC.GetPixel(j,i));
- }
- }
- // Set the dc back to normal
- tempDC.SelectObject(pOldBitmap);
- #if 0
- if ( m_pdwBits )
- {
- delete []m_pdwBits;
- m_pdwBits = NULL;
- }
- #endif
- }
- void CDIBSectionLite::Create32BitFromPicture (CPictureHolder* pPicture,int iWidth,int iHeight)
- {
- CBitmap ourNewSizedBMP;
- CWindowDC dc(NULL); // 创建DC时出错,内存泄漏了;
- CDC tempDC;
- CRect rcRender;
- tempDC.CreateCompatibleDC(&dc);
- ourNewSizedBMP.CreateDiscardableBitmap(&dc,iWidth,iHeight);
- // Now we need to select it into our temp DC so we can render the picture onto it
- CBitmap* pOldBitmap = tempDC.SelectObject(&ourNewSizedBMP);
- // Render the picture onto our bmp
- rcRender.SetRect(0,0,iWidth,iHeight);
- pPicture->Render(&tempDC,rcRender,rcRender);
- // Create a 32 bit bitmap
- #if 1
- m_pdwBits = new DWORD[iWidth*iHeight];
- //memcpy(m_ppvBits,pdwBits,sizeof(DWORD));
- m_ppvBits = m_pdwBits;
- #else
- m_ppvBits = new DWORD[iWidth*iHeight];
- #endif
- BITMAPINFO bih;
- // create DIB Section
- bih.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bih.bmiHeader.biWidth = iWidth;
- bih.bmiHeader.biHeight = iHeight;
- bih.bmiHeader.biPlanes = 1;
- bih.bmiHeader.biBitCount = 32;
- bih.bmiHeader.biCompression = BI_RGB;
- bih.bmiHeader.biSizeImage = 0;
- bih.bmiHeader.biXPelsPerMeter = 0;
- bih.bmiHeader.biYPelsPerMeter = 0;
- bih.bmiHeader.biClrUsed = 0;
- bih.bmiHeader.biClrImportant = 0;
- SetBitmap(&bih,m_ppvBits);
- DWORD* pLine = (DWORD*)GetDIBits();
- // Copy the bits into our 32 bit dib..
- for(int i=0;i<iHeight;i++)
- {
- for(int j=0;j<iWidth;j++)
- {
- pLine[(i*iWidth)+j] = FixColorRef(tempDC.GetPixel(j,i));
- }
- }
- // Set the dc back to normal
- tempDC.SelectObject(pOldBitmap);
- #if 0
- if ( m_pdwBits )
- {
- delete []m_pdwBits;
- m_pdwBits = NULL;
- }
- #endif
- }
- inline COLORREF CDIBSectionLite::FixColorRef(COLORREF clr)
- {
- int r = GetRValue(clr);
- int g = GetGValue(clr);
- int b = GetBValue(clr);
- return RGB(b,g,r);
- }
- // --- In?: nNumColours - number of colours to set
- // pRGB - colours to fill
- // --- Out :
- // --- Returns : Returns TRUE on success
- // --- Effect : Sets the colours used by the image. Only works if # colours <= 256
- BOOL CDIBSectionLite::FillDIBColorTable(UINT nNumColours, RGBQUAD *pRGB)
- {
- if (!m_hBitmap || !pRGB || !nNumColours || !m_iColorTableSize
- || nNumColours > 256)
- return FALSE;
- // Create a memory DC compatible with the screen
- HDC hDC = ::GetDC(NULL);
- if (!hDC) return FALSE;
- CDC MemDC;
- MemDC.CreateCompatibleDC(CDC::FromHandle(hDC));
- ::ReleaseDC(NULL, hDC);
- if (!MemDC.GetSafeHdc())
- return FALSE;
- HBITMAP hOldBitmap = (HBITMAP) ::SelectObject(MemDC.GetSafeHdc(), m_hBitmap);
- // Set the bitmap colours.
- int nColours = ::SetDIBColorTable(MemDC.GetSafeHdc(), 0, nNumColours, pRGB);
- // Clean up
- if (hOldBitmap)
- ::SelectObject(MemDC.GetSafeHdc(), hOldBitmap);
- MemDC.DeleteDC();
- return (nColours > 0);
- }
- #ifdef _DEBUG
- // Makes trace windows a little bit more informative...
- void CDIBSectionLite::_ShowLastError()
- {
- LPVOID lpMsgBuf;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf, 0, NULL);
- TRACE1("Last error: %s\n", lpMsgBuf);
- LocalFree(lpMsgBuf);
- }
- #else
- void CDIBSectionLite::_ShowLastError() {}
- #endif
|