#ifndef TQXCFI_H #define TQXCFI_H #include #include #include #include #include "gimp.h" namespace Gwenview { // Safe readBlock helper functions class SafeDataStream { public: SafeDataStream(TQIODevice* device) : mDevice(device), mFailed(false) {} bool failed() const { return mFailed; } TQIODevice* device() const { return mDevice; } SafeDataStream& readRawBytes(char* data, uint length) { if (mFailed) return *this; int read_length=mDevice->readBlock(data, length); if (read_length==-1) mFailed=true; if ((uint)read_length!=length) mFailed=true; return *this; } SafeDataStream& operator>>(TQ_INT8& value) { return readRawBytes((char*)&value, 1); } SafeDataStream& operator>>(TQ_UINT32& value) { if (mFailed) return *this; uchar *p = (uchar *)(&value); char b[4]; if (mDevice->readBlock( b, 4 )==4) { *p++ = b[3]; *p++ = b[2]; *p++ = b[1]; *p = b[0]; } else { mFailed=true; } return *this; } SafeDataStream& operator>>(TQ_INT32& value) { return *this >>((TQ_UINT32&)value); } SafeDataStream& operator>>(float& value) { return *this >>((TQ_UINT32&)value); } SafeDataStream& operator>>(char*& value) { if (mFailed) return *this; TQ_UINT32 len; *this >> len; if (mFailed) return *this; if ( len == 0 ) { value = 0; return *this; } if (mDevice->atEnd() ) { value = 0; mFailed=true; return *this; } value = new char[len]; TQ_CHECK_PTR( value ); if ( !value ) { mFailed=true; return *this; } return readRawBytes(value, len); } SafeDataStream& readBytes(char*& data, uint& len) { if (mFailed) return *this; *this >> len; if (mFailed) return *this; data=new char[len]; TQ_CHECK_PTR( data ); if ( !data ) { mFailed=true; return *this; } return readRawBytes(data, len); } // This method is usefull to debug with gdb. Do not inline it! int at() const; private: TQIODevice* mDevice; bool mFailed; }; //! Plug-in for loading a GIMP XCF image file directly. /*! * This class uses the TQt 3.0 Image format plug-in loader to provide * the ability to read The GIMP XCF image files. This plug-in will * be dynamically loaded as needed. */ class XCFImageFormat : public TQImageFormatPlugin { /*! * Each layer in an XCF file is stored as a matrix of * 64-pixel by 64-pixel images. The GIMP has a sophisticated * method of handling very large images as well as implementing * parallel processing on a tile-by-tile basis. Here, though, * we just read them in en-masse and store them in a matrix. */ typedef TQValueVector< TQValueVector< TQImage > > Tiles; /*! * Each GIMP image is composed of one or more layers. A layer can * be one of any three basic types: RGB, grayscale or indexed. With an * optional alpha channel, there are six possible types altogether. * * Note: there is only ever one instance of this structure. The * layer info is discarded after it is merged into the final TQImage. */ struct Layer { TQ_UINT32 width; //!< Width of the layer TQ_UINT32 height; //!< Height of the layer TQ_INT32 type; //!< Type of the layer (GimpImageType) char* name; //!< Name of the layer TQ_UINT32 hierarchy_offset; //!< File position of Tile hierarchy TQ_UINT32 mask_offset; //!< File position of mask image uint nrows; //!< Number of rows of tiles (y direction) uint ncols; //!< Number of columns of tiles (x direction) Tiles image_tiles; //!< The basic image //! For Grayscale and Indexed images, the alpha channel is stored //! separately (in this data structure, anyway). Tiles alpha_tiles; Tiles mask_tiles; //!< The layer mask (optional) //! Additional information about a layer mask. struct { TQ_UINT32 opacity; TQ_UINT32 visible; TQ_UINT32 show_masked; uchar red, green, blue; TQ_UINT32 tattoo; } mask_channel; bool active; //!< Is this layer the active layer? TQ_UINT32 opacity; //!< The opacity of the layer TQ_UINT32 visible; //!< Is the layer visible? TQ_UINT32 linked; //!< Is this layer linked (geometrically) TQ_UINT32 preserve_transparency; //!< Preserve alpha when drawing on layer? TQ_UINT32 apply_mask; //!< Apply the layer mask? TQ_UINT32 edit_mask; //!< Is the layer mask the being edited? TQ_UINT32 show_mask; //!< Show the layer mask rather than the image? TQ_INT32 x_offset; //!< x offset of the layer relative to the image TQ_INT32 y_offset; //!< y offset of the layer relative to the image TQ_UINT32 mode; //!< Combining mode of layer (LayerModeEffects) TQ_UINT32 tattoo; //!< (unique identifier?) //! As each tile is read from the file, it is buffered here. uchar tile[TILE_WIDTH * TILE_HEIGHT * sizeof(TQRgb)]; //! The data from tile buffer is copied to the Tile by this //! method. Depending on the type of the tile (RGB, Grayscale, //! Indexed) and use (image or mask), the bytes in the buffer are //! copied in different ways. void (*assignBytes)( Layer& layer, uint i, uint j ); //! Construct a layer. Layer ( void ) : name( 0 ) {} //! Destruct the layer. ~Layer ( void ) { if ( name != 0 ) delete[] name; } }; /*! * The in-memory representation of the XCF Image. It contains a few * metadata items, but is mostly a container for the layer information. */ struct XCFImage { TQ_UINT32 width; //!< width of the XCF image TQ_UINT32 height; //!< height of the XCF image TQ_INT32 type; //!< type of the XCF image (GimpImageBaseType) TQ_UINT8 compression; //!< tile compression method (CompressionType) float x_resolution; //!< x resolution in dots per inch float y_resolution; //!< y resolution in dots per inch TQ_INT32 tattoo; //!< (unique identifier?) TQ_UINT32 unit; //!< Units of The GIMP (inch, mm, pica, etc...) TQ_INT32 num_colors; //!< number of colors in an indexed image TQValueVector< TQRgb > palette; //!< indexed image color palette int num_layers; //!< number of layers Layer layer; //!< most recently read layer bool initialized; //!< Is the TQImage initialized? TQImage image; //!< final TQImage //! Simple constructor. XCFImage ( void ) : initialized( false ) {} }; //! The bottom-most layer is copied into the final TQImage by this //! routine. typedef void (*PixelCopyOperation) ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); //! Higher layers are merged into the the final TQImage by this routine. typedef void (*PixelMergeOperation) ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); //! In layer DISSOLVE mode, a random number is chosen to compare to a //! pixel's alpha. If the alpha is greater than the random number, the //! pixel is drawn. This table merely contains the random number seeds //! for each ROW of an image. Therefore, the random numbers chosen //! are consistent from run to run. static int random_table[RANDOM_TABLE_SIZE]; //! This table provides the add_pixel saturation values (i.e. 250 + 250 = 255). static int add_lut[256][256]; //! Layer mode static data. typedef struct { bool affect_alpha; //!< Does this mode affect the source alpha? } LayerModes; //! Array of layer mode structures for the modes described by //! LayerModeEffects. static LayerModes layer_modes[]; public: /*! * The constructor for the XCF image loader. This initializes the * tables used in the layer merging routines. */ XCFImageFormat (); /*! * The image loader makes no (direct) use of dynamic memory * and the TQt infrastructure takes care of constructing and destructing * the loader so there is not much to do here. */ ~XCFImageFormat () {} /*! * You can query TQt about the types of image file formats it knows about * via TQImage::inputFormats or TQImage::inputFormatList(). * This method returns "xcf". */ TQStringList keys () const { return TQStringList() << "XCF"; } /*! * This method installs the XCF reader on demand. */ bool installIOHandler ( const TQString& ); static void registerFormat(); private: static void readXCF ( TQImageIO* image_io ); #ifdef TMP_WRITE static void writeXCF ( TQImageIO* ) {} #endif static void initializeImage ( XCFImage& xcf_image ); static void composeTiles ( XCFImage& xcf_image ); static bool loadImageProperties ( SafeDataStream& xcf_io, XCFImage& image ); static bool loadLayer ( SafeDataStream& xcf_io, XCFImage& xcf_image ); static bool loadLayerProperties ( SafeDataStream& xcf_io, Layer& layer ); static bool loadChannelProperties ( SafeDataStream& xcf_io, Layer& layer ); static bool loadHierarchy ( SafeDataStream& xcf_io, Layer& layer ); static bool loadMask ( SafeDataStream& xcf_io, Layer& layer ); static bool loadLevel ( SafeDataStream& xcf_io, Layer& layer, TQ_INT32 bpp ); static bool loadTileRLE ( SafeDataStream& xcf_io, uchar* tile, int size, int data_length, TQ_INT32 bpp ); static bool loadProperty ( SafeDataStream& xcf_io, PropType& type, TQByteArray& bytes ); static void setGrayPalette ( TQImage& image ); static void setPalette ( XCFImage& xcf_image, TQImage& image ); static void assignImageBytes ( Layer& layer, uint i, uint j ); static void assignMaskBytes ( Layer& layer, uint i, uint j ); static void copyLayerToImage ( XCFImage& xcf_image ); static void copyRGBToRGB ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void copyGrayToGray ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void copyGrayToRGB ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void copyGrayAToRGB ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void copyIndexedToIndexed ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void copyIndexedAToIndexed ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void copyIndexedAToRGB ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void mergeLayerIntoImage ( XCFImage& xcf_image ); static void mergeRGBToRGB ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void mergeGrayToGray ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void mergeGrayAToGray ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void mergeGrayToRGB ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void mergeGrayAToRGB ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void mergeIndexedToIndexed ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void mergeIndexedAToIndexed ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void mergeIndexedAToRGB ( Layer& layer, uint i, uint j, int k, int l, TQImage& image, int m, int n ); static void dissolveRGBPixels ( TQImage& image, int x, int y ); static void dissolveAlphaPixels ( TQImage& image, int x, int y ); }; } // namespace #endif