00001 /// \file CATImage.h 00002 /// \brief PNG image class 00003 /// \ingroup CAT 00004 /// 00005 /// Copyright (c) 2003-2008 by Michael Ellison. 00006 /// See COPYING.txt for the \ref gaslicense License (MIT License). 00007 /// 00008 // $Author: mikeellison $ 00009 // $Date: 2008-01-21 08:33:12 -0600 (Mon, 21 Jan 2008) $ 00010 // $Revision: $ 00011 // $NoKeywords: $ 00012 // 00013 #ifndef _CATImage_H_ 00014 #define _CATImage_H_ 00015 00016 #include "CATInternal.h" 00017 #include "CATStream.h" 00018 #include "CATColor.h" 00019 #include "CATRect.h" 00020 #include "png.h" 00021 00022 /// \class CATImage 00023 /// \brief Base image class 00024 /// \ingroup CAT 00025 /// 00026 /// All images are 32-bit R,G,B,A. This interface provides the basics 00027 /// needed for working with the images. 00028 /// 00029 /// Note: Alpha channels are stored where 255 means opaque, and 00030 /// 0 is totally translucent. Make sure to set this when 00031 /// loading / building images. 00032 /// 00033 class CATImage 00034 { 00035 public: 00036 /// Eventually, this may specify file format. 00037 /// 00038 /// Currently, we only support PNG with RGB/Alpha channels. 00039 enum CATIMAGEFORMAT 00040 { 00041 CATIMAGE_PNG_RGBA32 00042 }; 00043 00044 /// Load() loads an image from a file. 00045 /// 00046 /// Currently, only .PNG is supported. Images are converted 00047 /// into 32-bit RGBA (8-bits per channel) 00048 /// 00049 /// Call CATImage::ReleaseImage() when done with the returned image. 00050 /// 00051 /// \param stream - an opened stream to load the image from. 00052 /// The stream should be positioned at the 00053 /// start of the image. 00054 /// 00055 /// \param image - image ref set to image from stream on success. 00056 /// \return CATResult - CAT_SUCCESS on success. 00057 static CATResult Load ( CATStream* stream, 00058 CATImage*& image); 00059 00060 /// Save() saves an image to a .png file. 00061 /// 00062 /// Currently, only .PNG format is supported. Images are 00063 /// saved as 32-bit RGBA (8-bits per channel). 00064 /// 00065 /// \param stream - an opened stream to save the image to. 00066 /// The stream should be positioned to the location 00067 /// to save the image to, and it must be writeable. 00068 /// 00069 /// \param image - ptr to image to save. 00070 /// \param imageFormat - right now, doesn't do anything. Should 00071 /// always be CATIMAGE_PNG_RGBA32. 00072 /// 00073 /// \return CATResult - CAT_SUCCESS on success. 00074 static CATResult Save( CATStream* stream, 00075 CATImage* image, 00076 CATIMAGEFORMAT imageFormat = CATIMAGE_PNG_RGBA32); 00077 00078 static CATResult Save( const CATWChar* filename, 00079 CATImage* image); 00080 00081 /// CreateImage() creates an image. 00082 /// 00083 /// Use this instead of new to create image objects. 00084 /// If width and height are non-zero, creates the appropriate memory for 00085 /// the image and adds a reference. Otherwise, does not create memory 00086 /// buffer or add reference. 00087 /// 00088 /// Call CATImage::ReleaseImage() on the returned image when done. 00089 /// 00090 /// \param image - uninitialized image ptr. Set on return. 00091 /// \param width - desired width of image in pixels. 00092 /// \param height - desired height of image in pixels. 00093 /// \param init - if true, image data is set to 0. 00094 /// \param transparent - if false, sets all alpha channels 00095 /// to 255 (opaque). Otherwise, sets the 00096 /// alpha channels to 0 (transparent). 00097 /// Ignored if init == false. 00098 /// 00099 /// \return CATResult result code 00100 /// \sa CATImage::ReleaseImage() 00101 static CATResult CreateImage ( CATImage*& image, 00102 CATInt32 width, 00103 CATInt32 height, 00104 bool init = true, 00105 bool transparent = true); 00106 00107 00108 static CATResult CreateImageFromDIB( CATImage*& image, 00109 HBITMAP dibSection); 00110 00111 /// ReleaseImage decrements the reference count of an image and 00112 /// will free the image if it hits zero. 00113 /// It may also free parent images if the specified 00114 /// image holds the last reference to a parent. 00115 /// 00116 /// \param image - pointer to image to release. Is set to NULL 00117 /// if last reference was deleted. 00118 /// 00119 /// \return CATResult result code 00120 /// \sa CATImage::CreateImage() 00121 static CATResult ReleaseImage ( CATImage*& image ); 00122 00123 00124 /// CreateSub creates a sub-image of the specified parent. 00125 /// 00126 /// dstImage should not be instantiated prior to calling CreateSub. 00127 /// Sub image is returned in dstImage. 00128 /// 00129 /// The sub image references the parent's fData 00130 /// member, and the parent image must not be deleted before you 00131 /// are done using the sub image. 00132 /// 00133 /// You may create a sub image of a sub image, ad infinum. It'll 00134 /// handle the offsets. Call CATImage::ReleaseImage() when done. 00135 /// 00136 /// \param orgImg - parent image to derive subimage from. 00137 /// \param dstImg - uninitialized image ptr. Set on return. 00138 /// \param xOffset - relative x offset for top-left of sub image. 00139 /// \param yOffset - relative y offset for top-left of sub image. 00140 /// \param width - width of sub image. 00141 /// \param height - height of sub image. 00142 /// 00143 /// \return CATResult result code 00144 /// \sa CATImage::ReleaseImage() 00145 /// \sa CATImage::SetSubPosition() 00146 static CATResult CreateSub ( const CATImage* orgImg, 00147 CATImage*& dstImg, 00148 CATInt32 xOffset, 00149 CATInt32 yOffset, 00150 CATInt32 width, 00151 CATInt32 height); 00152 00153 /// CopyImage() creates a new image and stores it in dstImg. 00154 /// The data from srcImg is copied into a buffer owned by 00155 /// dstImg. 00156 /// 00157 /// Caller must call CATImage::ReleaseImage() on the returned 00158 /// image when done. 00159 /// 00160 /// \param srcImg - source image to copy from 00161 /// \param dstImg - uninitizlied image ptr. Contains copy 00162 /// of srcImg on return. 00163 /// 00164 /// \return CATResult result code 00165 /// \sa CATImage::ReleaseImage() 00166 static CATResult CopyImage ( const CATImage* srcImg, 00167 CATImage*& dstImg); 00168 00169 /// CopyImage() creates a new image of the same type as srcImg 00170 /// and stores it in dstImg. The data from srcImg is 00171 /// copied into a buffer owned by dstImg. 00172 /// 00173 /// Caller must call CATImage::ReleaseImage() on the returned 00174 /// image when done. 00175 /// 00176 /// This version allows you to specify offsets, width, and 00177 /// height of the data to copy into a new image. 00178 /// 00179 /// \param srcImg - source image to copy from 00180 /// \param dstImg - uninitialized image ptr. Contains copy 00181 /// of srcImg on return. 00182 /// \param xOffset - relative x offset for top-left of copy. 00183 /// \param yOffset - relative y offset for top-left of copy. 00184 /// \param width - width of destination image. 00185 /// \param height - height of destination image. 00186 /// 00187 /// \return CATResult result code 00188 /// \sa CATImage::ReleaseImage() 00189 static CATResult CopyImage ( const CATImage* srcImg, 00190 CATImage*& dstImg, 00191 CATInt32 xOffset, 00192 CATInt32 yOffset, 00193 CATInt32 width, 00194 CATInt32 height); 00195 00196 /// CopyOver() copies from another image over the current image 00197 /// at the specified offsets for the specified width and height. 00198 /// 00199 /// If no width/height parameters are given, the entire width 00200 /// and/or height are used. 00201 /// 00202 /// Clipping is not performed. However, if the copy would go out 00203 /// of bounds, an error will be returned and the copy will not 00204 /// be performed. 00205 /// 00206 /// \param srcImg - source image to copy from 00207 /// \param dstOffsetX - x offset in dest image to copy to 00208 /// \param dstOffsetY - y offset in dest image to copy to 00209 /// \param srcOffsetX - x offset in src image to copy from 00210 /// \param srcOffsetY - y offset in src image to copy from 00211 /// \param width - width to copy in 00212 /// \param height - height to copy in 00213 /// \return CATResult - CAT_SUCCESS on success. 00214 CATResult CopyOver ( const CATImage* srcImg, 00215 CATInt32 dstOffsetX, 00216 CATInt32 dstOffsetY, 00217 CATInt32 srcOffsetX, 00218 CATInt32 srcOffsetY, 00219 CATInt32 width = 0, 00220 CATInt32 height = 0); 00221 00222 /// CopyOutBGR() copies the RGB data from a rectangle 00223 /// into a buffer and flips the Red and Blue channels. 00224 /// The buffer must be width*height*3 00225 /// bytes in size. 00226 /// 00227 /// \param rgbBuf - raw rgb buffer of width/height size 00228 /// \param offsetX - x offset to copy from 00229 /// \param offsetY - y offset to copy from 00230 /// \param width - width to copy 00231 /// \param height - height to copy 00232 /// \param widthBytes - width of line in bytes (w/pad) 00233 /// \return CATResult - CAT_SUCCESS on success. 00234 CATResult CopyOutBGR ( CATUInt8* rgbBuf, 00235 CATInt32 offsetX, 00236 CATInt32 offsetY, 00237 CATInt32 width, 00238 CATInt32 height, 00239 CATInt32 widthBytes); 00240 00241 /// Overlay() merges from another image over the current image 00242 /// at the specified offsets for the specified width and height. 00243 /// 00244 /// If no width/height parameters are given, the entire width 00245 /// and/or height are used. 00246 /// 00247 /// Clipping is not performed. However, if the copy would go out 00248 /// of bounds, an error will be returned and the copy will not 00249 /// be performed. 00250 /// 00251 /// The alpha channel is used for the merge operation from the 00252 /// source image only. The destination's alpha remains 00253 /// unaffected - the alpha is used for merging the colors only. 00254 /// 00255 /// \param srcImg - source image to copy from 00256 /// \param dstOffsetX - offset in dest image to copy to 00257 /// \param dstOffsetY - offset in dest image to copy to 00258 /// \param srcOffsetX - offset in src image to copy from 00259 /// \param srcOffsetY - offset in src image to copy from 00260 /// \param width - width to copy in 00261 /// \param height - height to copy in 00262 /// \return CATResult - CAT_SUCCESS on success. 00263 CATResult Overlay( const CATImage* srcImg, 00264 CATInt32 dstOffsetX, 00265 CATInt32 dstOffsetY, 00266 CATInt32 srcOffsetX, 00267 CATInt32 srcOffsetY, 00268 CATInt32 width = 0, 00269 CATInt32 height = 0); 00270 00271 00272 /// GetPixel() retrieves the red, green, blue, and alpha values for a 00273 /// specified pixel. 00274 /// 00275 /// This is for convenience and prototyping - for high-speed image 00276 /// processing you'll need to work more directly with the image 00277 /// buffer. 00278 /// 00279 /// \param x - x position within the image of the pixel 00280 /// \param y - y position within the image of the pixel 00281 /// \param r - receives the red value of the pixel 00282 /// \param g - receives the green value of the pixel 00283 /// \param b - receives the blue value of the pixel 00284 /// \param a - receives the alpha values of the pixel 00285 /// 00286 /// \return CATResult result code. CAT_SUCCESS on success. 00287 /// \sa SetPixel() 00288 CATResult GetPixel(CATInt32 x, 00289 CATInt32 y, 00290 unsigned char& r, 00291 unsigned char& g, 00292 unsigned char& b, 00293 unsigned char& a) const; 00294 00295 /// GetPixel() retrieves the red, green, blue, and alpha values for a 00296 /// specified pixel. 00297 /// 00298 /// This is for convenience and prototyping - for high-speed image 00299 /// processing you'll need to work more directly with the image 00300 /// buffer. 00301 /// 00302 /// \param x - x position within the image of the pixel 00303 /// \param y - y position within the image of the pixel 00304 /// \param color - receives the color of the pixel 00305 /// 00306 /// \return CATResult result code. CAT_SUCCESS on success. 00307 /// \sa SetPixel() 00308 CATResult GetPixel( CATInt32 x, 00309 CATInt32 y, 00310 CATColor& color) const; 00311 00312 /// SetPixel() sets the red, green, blue, and alpha values for a 00313 /// specified pixel. 00314 /// 00315 /// This is for convenience and prototyping - for high-speed image 00316 /// processing you'll need to work more directly with the image 00317 /// buffer. 00318 /// 00319 /// \param x - x position within the image of the pixel 00320 /// \param y - y position within the image of the pixel 00321 /// \param r - red value of the pixel 00322 /// \param g - green value of the pixel 00323 /// \param b - blue value of the pixel 00324 /// \param a - alpha value of the pixel (255 = opaque, 0 = transparent) 00325 /// 00326 /// \return CATResult result code. CAT_SUCCESS on success. 00327 /// \sa GetPixel() 00328 CATResult SetPixel ( CATInt32 x, 00329 CATInt32 y, 00330 unsigned char r, 00331 unsigned char g, 00332 unsigned char b, 00333 unsigned char a = 255); 00334 00335 /// SetPixel() sets the red, green, blue, and alpha values for a 00336 /// specified pixel. 00337 /// 00338 /// This is for convenience and prototyping - for high-speed image 00339 /// processing you'll need to work more directly with the image 00340 /// buffer. 00341 /// 00342 /// \param x - x position within the image of the pixel 00343 /// \param y - y position within the image of the pixel 00344 /// \param color - color to set pixel to 00345 /// 00346 /// \return CATResult result code. CAT_SUCCESS on success. 00347 /// \sa GetPixel() 00348 CATResult SetPixel ( CATInt32 x, 00349 CATInt32 y, 00350 const CATColor& color); 00351 00352 /// Clear() sets all the pixels in the image to 0. 00353 /// 00354 /// \param transparent - if false, sets all alpha channels 00355 /// to 255 (opaque). Otherwise, sets the 00356 /// alpha channels to 0 (transparent). 00357 /// 00358 /// \return CATResult result code. 00359 CATResult Clear(bool transparent = true); 00360 00361 /// FillRect() fills an area to a specific color. 00362 /// 00363 /// \param rect - rectangle to fill 00364 /// \param color - color to fill to 00365 /// \return CATResult - CAT_SUCCESS on success. 00366 CATResult FillRect(const CATRect& rect, const CATColor& color); 00367 00368 /// SetSubPosition() moves the ROI of the image within its parent. 00369 /// Will return CAT_ERR_IMAGE_OPERATION_INVALID_ON_ROOT if you try 00370 /// to use this on a root image instead of a sub image. 00371 /// 00372 /// \param newXOffset - relative x offset of new pos within parent. 00373 /// \param newYOffset - relative y offset of new pos within parent. 00374 /// \param newWidth - new width of sub image. 00375 /// \param newHeight - new height of sub image. 00376 /// 00377 /// \return CATResult result code. 00378 /// \sa CATImage::CreateSub() 00379 CATResult SetSubPosition ( CATInt32 newXOffset, 00380 CATInt32 newYOffset, 00381 CATInt32 newWidth, 00382 CATInt32 newHeight ); 00383 00384 /// GetRawDataPtr() retrieves the image data ptr. 00385 /// 00386 /// Remember that this may be a sub image, in which case the data ptr 00387 /// returned is to the raw buffer of a parent image. 00388 /// 00389 /// So, any time you access the raw data you should use the 00390 /// XOffsetAbs, YOffsetAbs, AbsWidth, and AbsHeight functions 00391 /// when calculating your pointers into the data. 00392 /// 00393 /// Also remember that if you modify a sub image, you'll be modifying 00394 /// the parent image and any other overlapping sub images. If you 00395 /// want to muck with an image without messing up any others, use 00396 /// CATImage::CopyImage() first to get a base image that owns its own 00397 /// data. 00398 /// 00399 /// Note that the xOffset and yOffset are relative to parent. They will 00400 /// be calculated at runtime if you call this function. 00401 /// 00402 /// \return unsigned char* to image data 00403 unsigned char* GetRawDataPtr() const; 00404 00405 /// Returns relative offset within parent image. 00406 /// \return CATInt32 - X Offset relative to parent. 00407 CATInt32 XOffsetRel () const; 00408 00409 /// Returns relative offset within parent image. 00410 /// \return CATInt32 - Y Offset relative to parent. 00411 CATInt32 YOffsetRel () const; 00412 00413 /// Returns absolute X offset within fData. 00414 /// \return CATInt32 - Absolute x offset of current image within root 00415 CATInt32 XOffsetAbs () const; 00416 00417 /// Returns absolute Y offset within fData. 00418 /// \return CATInt32 - Absolute y offset of current image within root 00419 CATInt32 YOffsetAbs () const; 00420 00421 /// Returns the absolute width of the fData image buffer. 00422 /// \return CATInt32 - Absolute width of root image 00423 CATInt32 AbsWidth () const; 00424 00425 /// Returns the absolute height of the fData image buffer. 00426 /// \return CATInt32 - Absolute height of root image 00427 CATInt32 AbsHeight () const; 00428 00429 /// Returns width of image in pixels. 00430 /// \return CATInt32 - Width of image 00431 CATInt32 Width () const; 00432 00433 /// Returns height of image in pixels. 00434 /// \return CATInt32 - Height of image 00435 CATInt32 Height () const; 00436 00437 /// Returns size of image buffer in bytes. 00438 /// \return CATInt32 - Size of image in bytes 00439 CATInt32 Size () const; 00440 00441 /// Returns absolute size of parent image. 00442 /// \return CATInt32 - Absolute size of root image in bytes. 00443 CATInt32 AbsSize () const; 00444 00445 /// IsImageRoot() returns true if the image is a root (parent) 00446 /// image that owns its own data. If the image is a sub image, 00447 /// it returns false. 00448 /// 00449 /// \return bool - true if the image is a root (without a parent), 00450 /// or fase otherwise. 00451 bool IsImageRoot () const; 00452 00453 /// AddRef increments our reference count and calls 00454 /// AddRef on our parent if one exists. 00455 /// \return long - current reference count 00456 unsigned long AddRef(); 00457 00458 /// DecRef decrements our reference count and calls 00459 /// ReleaseImage() on our parent if one exists. 00460 /// \return long - current reference count 00461 unsigned long DecRef(); 00462 00463 /// GetRefCount() retrieves the current reference 00464 /// count 00465 /// return unsigned long - current reference count 00466 /// \sa AddRef(), DecRef() 00467 unsigned long GetRefCount(); 00468 00469 // Debugging func for saving image to disk as a .png 00470 CATResult DbgSave ( const CATWChar* filename ); 00471 00472 protected: 00473 /// Constructor for CATImage - use CATImage::CreateImage() or similar 00474 /// static functions instead! 00475 /// 00476 CATImage (); 00477 00478 /// Destructor for CATImage - use CATImage::ReleaseImage() 00479 virtual ~CATImage(); 00480 00481 /// operator= is overridden to generate an error if someone 00482 /// attempts to use it - Don't use it! 00483 /// Use CreateCopy() or CreateSub() instead depending on whether you 00484 /// want a deep or shallow copy of the object. 00485 CATImage& operator=(const CATImage& img); 00486 00487 /// Create - internal image creation function. 00488 /// Creates the buffer and sets it up, then calls AddRef(). 00489 /// 00490 /// \param width - width of image in pixels. 00491 /// \param height - height of image in pixels. 00492 /// \param init - if true, initializes image pixels to 0. 00493 /// \param transparent - if false, sets all alpha channels 00494 /// to 255 (opaque). Otherwise, sets the 00495 /// alpha channels to 0 (transparent). 00496 /// Ignored if init == false. 00497 /// 00498 /// \return CATResult result code. 00499 /// \sa ::CATResult_CORE_ENUM, ::CATResult_IMAGE_ENUM 00500 CATResult Create ( CATInt32 width, 00501 CATInt32 height, 00502 bool init, 00503 bool transparent); 00504 00505 //--------------------------------------------------------------------- 00506 // PNG callbacks 00507 00508 /// PNGRead() reads from the current stream into the buffer 00509 /// provided by libpng. 00510 /// 00511 /// You shouldn't need to call this directly - these are called 00512 /// by libpng only. 00513 /// 00514 /// \param png_ptr - structure for the .png library. The CATStream* 00515 /// for the current stream is in png_ptr->io_ptr. 00516 /// \param data - target buffer 00517 /// \param length - number of bytes to read. 00518 /// \return none. Throws a CATRESULT on error. 00519 /// \sa Load() 00520 static void PNGRead( png_structp png_ptr, 00521 png_bytep data, 00522 png_size_t length); 00523 00524 00525 /// PNGWrite() writes to the current stream from the buffer 00526 /// provided by libpng. 00527 /// 00528 /// You shouldn't need to call this directly - these are called 00529 /// by libpng only. 00530 /// 00531 /// \param png_ptr - structure for the .png library. The CATStream* 00532 /// for the current stream is in png_ptr->io_ptr. 00533 /// \param data - source buffer 00534 /// \param length - number of bytes to write. 00535 /// \return none. Throws a CATRESULT on error. 00536 /// \sa Save() 00537 static void PNGWrite( png_structp png_ptr, 00538 png_bytep data, 00539 png_size_t length); 00540 00541 00542 /// PNGFlush() flushes the current stream for libpng. 00543 /// 00544 /// You shouldn't need to call this directly - these are called 00545 /// by libpng only. 00546 /// 00547 /// \param png_ptr - structure for the .png library. The CATStream* 00548 /// for the current stream is in png_ptr->io_ptr. 00549 /// \return none. Throws a CATRESULT on error. 00550 /// \sa Load(), Save() 00551 static void PNGFlush( png_structp png_ptr); 00552 00553 /// PNGError() is called by libpng when a fatal error occurs. 00554 /// 00555 /// This just throws a CATResult when called. 00556 /// 00557 /// \param png_ptr - structure for .png lib. 00558 /// \param error_msg - ASCIIZ message reporting the error. 00559 static void PNGError( png_structp png_ptr, 00560 png_const_charp error_msg); 00561 00562 /// PNGWarning() is called by libpng when a recoverable error occurs. 00563 /// 00564 /// This just throws a CATResult when called. 00565 /// 00566 /// \param png_ptr - structure for .png lib. 00567 /// \param warning_msg - ASCIIZ message reporting the warning. 00568 static void PNGWarning( png_structp png_ptr, 00569 png_const_charp warning_msg); 00570 00571 00572 00573 00574 //--------------------------------------------------------------------- 00575 private: 00576 00577 // Basic image information 00578 CATInt32 fWidth; ///< Width in pixels. 00579 00580 CATInt32 fHeight; ///< Height in pixels. 00581 00582 CATUInt8* fData; ///< Image data. 00583 ///< This may be a pointer to the parent 00584 ///< image's buffer. Remember to use 00585 ///< offsets. 00586 // SubImage/ROI information 00587 CATInt32 fXOffset; ///< X Offset within parent image. 00588 ///< To find offset within fData, 00589 ///< call XOffsetAbs(). 00590 00591 CATInt32 fYOffset; ///< Y Offset within parent image. 00592 ///< To find offset within fData, 00593 ///< call YOffsetAbs(). 00594 00595 bool fOwnData; ///< Set to true if we own image data. 00596 ///< (i.e. are we the parent?) 00597 00598 CATUInt32 fRefCount; ///< Ref count - inc for each sub image. 00599 00600 CATImage* fParentImage; ///< Parent image - so we can decrement 00601 ///< ref count on destruction. 00602 }; 00603 00604 #endif // _CATImage_H_