Character-Recognition Application for BREW "Recog" -4/4-
Building the Bitmap Class
Bitmap Class Motivation
A reusable Bitmap class is made to allow applications like Recog to easily read bitmaps.
Bitmap Class Header File
- Bitmap.hpp -
#if !defined(__BITMAP_HPP)
#define __BITMAP_HPP
#include <SophiaFramework.hpp>
SFMTYPEDEFCLASS(Bitmap)
class Bitmap {
private:
SFBBitmapSmp _pbitmap; // Pointer for bitmap
SFBDIBSmp _pdib; // Pointer for bitmap in DIB format
SFCError GetDib(Void); // Get bitmap in DIB format
SFCError Copy(BitmapConstRef bitmap); // Copy bitmap
public:
// Constructor
Bitmap(Void);
Bitmap(ACharConstPtr file);
Bitmap(WCharConstPtr file);
Bitmap(SFXAnsiStringConstRef file);
Bitmap(SFXWideStringConstRef file);
Bitmap(ACharConstPtr resFile, UInt16 id);
Bitmap(WCharConstPtr resFile, UInt16 id);
Bitmap(SFXAnsiStringConstRef resFile, UInt16 id);
Bitmap(SFXWideStringConstRef resFile, UInt16 id);
Bitmap(SFBBitmapSmpConstRef pbitmap);
Bitmap(BitmapConstRef bitmap);
~Bitmap(Void); // Destructor
// Read bitmap from file
SFCError LoadBitmap(ACharConstPtr file);
SFCError LoadBitmap(WCharConstPtr file);
SFCError LoadBitmap(SFXAnsiStringConstRef file);
SFCError LoadBitmap(SFXWideStringConstRef file);
// Read bitmap from resource file
SFCError LoadResBitmap(ACharConstPtr resFile, UInt16 id);
SFCError LoadResBitmap(WCharConstPtr resFile, UInt16 id);
SFCError LoadResBitmap(SFXAnsiStringConstRef resFile, UInt16 id);
SFCError LoadResBitmap(SFXWideStringConstRef resFile, UInt16 id);
// Create copy of bitmap
SFCError Create(SFBBitmapSmpConstRef pbitmap);
// Substitute operator
BitmapConstRef operator =(SFBBitmapSmpConstRef pbitmap);
BitmapConstRef operator =(BitmapConstRef bitmap);
// Get color information of the image
SFXRGBColor GetPixel(SFXPixelConstRef pixel) const;
SFXRGBColor GetPixel(SInt16 x, SInt16 y) const {
return GetPixel(SFXPixel(x, y));
}
SFXSize GetSize(Void) const; // Get size of the bitmap
UInt16 GetWidth(Void) const; // Get width of the bitmap
UInt16 GetHeight(Void) const; // Get height of the bitmap
UInt08 GetDepth(Void) const; // Get color depth of the bitmap
};
#endif
The Constructor, the LoadBitmap and LoadResBitmap functions are all designed to read bitmaps from files.
The GetDib Function: Generate DIB from DDB
SFCError Bitmap::GetDib(Void)
{
SFCError error(SFERR_NO_ERROR);
_pdib.Release();
if(_pbitmap != null) {
SFBDIBPtr pdib;
error = _pbitmap->QueryInterface(AEECLSID_BITMAP,
reinterpret_cast<VoidHandle>(&pdib));
if (error == SFERR_NO_ERROR) {
_pdib.Attach(pdib);
} else {
_pbitmap.Release();
}
} else {
error = SFERR_FAILED;
}
return error;
}
These are the important points of the previous code.
SFBDIBPtr pdib;
error = _pbitmap->QueryInterface(AEECLSID_BITMAP,
reinterpret_cast<VoidHandle>(&pdib));
_pbitmap is a member variable of the SFBBitmapSmp class. The DIB is generated by calling SFBBitmap::QueryInterface with AEECLSID_BITMAP as the first argument, and a pointer to a pointer (which points to the DIB) as a second argument.
The responsibility for releasing the DIB prior to application termination is left to the user, but fortunately it is automatically handled by using SophiaFramework UNIVERSE's "smart" pointers.
_pdib.Attach(pdib);
The preceding line is used to make the smart pointer _pdib manage the pdib generated by the SFBBitmap::QueryInterface function.
To avoid numerous ill-timed function calls associated with the smart pointer, the object can be released manually with the smart pointer's "Release" member function.
The DIB generated by SFBBitmap::QueryInterface is independent from the original bitmap. So when the original bitmap is modified, a new DIB needs to be generated.
The GetPixel Function: Get Pixel Color
This table shows the relationship between members of the IDIB structure ( explained in section 3 ) and their corresponding SFBDIB class member functions.
| IDIB Structure | SFBDIB Class |
|---|---|
| cx | GetWidth(Void) |
| cy | GetHeight(Void) |
| nDepth | GetDepth(Void) |
| nPitch | GetPitch(Void) |
| pBmp | GetBuffer(Void) |
The data of point ( x, y ) is stored in the [ x * nDepth ] bit, counting from [ pBmp + y * nPitch ].
SFXRGBColor Bitmap::GetPixel(SFXPixelConstRef pixel) const
{
if (_pdib == null) {
return SFXRGBColor(0, 0, 0, 0);
}
UInt32 bitsIndex(_pdib->GetDepth());
bitsIndex *= pixel.GetX();
BytePtr p(_pdib->GetBuffer() +
pixel.GetY() * _pdib->GetPitch() + (bitsIndex >> 3));
// bitsIndex >> 3, equals bitsIndex / 8
// Get the head memory address where the
// value of the selected point is stored
// (Using bit operataions to speed things up)
SInt08 localBitsIndex(8 - static_cast<SInt08>(bitsIndex & 7));
// bitsIndex & 7, equals bitsIndex % 8
// now, the target data can be found
// (Using bit operataion to speed things up)
SInt16 len(_pdib->GetDepth());
NativeColor color(0);
BytePtr pcolor(reinterpret_cast<BytePtr>(&color));
SInt08 leftBits(8); // how many more bits can be inserted in pcolor
UInt08 getbits;
UInt16 mask;
while (len > 0) {
// getbits is assigned the smallest value between
// len, localBitsIndex and leftBits.
getbits = (localBitsIndex < leftBits)
? localBitsIndex : leftBits;
if (getbits > len) {
getbits = static_cast<UInt08>(len);
}
mask = static_cast<UInt16>(1 << localBitsIndex) - 1;
*pcolor = (*pcolor << getbits)
| ((static_cast<UInt08>(mask) & *p)
>> ((getbits < localBitsIndex)
? (localBitsIndex - getbits) : 0));
len -= getbits;
leftBits -= getbits;
localBitsIndex -= getbits;
if (localBitsIndex <= 0) {
++p;
localBitsIndex = 8;
}
if (leftBits <= 0) {
++pcolor;
leftBits = 8;
}
}
return _pdib->NativeToColor(color);
}
The NativeColor of the target pixel is converted to a SFXRGBColor in this code.
The need to access the buffer bit by bit, makes this code a little complicated.







