#ifndef __DW_IMGBUF_HH__ #define __DW_IMGBUF_HH__ #ifndef __INCLUDED_FROM_DW_CORE_HH__ # error Do not include this file directly, use "core.hh" instead. #endif #include "../lout/debug.hh" namespace dw { namespace core { /** * \brief The platform independent interface for image buffers. * * %Image buffers depend on the platform (see \ref dw-images-and-backgrounds), * but have this general, platform independent interface. The purpose of * an image buffer is * *
    *
  1. storing the image data, *
  2. handling scaled versions of this buffer, and *
  3. drawing. *
* * The latter must be done independently from the window. * *

Creating

* * %Image buffers are created by calling dw::core::Platform::createImgbuf. * *

Storing %Image Data

* * dw::core::Imgbuf supports five image types, which are listed in the table * below. The representation defines, how the colors are stored within * the data, which is passed to dw::core::Imgbuf::copyRow. * * *
Type (dw::core::Imgbuf::Type) Bytes per * Pixel Representation *
dw::core::Imgbuf::RGB 3 red, green, blue *
dw::core::Imgbuf::RGBA 4 red, green, blue, alpha *
dw::core::Imgbuf::GRAY 1 gray value *
dw::core::Imgbuf::INDEXED 1 index to colormap *
dw::core::Imgbuf::INDEXED_ALPHA 1 index to colormap *
* * The last two types need a colormap, which is set by * dw::core::Imgbuf::setCMap, which must be called before * dw::core::Imgbuf::copyRow. This function expects the colors as 32 bit * unsigned integers, which have the format 0xrrbbgg (for indexed * images), or 0xaarrggbb (for indexed alpha), respectively. * * *

Scaling

* * The buffer with the original size, which was created by * dw::core::Platform::createImgbuf, is called root buffer. Imgbuf provides * the ability to scale buffers. Generally, both root buffers, as well as * scaled buffers, may be shared, memory management is done by reference * counters. * * Via dw::core::Imgbuf::getScaledBuf, you can retrieve a scaled buffer. * Generally, something like this must work always, in an efficient way: * * \code * dw::core::Imgbuf *curBuf, *oldBuf; * int width, heigt, * // ... * oldBuf = curBuf; * curBuf = oldBuf->getScaledBuf(oldBuf, width, height); * oldBuf->unref(); * \endcode * * \em oldBuf may both be a root buffer, or a scaled buffer. * * The root buffer keeps a list of all children, and all methods * operating on the image data (dw::core::Imgbuf::copyRow and * dw::core::Imgbuf::setCMap) are delegated to the scaled buffers, when * processed, and inherited, when a new scaled buffer is created. This * means, that they must only be performed for the root buffer. * * A possible implementation could be (dw::fltk::FltkImgbuf does it this way): * * * * Special care is to be taken, when the root buffer is not used anymore, * i.e. after dw::core::Imgbuf::unref the reference counter is 0, but there * are still scaled buffers. Since all methods operating on the image data * (dw::core::Imgbuf::copyRow and dw::core::Imgbuf::setCMap) are called for * the root buffer, the root buffer is still needed, and so must not be * deleted at this point. This is, how dw::fltk::FltkImgbuf solves this * problem: * * * * In the following example: * * \code * dw::fltk::FltkPlatform *platform = new dw::fltk::FltkPlatform (); * dw::core::Layout *layout = new dw::core::Layout (platform); * * dw::core::Imgbuf *rootbuf = * layout->createImgbuf (dw::core::Imgbuf::RGB, 100, 100); * dw::core::Imgbuf *scaledbuf = rootbuf->getScaledBuf (50, 50); * rootbuf->unref (); * scaledbuf->unref (); * \endcode * * the root buffer is not deleted, when dw::core::Imgbuf::unref is called, * since a scaled buffer is left. After calling dw::core::Imgbuf::unref for * the scaled buffer, it is deleted, and after it, the root buffer. * *

Drawing

* * dw::core::Imgbuf provides no methods for drawing, instead, this is * done by the views (implementation of dw::core::View). * * There are two situations, when drawing is necessary: * *
    *
  1. To react on expose events, the function dw::core::View::drawImage * should be used, with the following parameters: * * *
  2. When a row has been copied, it has to be drawn. To determine the * area, which has to be drawn, the dw::core::Imgbuf::getRowArea * should be used. The result can then passed * to dw::core::View::drawImage. *
* * \sa \ref dw-images-and-backgrounds */ class Imgbuf: public lout::object::Object, public lout::signal::ObservedObject { public: enum Type { RGB, RGBA, GRAY, INDEXED, INDEXED_ALPHA }; inline Imgbuf () { DBG_OBJ_CREATE ("dw::core::Imgbuf"); DBG_OBJ_BASECLASS (lout::object::Object); DBG_OBJ_BASECLASS (lout::signal::ObservedObject); } inline ~Imgbuf () { DBG_OBJ_DELETE (); } /* * Methods called from the image decoding */ virtual void setCMap (int *colors, int num_colors) = 0; virtual void copyRow (int row, const byte *data) = 0; virtual void newScan () = 0; /* * Methods called from dw::Image */ virtual Imgbuf* getScaledBuf (int width, int height) = 0; virtual void getRowArea (int row, dw::core::Rectangle *area) = 0; virtual int getRootWidth () = 0; virtual int getRootHeight () = 0; /** * Creates an image buffer with same parameters (type, gamma etc.) * except size. */ virtual Imgbuf *createSimilarBuf (int width, int height) = 0; /** * Copies another image buffer into this image buffer. */ virtual void copyTo (Imgbuf *dest, int xDestRoot, int yDestRoot, int xSrc, int ySrc, int widthSrc, int heightSrc) = 0; /* * Reference counting. */ virtual void ref () = 0; virtual void unref () = 0; /** * \todo Comment */ virtual bool lastReference () = 0; /** * \todo Comment */ virtual void setDeleteOnUnref (bool deleteOnUnref) = 0; /** * \todo Comment */ virtual bool isReferred () = 0; }; } // namespace core } // namespace dw #endif // __DW_IMGBUF_HH__