|
|
/**************************************************************************\
* * Copyright (c) 1998 Microsoft Corporation * * Module Name: * * GpBitmap.hpp * * Abstract: * * Bitmap related declarations * * Revision History: * * 12/09/1998 davidx * Created it. * \**************************************************************************/
#ifndef _GPBITMAP_HPP
#define _GPBITMAP_HPP
#define NEARCONSTANTALPHA 0x10
//--------------------------------------------------------------------------
// Abstract base class for bitmap image and metafile
//--------------------------------------------------------------------------
class GpImage : public GpObject { protected: VOID SetValid(BOOL valid) { GpObject::SetValid(valid ? ObjectTagImage : ObjectTagInvalid); }
public:
// Construct a GpImage object from a disk file
static GpImage* LoadImage(const WCHAR* filename);
// Construct a GpImage object from a data stream
static GpImage* LoadImage(IStream* stream);
virtual ObjectType GetObjectType() const { return ObjectTypeImage; }
// Make a copy of the image object
virtual GpImage* Clone() const= 0;
virtual GpImage* CloneColorAdjusted( GpRecolor * recolor, ColorAdjustType type = ColorAdjustTypeDefault ) const = 0;
// Get the encoder parameter list size
virtual GpStatus GetEncoderParameterListSize( CLSID* clsidEncoder, UINT* size ) = 0;
// Get the encoder parameter list
virtual GpStatus GetEncoderParameterList( CLSID* clsidEncoder, UINT size, OUT EncoderParameters* pBuffer ) = 0;
// Save images
virtual GpStatus SaveToStream( IStream* stream, CLSID* clsidEncoder, EncoderParameters* encoderParams ) = 0;
virtual GpStatus SaveToFile( const WCHAR* filename, CLSID* clsidEncoder, EncoderParameters* encoderParams ) = 0;
virtual GpStatus SaveAdd( const EncoderParameters* encoderParams ) = 0;
virtual GpStatus SaveAdd( GpImage* newBits, const EncoderParameters* encoderParams ) = 0;
// Dispose of the image object
virtual VOID Dispose() = 0;
// Derive a graphics context to draw into the GpImage object
virtual GpGraphics* GetGraphicsContext() = 0;
// Check if the GpImage object is valid
virtual BOOL IsValid() const { return GpObject::IsValid(ObjectTagImage); }
virtual BOOL IsSolid() { return FALSE; }
virtual BOOL IsOpaque() { return FALSE; }
// Get image information:
// resolution
// physical dimension in 0.01mm units
// bounding rectangle
// structure ImageInfo
// thumbnail
virtual GpStatus GetResolution(REAL* xdpi, REAL* ydpi) const = 0; virtual GpStatus GetPhysicalDimension(REAL* width, REAL* height) const = 0; virtual GpStatus GetBounds(GpRectF* rect, GpPageUnit* unit) const = 0; virtual GpStatus GetImageInfo(ImageInfo *imageInfo) const = 0; virtual GpStatus GetFrameCount(const GUID* dimensionID, UINT* count) const = 0; virtual GpStatus GetFrameDimensionsCount(OUT UINT* count) const = 0; virtual GpStatus GetFrameDimensionsList(OUT GUID* dimensionIDs, IN UINT count) const = 0; virtual GpStatus SelectActiveFrame(const GUID* dimensionID, UINT frameIndex) = 0; virtual GpImage* GetThumbnail(UINT thumbWidth, UINT thumbHeight, GetThumbnailImageAbort callback, VOID *callbackData) = 0; virtual GpStatus GetPalette(ColorPalette *palette, INT size) = 0; virtual GpStatus SetPalette(ColorPalette *palette) = 0; virtual INT GetPaletteSize() = 0;
// Rotate and Flip
virtual GpStatus RotateFlip(RotateFlipType rfType) = 0;
// Property related functions
virtual GpStatus GetPropertyCount(UINT* numOfProperty) = 0; virtual GpStatus GetPropertyIdList(UINT numOfProperty, PROPID* list) = 0; virtual GpStatus GetPropertyItemSize(PROPID propId, UINT* size) = 0; virtual GpStatus GetPropertyItem(PROPID propId,UINT propSize, PropertyItem* buffer) = 0; virtual GpStatus GetPropertySize(UINT* totalBufferSize, UINT* numProperties) = 0; virtual GpStatus GetAllPropertyItems(UINT totalBufferSize, UINT numProperties, PropertyItem* allItems) = 0; virtual GpStatus RemovePropertyItem(PROPID propId) = 0;
virtual GpStatus SetPropertyItem(PropertyItem* item) = 0;
// Determine the type of image object
GpImageType GetImageType() const { return ImgType; }
GpLockable* GetObjectLock() const { return &Lockable; }
// Default ICM mode is off. Default behaviour for this function is to
// do nothing.
// If a derived class supports embedded color correction, it needs
// to respect this call to turn ICM on or off.
virtual VOID SetICMConvert(BOOL icm) { }
private:
// Prevent apps from directly using new and delete operators
// on GpImage objects.
GpImage() { ImgType = ImageTypeUnknown;
// Set the tag in the object, even if IsValid overridden by
// GpBitmap or GpMetafile.
GpObject::SetValid(ObjectTagImage); }
protected:
GpImage(GpImageType imgType) { ImgType = imgType;
// Set the tag in the object, even if IsValid overridden by
// GpBitmap or GpMetafile.
GpObject::SetValid(ObjectTagImage); }
virtual ~GpImage() {}
GpImageType ImgType; // type of image object
// Object lock
mutable GpLockable Lockable; };
//--------------------------------------------------------------------------
// Represent raster bitmap objects
//--------------------------------------------------------------------------
class GpDecodedImage; class GpMemoryBitmap; class CopyOnWriteBitmap;
class GpBitmap : public GpImage { friend class GpObject; // for empty constructor
friend class CopyOnWriteBitmap;
private:
CopyOnWriteBitmap * InternalBitmap; LONG ScanBitmapRef; // ref count used for when a GpGraphics is wrapped around a GpBitmap
EpScanBitmap ScanBitmap;
VOID IncScanBitmapRef() { InterlockedIncrement(&ScanBitmapRef); }
VOID DecScanBitmapRef() { InterlockedDecrement(&ScanBitmapRef); }
GpBitmap(BOOL createInternalBitmap = TRUE); GpBitmap(const GpBitmap * bitmap); GpBitmap(const CopyOnWriteBitmap * internalBitmap);
// Destructor
// We don't want apps to use delete operator directly.
// Instead, they should use the Dispose method.
virtual ~GpBitmap();
protected:
CopyOnWriteBitmap * LockForWrite(); VOID Unlock() const; VOID LockForRead() const;
public:
// Constructors
GpBitmap(const WCHAR* filename); GpBitmap(IStream* stream); GpBitmap(INT width, INT height, PixelFormatID format); GpBitmap(INT width, INT height, PixelFormatID format, GpGraphics * graphics); GpBitmap( INT width, INT height, INT stride, // negative for bottom-up bitmaps
PixelFormatID format, BYTE * scan0 ); GpBitmap( BITMAPINFO* gdiBitmapInfo, VOID* gdiBitmapData, BOOL ownBitmapData ); GpBitmap(IDirectDrawSurface7 *surface);
// Check if the GpBitmap object is valid
virtual BOOL IsValid() const;
GpImage* Clone() const;
GpBitmap* Clone( const GpRect* rect, PixelFormatID format = PixelFormat32bppPARGB ) const;
virtual GpImage* CloneColorAdjusted( GpRecolor * recolor, ColorAdjustType type = ColorAdjustTypeDefault ) const;
// Similar to CloneColorAdjusted
GpStatus Recolor( GpRecolor *recolor, GpBitmap **dstBitmap, DrawImageAbort callback, VOID *callbackData, GpRect *rect = NULL );
GpStatus GetEncoderParameterListSize( IN CLSID* clsidEncoder, OUT UINT* size );
GpStatus GetEncoderParameterList( IN CLSID* clsidEncoder, IN UINT size, OUT EncoderParameters* pBuffer );
GpStatus SaveToStream( IStream* stream, CLSID* clsidEncoder, EncoderParameters* encoderParams );
GpStatus SaveToFile( const WCHAR* filename, CLSID* clsidEncoder, EncoderParameters* encoderParams );
GpStatus SaveAdd( const EncoderParameters* encoderParams );
GpStatus SaveAdd( GpImage* newBits, const EncoderParameters* encoderParams );
// Dispose the bitmap object
VOID Dispose();
// Get bitmap information
virtual GpStatus GetResolution(REAL* xdpi, REAL* ydpi) const; virtual GpStatus GetPhysicalDimension(REAL* width, REAL* height) const; virtual GpStatus GetBounds(GpRectF* rect, GpPageUnit* unit) const; virtual GpStatus GetSize(Size* size) const; virtual GpStatus GetImageInfo(ImageInfo *imageInfo) const; virtual GpImage* GetThumbnail(UINT thumbWidth, UINT thumbHeight, GetThumbnailImageAbort callback, VOID *callbackData); virtual GpStatus GetFrameCount(const GUID* dimensionID, UINT* count) const; virtual GpStatus GetFrameDimensionsCount(OUT UINT* count) const; virtual GpStatus GetFrameDimensionsList(OUT GUID* dimensionIDs, IN UINT count) const; virtual GpStatus SelectActiveFrame(const GUID* dimensionID, UINT frameIndex); virtual GpStatus GetPalette(ColorPalette *palette, INT size); virtual GpStatus SetPalette(ColorPalette *palette); virtual INT GetPaletteSize();
GpStatus GetTransparencyHint(DpTransparency* transparency); GpStatus SetTransparencyHint(DpTransparency transparency);
GpStatus GetTransparencyFlags(DpTransparency* transparency, PixelFormatID loadFormat = PixelFormatDontCare, BYTE* minAlpha = NULL, BYTE* maxAlpha = NULL);
// Property related functions
virtual GpStatus GetPropertyCount(UINT* numOfProperty); virtual GpStatus GetPropertyIdList(UINT numOfProperty, PROPID* list); virtual GpStatus GetPropertyItemSize(PROPID propId, UINT* size); virtual GpStatus GetPropertyItem(PROPID propId,UINT propSize, PropertyItem* buffer); virtual GpStatus GetPropertySize(UINT* totalBufferSize,UINT* numProperties); virtual GpStatus GetAllPropertyItems(UINT totalBufferSize, UINT numProperties, PropertyItem* allItems); virtual GpStatus RemovePropertyItem(PROPID propId); virtual GpStatus SetPropertyItem(PropertyItem* item);
// Retrieve bitmap data
GpStatus LockBits( const GpRect* rect, UINT flags, PixelFormatID pixelFormat, BitmapData* bmpdata, INT width = 0, INT height = 0 ) const;
GpStatus UnlockBits( BitmapData* bmpdata, BOOL Destroy=FALSE ) const;
// Flush batched drawing operations and optionally wait for drawing to
// complete. This is currently a nop operation. If the behavior
// of a GpBitmap changes to a model where rendering operations are
// non-immediate then this routine will need to be implemented.
VOID Flush(GpFlushIntention intention) {};
// Get and set pixel on the bitmap.
GpStatus GetPixel(INT x, INT y, ARGB *color); GpStatus SetPixel(INT x, INT y, ARGB color);
// Rotate and Flip
GpStatus RotateFlip( RotateFlipType rfType );
// Derive a graphics context on top of the bitmap object
GpGraphics* GetGraphicsContext();
GpStatus GpBitmap::InitializeSurfaceForGdipBitmap( DpBitmap * surface, INT width, INT height );
// Derive an HDC for interop on top of the bitmap object
HDC GetHdc(); VOID ReleaseHdc(HDC hdc);
// Serialization
virtual UINT GetDataSize() const; virtual GpStatus GetData(IStream * stream) const; virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
GpStatus GetCompressedData( DpCompressedData * compressed_data, BOOL getJPEG = TRUE, BOOL getPNG = TRUE, HDC hdc = (HDC)NULL);
GpStatus DeleteCompressedData( DpCompressedData * compressed_data);
BOOL IsDirty() const;
// Color adjust
virtual GpStatus ColorAdjust( GpRecolor * recolor, ColorAdjustType type );
GpStatus ColorAdjust( GpRecolor * recolor, PixelFormatID pixfmt, DrawImageAbort callback, VOID *callbackData );
GpStatus GetPixelFormatID(PixelFormatID* pixfmt);
enum { Invalid = 0, // bitmap object is invalid
ImageRef = 1, // contains a reference only (e.g. filename)
ExtStream = 2, // contains a reference to a stream
DecodedImg = 3, // contains a decoded image object,
// but it's not decoded yet - name is misleading.
MemBitmap = 4 // contains an in-memory bitmap object
};
INT GetDecodeState();
GpStatus ForceValidation();
GpStatus SetResolution(REAL xdpi, REAL ydpi);
GpStatus PreDraw( INT numPoints, GpPointF *dstPoints, GpRectF *srcRect, INT numBitsPerPixel );
DWORD GetUniqueness() { return (DWORD)GetUid(); }
// Interop:
static GpStatus CreateFromHBITMAP( HBITMAP hbm, HPALETTE hpal, GpBitmap** bitmap );
static GpStatus CreateBitmapAndFillWithBrush( InterpolationMode interpolationMode, PixelOffsetMode pixelOffsetMode, const GpMatrix * worldToDevice, const GpRect * drawBounds, GpBrush * brush, GpBitmap ** bitmap, PixelFormatID pixelFormat = PIXFMT_32BPP_ARGB );
static GpStatus DrawAndHalftoneForStretchBlt( HDC hdc, BITMAPINFO * bmpInfo, BYTE * bits, INT srcX, INT srcY, INT srcWidth, INT srcHeight, INT destWidth, INT destHeight, BITMAPINFO ** destBmpInfo, BYTE ** destBmpBits, HBITMAP * destDIBSection, InterpolationMode interpolationMode );
GpStatus CreateHBITMAP(HBITMAP *phbm, ARGB background);
GpStatus ICMFrontEnd( GpBitmap **dstBitmap, DrawImageAbort callback, VOID *callbackData, GpRect *rect = NULL );
static GpStatus CreateFromHICON( HICON hicon, GpBitmap** bitmap );
GpStatus CreateHICON(HICON *phicon);
static GpStatus CreateFromResource( HINSTANCE hInstance, LPWSTR lpBitmapName, GpBitmap** bitmap );
// We need to know if the bitmap is associated with a display
// so we know how to handle the page transform when it is
// set to UnitDisplay.
BOOL IsDisplay() const; VOID SetDisplay(BOOL display);
BOOL IsICMConvert() const; virtual VOID SetICMConvert(BOOL icm); };
// This is the base class for any class that implements the CopyOnWrite
// technology that enable cloning to be very light-weight when cloning for
// read access. It implements read and write locking for synchronization
// using a critical section, and it keeps track of reference counting
// the object so that it can be deleted at the right time.
class CopyOnWrite { protected: // Constructor: notice that when an object is first
// created, its reference count is set to 1.
CopyOnWrite() { RefCount = 1; #if DBG
Lock = NotLocked; LockCount = 0; #endif
InitializeCriticalSection(&Semaphore); }
virtual ~CopyOnWrite() { DeleteCriticalSection(&Semaphore); }
#if DBG
enum LockedType { NotLocked, LockedForRead, LockedForWrite }; #endif
virtual CopyOnWrite * Clone() const = 0; virtual BOOL IsValid() const = 0;
// Returns NULL if it fails to lock for writing
CopyOnWrite * LockForWrite() { EnterCriticalSection(&Semaphore);
CopyOnWrite * writeableObject = this;
// If there is more than one reference to this object, we must
// clone it before giving write access to it.
if (RefCount > 1) { writeableObject = this->Clone();
if (writeableObject == NULL) { LeaveCriticalSection(&Semaphore); return NULL; }
ASSERT(writeableObject->IsValid());
// else we succeeded in cloning the object
RefCount--;
EnterCriticalSection(&(writeableObject->Semaphore)); LeaveCriticalSection(&Semaphore); }
#if DBG
writeableObject->Lock = LockedForWrite; writeableObject->LockCount++; #endif
return writeableObject; }
VOID LockForRead() const { EnterCriticalSection(&Semaphore);
#if DBG
if (Lock == NotLocked) { Lock = LockedForRead; } LockCount++; #endif
}
VOID Unlock() const { #if DBG
ASSERT(Lock != NotLocked); if (--LockCount <= 0) { Lock = NotLocked; LockCount = 0; } #endif
LeaveCriticalSection(&Semaphore); }
// Increment reference count
// Note that we must use the critical section to control access, rather
// than using interlocked increment.
LONG AddRef() const { EnterCriticalSection(&Semaphore); RefCount++; LeaveCriticalSection(&Semaphore); return RefCount; }
// Decrement reference count
// Note that we must use the critical section to control access, rather
// than using interlocked decrement.
LONG Release() const { EnterCriticalSection(&Semaphore);
ULONG count = --RefCount;
// must leave the critical section before calling delete so that
// we don't try to access the freed memory.
LeaveCriticalSection(&Semaphore);
if (count == 0) { delete this; }
return count; }
private:
mutable LONG RefCount; mutable CRITICAL_SECTION Semaphore;
#if DBG
mutable INT LockCount; protected: mutable LockedType Lock; #endif
};
GpStatus ConvertTo16BppAndFlip( GpBitmap * sourceBitmap, GpBitmap * & destBitmap );
VOID HalftoneColorRef_216( COLORREF color, // color to halftone
UNALIGNED VOID *dib // packed 8 bpp DIB buffer with 8 colors
// The DIB buffer should be this size:
// sizeof(BITMAPINFOHEADER) + // DIB 8 bpp header
// (8 * sizeof(RGBQUAD)) + // DIB 8 colors
// (8 * 8) // DIB 8x8 pixels
);
#endif // !_GPBITMAP_HPP
|