René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle - Most wanted - Feedback -
 

DibSection: a C++ class

This class wraps a DIB Section. A DIB Section is basically a DIB that exposes its internal Data (Pixel) so that they can be written to directly.
Most of its methods should be fairly self explanotary, except Size. This method sizes and resized the bitmap. It is first destroyed using DeleteObject(). If the size happens to be exactly the same size that the bitmap already had, DeleteObject is not called however and hence no new DibSection allocated but false returned.
This class is used in

The header file

DibSection.h
/* 
   DibSection.h

   Copyright (C) 2002-2004 René Nyffenegger

   This source code is provided 'as-is', without any express or implied
   warranty. In no event will the author be held liable for any damages
   arising from the use of this software.

   Permission is granted to anyone to use this software for any purpose,
   including commercial applications, and to alter it and redistribute it
   freely, subject to the following restrictions:

   1. The origin of this source code must not be misrepresented; you must not
      claim that you wrote the original source code. If you use this source code
      in a product, an acknowledgment in the product documentation would be
      appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original source code.

   3. This notice may not be removed or altered from any source distribution.

   René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/

#ifndef DIB_SECTION_H_
#define DIB_SECTION_H__

class DC;

#include "Bitmap.h"

class DibSection : public Bitmap {
  public:
    DibSection(int bmpWidth, int bmpHeight);
    DibSection();
   ~DibSection();

    inline void PixelAt(unsigned int x, unsigned int y, unsigned int color);
 
    void BitBltTo  (DC const& dcTo, int xTo, int yTo);
    void BitBltFrom(DC const& dcFrom, int xTo, int yTo, int width, int height);
 
    bool Size(int bmpWidth, int bmpHeight);

  private:
    char*   theBits_;

    /*! todo bmpWidth_ and such to the base class! */
    int     bmpWidth_;
    int     bmpHeight_;

    int     lineLength_;
};

// 4273 is inconsistent dll linkage.  dllexport assumed.
//#pragma warning (push)
//#pragma warning (disable: 4273)
void DibSection::PixelAt(unsigned int x, unsigned int y, unsigned int color) {
//#pragma warning (pop)

#ifdef _DEBUG
  if (x>bmpWidth_) {
    throw "x too large in PixelAt";
  }
  if (y>bmpHeight_) {
    throw "y too large in PixelAt";
  }
#endif

  theBits_[y*lineLength_ + 3*x + 0] = (color & 0xff0000) >> 16;
  theBits_[y*lineLength_ + 3*x + 1] = (color & 0x00ff00) >>  8;
  theBits_[y*lineLength_ + 3*x + 2] = (color & 0x0000ff) >>  0;
}

#endif

The implementation file

DibSection.cpp
/* 
   DibSection.cpp

   Copyright (C) 2002-2005 René Nyffenegger

   This source code is provided 'as-is', without any express or implied
   warranty. In no event will the author be held liable for any damages
   arising from the use of this software.

   Permission is granted to anyone to use this software for any purpose,
   including commercial applications, and to alter it and redistribute it
   freely, subject to the following restrictions:

   1. The origin of this source code must not be misrepresented; you must not
      claim that you wrote the original source code. If you use this source code
      in a product, an acknowledgment in the product documentation would be
      appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original source code.

   3. This notice may not be removed or altered from any source distribution.

   René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/

#include "DibSection.h"
#include "DC.h"
#include "MemoryDC.h"
#include "win32_LastError.h"

DibSection::DibSection(int bmpWidth, int bmpHeight) : 
  Bitmap     (), 
  bmpWidth_  (0), 
  bmpHeight_ (0), 
  lineLength_(0) 
{
  Size(bmpWidth, bmpHeight);
}

DibSection::DibSection() : Bitmap(), theBits_(0), bmpWidth_(0), bmpHeight_(0), lineLength_(0) {}

bool DibSection::Size(int bmpWidth, int bmpHeight) {
  if (bmpWidth_ == bmpWidth && bmpHeight == bmpHeight_) {
    return false;
  }

  if (bitmap_) {
    ::DeleteObject(bitmap_);
  }

  bmpWidth_ = bmpWidth;
  bmpHeight_= bmpHeight;

  BITMAPINFOHEADER bitmapInfo;

  bitmapInfo.biSize          = sizeof(BITMAPINFOHEADER);
  bitmapInfo.biWidth         = bmpWidth_;
  bitmapInfo.biHeight        = bmpHeight_;
  bitmapInfo.biPlanes        = 1;
  bitmapInfo.biBitCount      = 24;
  bitmapInfo.biCompression   = BI_RGB;
  bitmapInfo.biSizeImage     = 0;
  bitmapInfo.biXPelsPerMeter = 0;
  bitmapInfo.biYPelsPerMeter = 0;
  bitmapInfo.biClrUsed       = 0;
  bitmapInfo.biClrImportant  = 0;

  bitmap_ = ::CreateDIBSection(
      ::GetWindowDC(0), 
      (LPBITMAPINFO)&bitmapInfo,
      DIB_RGB_COLORS,
      (LPVOID*) &theBits_,
      0,
      0);


  if (!bitmap_) {
    ::MessageBox(0, Win32_LastError().c_str(), "CreateDIBSection failed", 0);
  }

  lineLength_ = 3*bmpWidth;
  lineLength_ = ((lineLength_ + 3) >> 2 ) << 2;

  return true;
}

DibSection::~DibSection() {
  ::DeleteObject(bitmap_);
  bitmap_=0;
}

void DibSection::BitBltTo(const DC& dcTo, int xTo, int yTo) {
  MemoryDC memDc;

  Bitmap oldBitmap = memDc.Select(*this);

  ::BitBlt (dcTo, xTo, yTo, bmpWidth_, bmpHeight_, memDc, 0, 0, SRCCOPY);

  memDc.Select(oldBitmap);
}

void DibSection::BitBltFrom(const DC& dcFrom, int xTo, int yTo, int width, int height) {
  MemoryDC memDc;

  Bitmap oldBitmap = memDc.Select(*this);

  ::BitBlt (memDc, xTo, yTo, width, height, dcFrom, 0, 0, SRCCOPY);

  memDc.Select(oldBitmap);
}