--- /dev/null
+
+#ifdef WIN32
+
+ #ifdef IMAGECOMPOSER_EXPORTS
+ #define IMAGE_COMPOSER_API __declspec( dllexport )
+ #else
+ #define IMAGE_COMPOSER_API __declspec( dllimport )
+ #endif
+
+#else
+ #define IMAGE_COMPOSER_API
+#endif
--- /dev/null
+
+#include <ImageComposer_ColorMaskOperator.h>
+#include <ImageComposer_Image.h>
+#include <QRectF>
+#include <QRgb>
+#include <QPixmap>
+#include <QPainter>
+
+/**
+ Constructor
+ @param theRefColor the color to the searched (the color for mask)
+ @param isMakeTransparent the boolean flag controlling if the pixels with matching color
+ should be made transparent or one with non-matching color
+ @param theRGBThreshold the threshold for RGB components
+ @param theAlphaThreshold the threshold for Alpha component
+*/
+ImageComposer_ColorMaskOperator::ImageComposer_ColorMaskOperator( const QColor& theRefColor,
+ bool isMakeTransparent,
+ int theRGBThreshold,
+ int theAlphaThreshold )
+: ImageComposer_Operator( TRANSPARENT ),
+ myRefColor( theRefColor ), myIsMakeTransparent( isMakeTransparent ),
+ myRGBThreshold( theRGBThreshold ), myAlphaThreshold( theAlphaThreshold )
+{
+}
+
+/**
+*/
+ImageComposer_ColorMaskOperator::~ImageComposer_ColorMaskOperator()
+{
+}
+
+/**
+*/
+QString ImageComposer_ColorMaskOperator::name() const
+{
+ return "colormask";
+}
+
+/**
+*/
+QRectF ImageComposer_ColorMaskOperator::calcResultBoundingRect( const QRectF& theImage1Bounds,
+ const QRectF& ) const
+{
+ return theImage1Bounds;
+}
+
+/**
+*/
+void ImageComposer_ColorMaskOperator::drawResult( QPainter& thePainter,
+ const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& ) const
+{
+ QImage anImage = theImage1.convertToFormat( QImage::Format_ARGB32 );
+ int aRMin = myRefColor.red() - myRGBThreshold;
+ int aRMax = myRefColor.red() + myRGBThreshold;
+ int aGMin = myRefColor.green() - myRGBThreshold;
+ int aGMax = myRefColor.green() + myRGBThreshold;
+ int aBMin = myRefColor.blue() - myRGBThreshold;
+ int aBMax = myRefColor.blue() + myRGBThreshold;
+ int anAMin = myRefColor.alpha() - myAlphaThreshold;
+ int anAMax = myRefColor.alpha() + myAlphaThreshold;
+
+ QRgb aTransparent = TRANSPARENT.rgba();
+
+ for( int y = 0, aMaxY = anImage.height(); y < aMaxY; y++ )
+ for( int x = 0, aMaxX = anImage.width(); x < aMaxX; x++ )
+ {
+ QRgb* aLine = ( QRgb* )anImage.scanLine( y );
+ int aRed = qRed( aLine[x] );
+ int aGreen = qGreen( aLine[x] );
+ int aBlue = qBlue( aLine[x] );
+ int anAlpha = qAlpha( aLine[x] );
+ bool isInRange = ( anAMin <= anAlpha && anAlpha <= anAMax )
+ && ( aRMin <= aRed && aRed <= aRMax )
+ && ( aGMin <= aGreen && aGreen <= aGMax )
+ && ( aBMin <= aBlue && aBlue <= aBMax );
+ if( myIsMakeTransparent == isInRange )
+ aLine[x] = aTransparent;
+ }
+
+ ImageComposer_Image aResult;
+ aResult = anImage;
+ aResult.setTransform( theImage1.transform() );
+ aResult.draw( thePainter );
+}
--- /dev/null
+
+#ifndef IMAGE_COMPOSER_COLOR_MASK_OPERATOR_HEADER
+#define IMAGE_COMPOSER_COLOR_MASK_OPERATOR_HEADER
+
+#include <ImageComposer_Operator.h>
+#include <QColor>
+
+/**
+ \class ImageComposer_ColorMaskOperator
+ Implementation of the color mask operator
+*/
+class IMAGE_COMPOSER_API ImageComposer_ColorMaskOperator : public ImageComposer_Operator
+{
+public:
+ ImageComposer_ColorMaskOperator( const QColor& theRefColor,
+ bool isMakeTransparent,
+ int theRGBThreshold,
+ int theAlphaThreshold );
+ virtual ~ImageComposer_ColorMaskOperator();
+
+ virtual QString name() const;
+
+protected:
+ virtual QRectF calcResultBoundingRect( const QRectF& theImage1Bounds,
+ const QRectF& theImage2Bounds ) const;
+ virtual void drawResult( QPainter& thePainter, const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const;
+
+private:
+ QColor myRefColor; ///< the color to the searched (the color for mask)
+ bool myIsMakeTransparent; ///< the boolean flag controlling if the pixels with matching color
+ ///< should be made transparent or one with non-matching color
+ int myRGBThreshold; ///< the threshold for RGB components
+ int myAlphaThreshold; ///< the threshold for Alpha component
+};
+
+#endif
--- /dev/null
+
+#include <ImageComposer_CropOperator.h>
+#include <ImageComposer_Image.h>
+#include <QPixmap>
+#include <QPainter>
+
+/**
+ Constructor
+ @param theBackground the background color for result image
+ @param theRect the cropping rectangle (in the global CS)
+*/
+ImageComposer_CropOperator::ImageComposer_CropOperator( const QColor& theBackground, const QRect& theRect )
+: ImageComposer_Operator( theBackground )
+{
+ myClipPath.addRect( theRect );
+}
+
+/**
+ Constructor
+ @param theBackground the background color for result image
+ @param thePath the cropping path (in the global CS)
+*/
+ImageComposer_CropOperator::ImageComposer_CropOperator( const QColor& theBackground, const QPainterPath& thePath )
+: ImageComposer_Operator( theBackground )
+{
+ myClipPath = thePath;
+}
+
+/**
+*/
+ImageComposer_CropOperator::~ImageComposer_CropOperator()
+{
+}
+
+/**
+ Return clipping path
+ @return clipping path
+*/
+QPainterPath ImageComposer_CropOperator::clipPath() const
+{
+ return myClipPath;
+}
+
+/**
+*/
+QString ImageComposer_CropOperator::name() const
+{
+ return "crop";
+}
+
+/**
+*/
+QRectF ImageComposer_CropOperator::calcResultBoundingRect( const QRectF&, const QRectF& ) const
+{
+ return myImgClipPath.boundingRect();
+}
+
+/**
+*/
+void ImageComposer_CropOperator::drawResult( QPainter& thePainter,
+ const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& ) const
+{
+ QRectF aBounds = myImgClipPath.boundingRect();
+ QTransform aTranslate;
+ aTranslate.translate( -aBounds.left(), -aBounds.top() );
+ QPainterPath aClipPath = aTranslate.map( myImgClipPath );
+ thePainter.setClipPath( aClipPath );
+ theImage1.draw( thePainter );
+ //thePainter.fillPath( aClipPath, Qt::red );
+}
+
+/**
+*/
+ImageComposer_Image ImageComposer_CropOperator::process( const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const
+{
+ QRect anImageRect( 0, 0, theImage1.width(), theImage1.height() );
+ QPainterPath anImageBoundsPath;
+ anImageBoundsPath.addPolygon( theImage1.transform().mapToPolygon( anImageRect ) );
+
+ const_cast<ImageComposer_CropOperator*>( this )->myImgClipPath =
+ theImage1.transform().inverted().map( myClipPath.intersected( anImageBoundsPath ) );
+
+ return ImageComposer_Operator::process( theImage1, theImage2 );
+}
--- /dev/null
+
+#ifndef IMAGE_COMPOSER_CROP_OPERATOR_HEADER
+#define IMAGE_COMPOSER_CROP_OPERATOR_HEADER
+
+#include <ImageComposer_Operator.h>
+#include <QColor>
+#include <QPainterPath>
+
+/**
+ \class ImageComposer_CropOperator
+ Implementation of the cropping operator
+*/
+class IMAGE_COMPOSER_API ImageComposer_CropOperator : public ImageComposer_Operator
+{
+public:
+ ImageComposer_CropOperator( const QColor& theBackground, const QRect& );
+ ImageComposer_CropOperator( const QColor& theBackground, const QPainterPath& );
+ virtual ~ImageComposer_CropOperator();
+
+ QPainterPath clipPath() const;
+
+ virtual QString name() const;
+ virtual ImageComposer_Image process( const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const;
+
+protected:
+ virtual QRectF calcResultBoundingRect( const QRectF& theImage1Bounds,
+ const QRectF& theImage2Bounds ) const;
+ virtual void drawResult( QPainter& thePainter, const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const;
+
+private:
+ QPainterPath myClipPath; ///< the clipping path specified initially
+ QPainterPath myImgClipPath; ///< the clipping path mapped to first image's local CS
+};
+
+#endif
--- /dev/null
+
+#include <ImageComposer_CutOperator.h>
+#include <ImageComposer_Image.h>
+#include <QString>
+#include <QPixmap>
+#include <QPainter>
+
+/**
+ Constructor
+ @param theBackground the background color for result image
+*/
+ImageComposer_CutOperator::ImageComposer_CutOperator( const QColor& theBackground )
+ : ImageComposer_Operator( theBackground )
+{
+}
+
+/**
+*/
+ImageComposer_CutOperator::~ImageComposer_CutOperator()
+{
+}
+
+/**
+*/
+QString ImageComposer_CutOperator::name() const
+{
+ return "cut";
+}
+
+/**
+*/
+QRectF ImageComposer_CutOperator::calcResultBoundingRect( const QRectF& theImage1Bounds,
+ const QRectF& ) const
+{
+ return theImage1Bounds;
+}
+
+/**
+*/
+void ImageComposer_CutOperator::drawResult( QPainter& thePainter,
+ const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const
+{
+ theImage1.draw( thePainter );
+ theImage2.draw( thePainter );
+}
--- /dev/null
+
+#ifndef IMAGE_COMPOSER_CUT_OPERATOR_HEADER
+#define IMAGE_COMPOSER_CUT_OPERATOR_HEADER
+
+#include <ImageComposer_Operator.h>
+#include <QColor>
+
+/**
+ \class ImageComposer_CutOperator
+ Implementation of the cutting operator
+*/
+class IMAGE_COMPOSER_API ImageComposer_CutOperator : public ImageComposer_Operator
+{
+public:
+ ImageComposer_CutOperator( const QColor& theBackground );
+ virtual ~ImageComposer_CutOperator();
+
+ virtual QString name() const;
+
+protected:
+ virtual QRectF calcResultBoundingRect( const QRectF& theImage1Bounds,
+ const QRectF& theImage2Bounds ) const;
+ virtual void drawResult( QPainter& thePainter, const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const;
+};
+
+#endif
--- /dev/null
+
+#include <ImageComposer_FuseOperator.h>
+#include <ImageComposer_Image.h>
+#include <QString>
+#include <QPixmap>
+#include <QPainter>
+
+/**
+ Constructor
+ @param theBackground the background color for result image
+*/
+ImageComposer_FuseOperator::ImageComposer_FuseOperator( const QColor& theBackground )
+ : ImageComposer_Operator( theBackground )
+{
+}
+
+/**
+*/
+ImageComposer_FuseOperator::~ImageComposer_FuseOperator()
+{
+}
+
+/**
+*/
+QString ImageComposer_FuseOperator::name() const
+{
+ return "fuse";
+}
+
+/**
+*/
+QRectF ImageComposer_FuseOperator::calcResultBoundingRect( const QRectF& theImage1Bounds,
+ const QRectF& theImage2Bounds ) const
+{
+ return theImage1Bounds.united( theImage2Bounds );
+}
+
+/**
+*/
+void ImageComposer_FuseOperator::drawResult( QPainter& thePainter,
+ const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const
+{
+ theImage1.draw( thePainter );
+ theImage2.draw( thePainter );
+}
--- /dev/null
+
+#ifndef IMAGE_COMPOSER_FUSE_OPERATOR_HEADER
+#define IMAGE_COMPOSER_FUSE_OPERATOR_HEADER
+
+#include <ImageComposer_Operator.h>
+#include <QColor>
+
+/**
+ \class ImageComposer_FuseOperator
+ Implementation of the fusing operator
+*/
+class IMAGE_COMPOSER_API ImageComposer_FuseOperator : public ImageComposer_Operator
+{
+public:
+ ImageComposer_FuseOperator( const QColor& theBackground );
+ virtual ~ImageComposer_FuseOperator();
+
+ virtual QString name() const;
+
+protected:
+ virtual QRectF calcResultBoundingRect( const QRectF& theImage1Bounds,
+ const QRectF& theImage2Bounds ) const;
+ virtual void drawResult( QPainter& thePainter, const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const;
+};
+
+#endif
--- /dev/null
+
+#include <ImageComposer_Image.h>
+#include <ImageComposer_CropOperator.h>
+#include <ImageComposer_CutOperator.h>
+#include <ImageComposer_FuseOperator.h>
+#include <QPainter>
+
+QColor ImageComposer_Image::myDefaultBackground = TRANSPARENT;
+
+/**
+ Constructor
+*/
+ImageComposer_Image::ImageComposer_Image()
+{
+}
+
+/**
+ Destructor
+*/
+ImageComposer_Image::~ImageComposer_Image()
+{
+}
+
+/**
+ Get current image transformation
+ @return current image transformation
+*/
+QTransform ImageComposer_Image::transform() const
+{
+ return myTransform;
+}
+
+/**
+ Change current image transformation
+ @param theTransform a new image transformation
+*/
+void ImageComposer_Image::setTransform( const QTransform& theTransform )
+{
+ myTransform = theTransform;
+}
+
+/**
+ Change current image transformation
+ @param theDx the image translation along X axis of the global CS
+ @param theDy the image translation along Y axis of the global CS
+ @param theRotationDeg the image rotation in degrees around the image center
+*/
+void ImageComposer_Image::setLocalTransform( qreal theDx, qreal theDy, qreal theRotationDeg )
+{
+ QTransform aTr;
+ aTr.translate( width()*0.5, height()*0.5 );
+ aTr.rotate( theRotationDeg );
+ aTr.translate( -width()*0.5, -height()*0.5 );
+ aTr.translate( theDx, theDy );
+ myTransform = aTr;
+}
+
+/**
+ Get image's bounding rectangle in the global CS
+ @return image's bounding rectangle in the global CS
+*/
+QRectF ImageComposer_Image::boundingRect() const
+{
+ QRect aRect( 0, 0, width(), height() );
+ return myTransform.mapToPolygon( aRect ).boundingRect();
+}
+
+/**
+ Draw the image using the given painter
+ @param thePainter the painter for image drawing
+*/
+void ImageComposer_Image::draw( QPainter& thePainter ) const
+{
+ thePainter.save();
+ thePainter.setTransform( myTransform, true );
+ thePainter.drawImage( 0, 0, *this );
+ thePainter.restore();
+}
+
+/**
+ Operator of another image assignment
+ @param theImage the image to assign
+ @return the assigned image
+*/
+const ImageComposer_Image& ImageComposer_Image::operator = ( const ImageComposer_Image& theImage )
+{
+ myTransform = theImage.myTransform;
+ QImage::operator = ( ( const QImage& ) theImage );
+ return theImage;
+}
+
+/**
+ Operator of another image assignment
+ @param theImage the image to assign
+ @return the assigned image
+*/
+const QImage& ImageComposer_Image::operator = ( const QImage& theImage )
+{
+ QImage::operator = ( ( const QImage& ) theImage );
+ return theImage;
+}
+
+/**
+ Apply the given operator to the image
+ @param theOperator the operator to be applied
+ @param theImage the additional image to compose (optional)
+ @return the result image
+*/
+ImageComposer_Image ImageComposer_Image::apply( const ImageComposer_Operator& theOperator,
+ const ImageComposer_Image& theImage ) const
+{
+ return theOperator.process( *this, theImage );
+}
+
+/**
+ Get default background color used for image operators
+ @return default background color
+*/
+QColor ImageComposer_Image::defaultBackground()
+{
+ return myDefaultBackground;
+}
+
+/**
+ Change default background color used for image operators
+ @param theDefaultBackground a new default background color
+*/
+void ImageComposer_Image::setDefaultBackground( const QColor& theDefaultBackground )
+{
+ myDefaultBackground = theDefaultBackground;
+}
+
+/**
+ Operator of image cropping by a rectangle
+ @param theRect the rectangle for cropping
+ @return cropped image
+*/
+ImageComposer_Image ImageComposer_Image::operator & ( const QRect& theRect ) const
+{
+ return apply( ImageComposer_CropOperator( myDefaultBackground, theRect ) );
+}
+
+/**
+ Operator of image cropping by a path
+ @param thePath the path for cropping
+ @return cropped image
+*/
+ImageComposer_Image ImageComposer_Image::operator & ( const QPainterPath& thePath ) const
+{
+ return apply( ImageComposer_CropOperator( myDefaultBackground, thePath ) );
+}
+
+/**
+ Operator of image cutting by another image
+ @param theImage the image for cutting
+ @return cut image
+*/
+ImageComposer_Image ImageComposer_Image::operator & ( const ImageComposer_Image& theImage ) const
+{
+ return apply( ImageComposer_CutOperator( myDefaultBackground ), theImage );
+}
+
+/**
+ Operator of image fusing with another image
+ @param theImage the image for fusing
+ @return fused image
+*/
+ImageComposer_Image ImageComposer_Image::operator | ( const ImageComposer_Image& theImage ) const
+{
+ return apply( ImageComposer_FuseOperator( myDefaultBackground ), theImage );
+}
--- /dev/null
+
+#ifndef IMAGE_COMPOSER_IMAGE_HEADER
+#define IMAGE_COMPOSER_IMAGE_HEADER
+
+#include <QImage>
+#include <ImageComposer.h>
+
+class ImageComposer_Operator;
+
+/**
+ \class ImageComposer_Image
+ Implementation of image in the global coordinate system
+*/
+class IMAGE_COMPOSER_API ImageComposer_Image : public QImage
+{
+public:
+ ImageComposer_Image();
+ ~ImageComposer_Image();
+
+ void draw( QPainter& thePainter ) const;
+
+ QTransform transform() const;
+ void setTransform( const QTransform& );
+ void setLocalTransform( qreal theDx, qreal theDy, qreal theRotationDeg );
+
+ QRectF boundingRect() const;
+
+ const ImageComposer_Image& operator = ( const ImageComposer_Image& theImage );
+ const QImage& operator = ( const QImage& theImage );
+
+ ImageComposer_Image apply( const ImageComposer_Operator& theOperator,
+ const ImageComposer_Image& theImage = ImageComposer_Image() ) const;
+
+ static QColor defaultBackground();
+ static void setDefaultBackground( const QColor& );
+ ImageComposer_Image operator & ( const QRect& ) const;
+ ImageComposer_Image operator & ( const QPainterPath& ) const;
+ ImageComposer_Image operator & ( const ImageComposer_Image& ) const;
+ ImageComposer_Image operator | ( const ImageComposer_Image& ) const;
+
+private:
+ QTransform myTransform; ///< the image transformation in the global CS
+ static QColor myDefaultBackground; ///< the default background color to be used in operators
+};
+
+#endif
--- /dev/null
+
+#include <ImageComposer_Operator.h>
+#include <ImageComposer_Image.h>
+#include <QPixmap>
+#include <QPainter>
+
+/**
+ Constructor
+ @param theBackground the background color for result image
+*/
+ImageComposer_Operator::ImageComposer_Operator( const QColor& theBackground )
+: myBackground( theBackground )
+{
+}
+
+/**
+ Destructor
+*/
+ImageComposer_Operator::~ImageComposer_Operator()
+{
+}
+
+/**
+ Return name of the operator
+ @return name of the operator
+*/
+QString ImageComposer_Operator::name() const
+{
+ return "";
+}
+
+/**
+ Perform the composing of images
+ @param theImage1 the first image to compose
+ @param theImage2 the second image to compose
+ @return the result image
+*/
+ImageComposer_Image ImageComposer_Operator::process( const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const
+{
+ ImageComposer_Image anImage1 = theImage1;
+ ImageComposer_Image anImage2 = theImage2;
+ QTransform aInvTransform = anImage1.transform().inverted();
+ anImage1.setTransform( anImage1.transform() * aInvTransform );
+ if( !anImage2.isNull() )
+ anImage2.setTransform( anImage2.transform() * aInvTransform );
+
+ QRectF aBounds1 = anImage1.boundingRect();
+ QRectF aBounds2;
+ if( !anImage2.isNull() )
+ aBounds2 = anImage2.boundingRect();
+ QRectF aBounds = calcResultBoundingRect( aBounds1, aBounds2 );
+
+ QTransform aTranslate;
+ aTranslate.translate( -aBounds.left(), -aBounds.top() );
+ anImage1.setTransform( anImage1.transform() * aTranslate );
+ anImage2.setTransform( anImage2.transform() * aTranslate );
+
+ QPixmap aResultImage( aBounds.width(), aBounds.height() );
+ aResultImage.fill( myBackground );
+
+ QPainter aPainter( &aResultImage );
+ aPainter.setRenderHint( QPainter::SmoothPixmapTransform, true );
+ aPainter.setRenderHint( QPainter::Antialiasing, true );
+ aPainter.setRenderHint( QPainter::HighQualityAntialiasing, true );
+
+ drawResult( aPainter, anImage1, anImage2 );
+
+ ImageComposer_Image aResult;
+ aResult = aResultImage.toImage();
+ QTransform aResultTransform = theImage1.transform();
+ aResultTransform.translate( aBounds.left(), aBounds.top() );
+ aResult.setTransform( aResultTransform );
+ return aResult;
+}
--- /dev/null
+
+#ifndef IMAGE_COMPOSER_OPERATOR_HEADER
+#define IMAGE_COMPOSER_OPERATOR_HEADER
+
+#include <ImageComposer.h>
+#include <QColor>
+
+class QString;
+class QRectF;
+class QPainter;
+class QTransform;
+class ImageComposer_Image;
+
+const QColor TRANSPARENT( 255, 255, 255, 0 );
+
+/**
+ \class ImageComposer_Operator
+ Implementation of the base abstract operation for image composing
+*/
+class IMAGE_COMPOSER_API ImageComposer_Operator
+{
+public:
+ ImageComposer_Operator( const QColor& theBackground );
+ virtual ~ImageComposer_Operator();
+
+ virtual QString name() const;
+ virtual ImageComposer_Image process( const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const;
+
+protected:
+ /**
+ Calculate bounding rectangle for the result image
+ @param theImage1Bounds bounding rectangle of the first image
+ @param theImage2Bounds bounding rectangle of the second image
+ @return calculated bounding rectangle
+ */
+ virtual QRectF calcResultBoundingRect( const QRectF& theImage1Bounds,
+ const QRectF& theImage2Bounds ) const = 0;
+
+ /**
+ Draw result image using the given painter
+ @param thePainter the painter on the result image
+ @param theImage1 the first image to compose
+ @param theImage2 the second image to compose
+ */
+ virtual void drawResult( QPainter& thePainter, const ImageComposer_Image& theImage1,
+ const ImageComposer_Image& theImage2 ) const = 0;
+
+private:
+ QColor myBackground; ///< the background color for result image
+};
+
+#endif
--- /dev/null
+
+#include <ImageComposer_Tools.h>
+
--- /dev/null
+
+#ifndef IMAGE_COMPOSER_TOOLS_HEADER
+#define IMAGE_COMPOSER_TOOLS_HEADER
+
+class ImageComposer_Tools
+{
+};
+
+#endif