Logo Search packages:      
Sourcecode: paintlib version File versions

WinBmpEx.cpp

/*
/--------------------------------------------------------------------
|
|      $Id: WinBmpEx.cpp,v 1.6 2002/03/31 13:36:42 uzadow Exp $
|          PaintLib windows DrawDib bitmap class implementation
|
|          Copyright (c) 1998-2000 Bernard Delmée
|
\--------------------------------------------------------------------
*/

#include "stdafx.h"
#include "WinBmpEx.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

PLWinBmpEx::PLWinBmpEx()
{
#ifndef _WITHOUT_VFW_
    m_hdd = 0;
#endif
    m_pal = 0;
}

PLWinBmpEx::~PLWinBmpEx()
{
#ifndef _WITHOUT_VFW_
    if (m_hdd)    ::DrawDibClose(m_hdd);
#endif
    if (m_pal)    ::DeleteObject(m_pal);
}


//////////////////////////////////////////////////////////////////////
// Draw DIB on caller's DC. Does stretching from source to destination
// rectangles. Generally, you can let the following default to zero/NULL:
//
//    nStretchMode= 0 means 'use DrawDib'; any other value must be
//                  a valid stretch-mode and will force GDI usage       
//    hPal        = palette, default=NULL, (use DIB's palette)
//    bForeground = realize in foreground (default true)
//
// If you are handling palette messages, you should use bForeground=false,
// since you will realize the foreground palette in WM_QUERYNEWPALETTE.
//
BOOL PLWinBmpEx::DrawEx( HDC dc, const RECT* rcDst, const RECT* rcSrc,
                    HPALETTE hPal, bool bForeground,
                  int nStretchMode, DWORD ropcode )
{
    // Select, realize palette
    if (hPal==NULL)        // no palette specified:
        hPal = GetLogPalette();    // use default
    HPALETTE hOldPal = ::SelectPalette(dc, hPal, !bForeground);
    ::RealizePalette(dc);

    // Compute rectangles where NULL specified
    RECT rc;
    if (!rcSrc)
    {  // if no source rect, use whole bitmap
        rc.left = rc.top = 0;
        rc.right    = GetWidth();
        rc.bottom   = GetHeight();
        rcSrc = &rc;
    }
    if (!rcDst) // if no destination rect, use source
        rcDst = rcSrc;

    BOOL bRet = false;

#ifndef _WITHOUT_VFW_
    bool bUseDrawDib = nStretchMode < 0;
    if (bUseDrawDib)
    {
        if (!m_hdd)  VERIFY(m_hdd = DrawDibOpen());

        // Let DrawDib do the work!
        bRet = ::DrawDibDraw( m_hdd, dc,
                              rcDst->left,
                              rcDst->top,
                              rcDst->right  - rcDst->left,
                              rcDst->bottom - rcDst->top,
                              GetBMI(),
                              GetBits(),
                              rcSrc->left,
                              rcSrc->top,
                              rcSrc->right  - rcSrc->left,
                              rcSrc->bottom - rcSrc->top,
                              bForeground ? 0 : DDF_BACKGROUNDPAL);
    }
    else      // use normal draw function
#endif
    {
      // If user wanted DrawDib but vfw support is not linked in,
      // then try to use best looking GDI mode
      if (nStretchMode < 0) nStretchMode = HALFTONE;
      int osm = 0;
      if (nStretchMode > 0) osm = ::SetStretchBltMode( dc, nStretchMode );
#if 0 // way too slooooooooooooooooooow!        
      bRet = GDI_ERROR != ::StretchDIBits(
                      dc,
                        rcDst->left,
                        rcDst->top,
                        rcDst->right  - rcDst->left,
                        rcDst->bottom - rcDst->top,
                        rcSrc->left,
                        rcSrc->top,
                        rcSrc->right  - rcSrc->left,
                        rcSrc->bottom - rcSrc->top,
                        GetBits(),       // Pointer to bits
                        (BITMAPINFO*) GetBMI(),        // BITMAPINFO
                        DIB_RGB_COLORS,  // Options
                        ropcode);        // Raster operator code
#else
      HDC hSrcDC;
      hSrcDC = CreateCompatibleDC (dc);
      HGDIOBJ hOldBmp = ::SelectObject (hSrcDC, GetHandle());
      if (m_pClrTab)    // uses associated colormap
          (void) ::SetDIBColorTable (hSrcDC, 0, 256, (RGBQUAD *)m_pClrTab);

      bRet = ::StretchBlt (   dc,
                        rcDst->left,
                        rcDst->top,
                        rcDst->right  - rcDst->left,
                        rcDst->bottom - rcDst->top,
                        hSrcDC,
                        rcSrc->left,
                        rcSrc->top,
                        rcSrc->right  - rcSrc->left,
                        rcSrc->bottom - rcSrc->top,
                        ropcode );

      ::SelectObject (hSrcDC, hOldBmp);
      ::DeleteDC(hSrcDC);

      // restore GDI stretch-mode
      if (osm) 
          (void) ::SetStretchBltMode( dc, osm );
    }
#endif      // _WITHOUT_VFW_

    // restore DC palette
    if (hOldPal)
        ::SelectPalette(dc, hOldPal, true);

    return bRet;
}

// Draw DIB on DC.
void PLWinBmpEx::Draw( HDC dc, int x, int y, DWORD )
{
    // Compute destination rectangle
    RECT rcDst;
    rcDst.left        = x;
    rcDst.top         = y;
    rcDst.right       = x + GetWidth();
    rcDst.bottom    = y + GetHeight();
    (void) DrawEx( dc, &rcDst );
}

// Draw part of the DIB on a DC.
BOOL PLWinBmpEx::DrawExtract( HDC dc, POINT pntDest, RECT rcSrc )
{
    // Compute destination rectangle
    RECT rcDst;
    rcDst.left        = pntDest.x;
    rcDst.top         = pntDest.y;
    rcDst.right       = pntDest.x + abs(rcSrc.right  - rcSrc.left);
    rcDst.bottom    = pntDest.y + abs(rcSrc.bottom - rcSrc.top );
    return DrawEx( dc, &rcDst, &rcSrc );
}

// Play with the elastic bitmap...
void PLWinBmpEx::StretchDraw( HDC dc, int x, int y, double Factor, DWORD )
{
    // Compute rectangles
    RECT rcSrc, rcDst;
    rcSrc.left        = 0;
    rcSrc.top         = 0;
    rcSrc.right       = GetWidth();
    rcSrc.bottom    = GetHeight();
    rcDst.left        = x;
    rcDst.top         = y;
    rcDst.right       = x + int(Factor * GetWidth() );
    rcDst.bottom    = y + int(Factor * GetHeight());
    (void) DrawEx( dc, &rcDst, &rcSrc );
}

// Draws the bitmap on the given device context.
// Scales the bitmap so w is the width and h the height.
void PLWinBmpEx::StretchDraw( HDC hDC, int x, int y, int w, int h, DWORD )
{
    // Compute rectangles
    RECT rcSrc, rcDst;
    rcSrc.left        = 0;
    rcSrc.top         = 0;
    rcSrc.right       = GetWidth();
    rcSrc.bottom    = GetHeight();
    rcDst.left        = x;
    rcDst.top         = y;
    rcDst.right       = x + w;
    rcDst.bottom    = y + h;
    (void) DrawEx( hDC, &rcDst, &rcSrc );
}


//////////////////////////////////////////////////////////////////////
// all code hereunder related to palette management

#define PALVERSION 0x300  // magic number for LOGPALETTE

const int  MAXPALCOLORS = 256;

//////////////////
// Create the palette. Use halftone palette for hi-color bitmaps.
//
HPALETTE PLWinBmpEx::CreatePalette(void)
{
    // should not already have palette
    ASSERT( m_pal == 0 );

    HPALETTE hRet = HPALETTE(0);
    if (m_pClrTab)
    {
        // RGBQUAD* colors = new RGBQUAD[MAXPALCOLORS];
        UINT nColors = GetNumColors();  // 256, really...
        // Allocate memory for logical palette
        int len = sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nColors;
        LOGPALETTE* pLogPal = (LOGPALETTE*)new char[len];
        if (!pLogPal)
            return hRet;

        // set version and number of palette entries
        pLogPal->palVersion = PALVERSION;
        pLogPal->palNumEntries = (WORD) nColors;

        // copy color entries
        for (UINT i = 0; i < nColors; i++)
        {
            PLBYTE * pb = (PLBYTE *) (m_pClrTab+i);
            pLogPal->palPalEntry[i].peRed   = pb[PL_RGBA_RED  ];
            pLogPal->palPalEntry[i].peGreen = pb[PL_RGBA_GREEN];
            pLogPal->palPalEntry[i].peBlue  = pb[PL_RGBA_BLUE ];
            pLogPal->palPalEntry[i].peFlags = 0;
        }

        // create the palette and destroy LOGPAL
        hRet = ::CreatePalette(pLogPal);
        delete [] (char*)pLogPal;
    }
    else
    {
        // If the file itself did not contain a colormap, we will use
        // a default palette and rely on DrawDib's halftoning.
        // When displaying higher-color images on 8bpp hardware,
        // this is suboptimal though. Ideally we should build the
        // palette according to an histogram of the actual RGB values.
        // "SeeDib" from MS Source Code Samples does that nicely
        HDC dcScreen = ::GetWindowDC(NULL);
        hRet = ::CreateHalftonePalette(dcScreen);
        ::ReleaseDC (NULL, dcScreen);

    }
    return hRet;
}

// this is implicitly done the first time one calls GetLogPalette
// e.g. in DrawEx(); but one needs to call it when recycling a
// bitmap with a new contents (e.g. decoding a second file)
void PLWinBmpEx::BuildLogPalette(void)
{
    if (m_pal)
    {
        ::DeleteObject(m_pal);
        m_pal = 0;
    }

    m_pal = CreatePalette();
}


HPALETTE PLWinBmpEx::GetLogPalette(void)
{
    // build the palette the 1st time we're asked to provide it
    if ( ! m_pal )
        // the bitmap has hopefully been populated (by a decoder),
        // we can associate it with a logical palette
        m_pal = CreatePalette();

    return m_pal;
}

/*
/--------------------------------------------------------------------
|
|      $Log: WinBmpEx.cpp,v $
|      Revision 1.6  2002/03/31 13:36:42  uzadow
|      Updated copyright.
|
|      Revision 1.5  2001/09/16 19:03:23  uzadow
|      Added global name prefix PL, changed most filenames.
|
|      Revision 1.4  2000/09/01 13:27:06  Administrator
|      Minor bugfixes
|
|      Revision 1.3  2000/07/07 14:00:26  Ulrich von Zadow
|      Minor bugfixes.
|
|      Revision 1.2  2000/03/30 21:47:41  Ulrich von Zadow
|      Added zoom-in mode, PLWinBmpEx, conditional use of DrawDIB
|      and some other nice stuff by Bernard Delmée.
|
|
|
\--------------------------------------------------------------------
*/

Generated by  Doxygen 1.6.0   Back to index