src/qvcore/qvimage.h

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #ifndef QVIMAGE_H
00026 #define QVIMAGE_H
00027 
00028 #include <QMetaType>
00029 #include <qvcore/qvimagebuffer.h>
00030 
00040 #define QVIMAGE_INIT_READ(TYPE, IMAGE)                                          \
00041         const TYPE * __qv_data_##IMAGE##__ = IMAGE.getReadData();               \
00042         const uInt __qv_step_##IMAGE##__ = IMAGE.getStep()/sizeof(TYPE);        \
00043         const uChar __qv_planes_##IMAGE##__  = IMAGE.getChannels();             \
00044         const uInt __qv_next_line_inc_##IMAGE##__ = __qv_step_##IMAGE##__ - IMAGE.getCols();
00045 
00055 #define QVIMAGE_INIT_WRITE(TYPE, IMAGE)                                         \
00056         TYPE * __qv_data_##IMAGE##__ = IMAGE.getWriteData();                    \
00057         const uInt __qv_step_##IMAGE##__ = IMAGE.getStep()/sizeof(TYPE);        \
00058         const uChar __qv_planes_##IMAGE##__  = IMAGE.getChannels();             \
00059         const uInt __qv_next_line_inc_##IMAGE##__ = __qv_step_##IMAGE##__ - IMAGE.getCols();
00060 
00070 #define QVIMAGE_PTR_INIT_READ(TYPE, IMAGE)                                      \
00071         const TYPE * __qv_data_##IMAGE##__ = IMAGE->getReadData();              \
00072         const uInt __qv_step_##IMAGE##__ = IMAGE->getStep()/sizeof(TYPE);       \
00073         const uChar __qv_planes_##IMAGE##__  = IMAGE->getChannels();            \
00074         const uInt __qv_next_line_inc_##IMAGE##__ = __qv_step_##IMAGE##__ - IMAGE->getCols();
00075 
00085 #define QVIMAGE_PTR_INIT_WRITE(TYPE, IMAGE)                                     \
00086         TYPE * __qv_data_##IMAGE##__ = IMAGE->getWriteData();                   \
00087         const uInt __qv_step_##IMAGE##__ = IMAGE->getStep()/sizeof(TYPE);       \
00088         const uChar __qv_planes_##IMAGE##__  = IMAGE->getChannels();            \
00089         const uInt __qv_next_line_inc_##IMAGE##__ = __qv_step_##IMAGE##__ - IMAGE->getCols();
00090 
00100 #define QVIMAGE_PIXEL(IMAGE, Col, Row, Channel) \
00101         (__qv_data_##IMAGE##__ [(Row)* __qv_step_##IMAGE##__ + __qv_planes_##IMAGE##__ *(Col)+(Channel)])
00102 
00112 #define QVIMAGE_PIXEL_PTR(IMAGE, Col, Row, Channel)     \
00113         (& (__qv_data_##IMAGE##__ [(Row)* __qv_step_##IMAGE##__ + __qv_planes_##IMAGE##__ *(Col)+(Channel)]))
00114 
00121 #define QVIMAGE_ROW_INCREMENT_PTR(IMAGE)        ( __qv_step_##IMAGE##__ )
00122 
00129 #define QVIMAGE_COL_INCREMENT_PTR(IMAGE)        ( __qv_planes_##IMAGE##__ )
00130 
00137 #define QVIMAGE_NEXT_LINE_INCREMENT_PTR(IMAGE)  ( __qv_next_line_inc_##IMAGE##__ )
00138 
00171 class QVGenericImage
00172         {
00173         public:
00177                 QVGenericImage (): roi(0,0,0,0), anchor(QPoint(0,0))                                    { }
00178 
00182                 QVGenericImage(QVGenericImage const &img): roi(img.getROI()), anchor(img.getAnchor())   { }
00183 
00185                 virtual ~QVGenericImage ()                                                              { };
00186 
00190                 virtual uInt    getCols()               const   = 0;
00191 
00195                 virtual uInt    getRows()               const   = 0;
00196 
00205                 virtual uInt    getStep()               const   = 0;
00206 
00213                 virtual uInt    getChannels()           const   = 0;
00214 
00221                 virtual uInt    getTypeSize()           const   = 0;
00222 
00229                 virtual uInt    getDataSize()           const   = 0;
00230 
00237                 const QRect &   getROI()                const   { return roi; }
00238 
00245                 const QPoint &  getAnchor()             const   { return anchor; }
00246 
00247                 // ROI operations
00256                 void resetROI()                         { setROI(0,0,getCols(), getRows()); }
00257 
00267                 void erodeROI(uInt cols, uInt rows)
00268                         { setROI(getROI().x()+cols, getROI().y()+rows, getROI().width()-2*cols, getROI().height()-2*rows); }
00269 
00279                 void dilateROI(uInt cols, uInt rows)
00280                         { setROI(getROI().x()-cols, getROI().y()-rows, getROI().width()+2*cols, getROI().height()+2*rows); }
00281 
00294                 void setROI(int x, int y, uInt w, uInt h) { setROI(QRect(x,y,w,h)); }
00295 
00299                 void setMarginROI(int margin)
00300                         { setROI(margin, margin, getCols() - 2*margin, getRows() -2*margin); }
00301 
00305                 void setROI(const QRect &rect)
00306                         {
00307                         Q_ASSERT_X(rect.x() >= 0,"QVGenericImage::setROI()","QRect.x() is less than zero");
00308                         Q_ASSERT_X(rect.y() >= 0,"QVGenericImage::setROI()","QRect.y() is less than zero");
00309                         Q_ASSERT_X(rect.width() > 0,"QVGenericImage::setROI()","QRect.width() is less or equal to zero");
00310                         Q_ASSERT_X(rect.height() > 0,"QVGenericImage::setROI()","QRect.height() is less or equal to zero");
00311                         Q_ASSERT_X(rect.x()+rect.width() <= (int) getCols(),"QVGenericImage::setROI()","x + width > columns");
00312                         Q_ASSERT_X(rect.y()+rect.height() <= (int) getRows(),"QVGenericImage::setROI()","y + height > rows");
00313                         roi = rect;
00314                         }
00315 
00316                 // Anchor operations
00319                 void resetAnchor()                      { setAnchor(0,0); }
00320 
00325                 void setAnchor(int col, int row)        { setAnchor(QPoint(col,row)); }
00326 
00330                 void setAnchor(const QPoint &point)
00331                         {
00332                         Q_ASSERT_X(point.x()>=0,"QVGenericImage::setAnchor()","horizontal value for anchor is less than zero");
00333                         Q_ASSERT_X(point.y()>=0,"QVGenericImage::setAnchor()","vertical value for anchor is less than zero");
00334                         Q_ASSERT_X(point.x() < (int) getCols(),"QVGenericImage::setAnchor()","horizontal value exceeds cols");
00335                         Q_ASSERT_X(point.y() < (int) getRows(),"QVGenericImage::setAnchor()","vertical value exceeds rows");
00336                         anchor = point;
00337                         }
00338 
00343                 virtual const char * getTypeQString() const = 0;
00344 
00373                 bool isCompatibleWith(const char *qvImageClassName) const
00374                         {
00375                         Q_ASSERT_X(qvImageClassName!= NULL,"QVGenericImage::isCompatibleWith()","class name string is NULL");
00376                         return (0 == strcmp(this->getTypeQString(),qvImageClassName));
00377                         }
00378 
00389                 bool isCompatibleWith(const QVGenericImage *image) const
00390                         {
00391                         Q_ASSERT_X(image!= NULL,"QVGenericImage::isCompatibleWith()","NULL pointer");
00392                         return this->isCompatibleWith(image->getTypeQString());
00393                         }
00394 
00395         protected:
00396                 QRect roi;
00397                 QPoint anchor;
00398         };
00399 
00604 template <typename Type, int Channels = 1> class QVImage: public QVGenericImage 
00605         {
00606         public:
00612                 QVImage():QVGenericImage()
00613                         {
00614                         this->imageBuffer = new QVImageBuffer<Type, Channels>(1, 1);
00615                         setROI(0,0, this->imageBuffer->getCols(), this->imageBuffer->getRows());
00616                         setAnchor(0,0);
00617                         }
00618 
00655                 QVImage(uInt cols, uInt rows, uInt step = 0, const Type * buffer = NULL):QVGenericImage()
00656                         {
00657                         this->imageBuffer = new QVImageBuffer<Type, Channels>(cols, rows, step, buffer);
00658                         setROI(0,0, cols, rows);
00659                         setAnchor(0,0);
00660                         }
00661 
00678                 QVImage(QVImage<uChar,1> const &img);
00679 
00681                 QVImage(QVImage<uChar,3> const &img);
00682 
00684                 QVImage(QVImage<uShort,1> const &img);
00685 
00687                 QVImage(QVImage<uShort,3> const &img);
00688 
00690                 QVImage(QVImage<sShort,1> const &img);
00691 
00693                 QVImage(QVImage<sShort,3> const &img);
00694 
00696                 QVImage(QVImage<sInt,1> const &img);
00697 
00699                 QVImage(QVImage<sInt,3> const &img);
00700 
00702                 QVImage(QVImage<sFloat,1> const &img);
00703 
00705                 QVImage(QVImage<sFloat,3> const &img);
00706 
00716                 QVImage(QVImage<uChar,1> const &red, QVImage<uChar,1> const &green, QVImage<uChar,1> const &blue);
00717 
00719                 QVImage(QVImage<uShort,1> const &red, QVImage<uShort,1> const &green, QVImage<uShort,1> const &blue);
00720 
00722                 QVImage(QVImage<sShort,1> const &red, QVImage<sShort,1> const &green, QVImage<sShort,1> const &blue);
00723 
00725                 QVImage(QVImage<sInt,1> const &red, QVImage<sInt,1> const &green, QVImage<sInt,1> const &blue);
00726 
00728                 QVImage(QVImage<sFloat,1> const &red, QVImage<sFloat,1> const &green, QVImage<sFloat,1> const &blue);
00729 
00730 
00732                 const char * getTypeQString() const;
00733 
00735                 uInt getRows()          const   { return imageBuffer->getRows(); }
00736 
00738                 uInt getCols()          const   { return imageBuffer->getCols(); }
00739 
00741                 inline uInt getStep()   const   { return imageBuffer->getStep(); }
00742 
00744                 inline uInt getChannels()       const   { return imageBuffer->getChannels(); }
00745 
00747                 uInt getDataSize()      const   { return imageBuffer->getDataSize(); }
00748 
00750                 uInt getTypeSize()      const   { return imageBuffer->getTypeSize(); }
00751 
00762                 const Type * getReadData()      const   { return imageBuffer->getReadData(); }
00763 
00774                 Type * getWriteData()           { return imageBuffer->getWriteData(); }
00775 
00790                 void set(Type c1 = 0, Type c2 = 0, Type c3 = 0);
00791 
00800                 inline Type &operator()(const uInt col, const uInt row, const uInt channel = 0)
00801                         {
00802                         Type * data = imageBuffer->getWriteData();
00803                         uInt step = getStep();
00804 
00805                         Q_ASSERT_X(col < getCols(),"QVImage::operator()","col further upper bound");
00806                         Q_ASSERT_X(row < getRows(),"QVImage::operator()","row further upper bound");
00807                         int idx = row*step/sizeof(Type) + Channels*col+channel;
00808                         Q_ASSERT_X(idx >= 0,"QVImage::operator()","accessing below data");
00809                         Q_ASSERT_X(idx < imageBuffer->getDataSize(),"QVImage::operator()","accessing above data");
00810                         return data[idx];
00811                         }
00812 
00813                 inline Type operator()(const uInt col, const uInt row, const uInt channel = 0) const
00814                         {
00815                         Type const * data = imageBuffer->getReadData();
00816                         uInt cols = getCols(), rows = getRows();
00817                         uInt step = getStep();
00818                         int dataSize = getDataSize();
00819 
00820                         Q_ASSERT_X(col < cols,"QVImage::operator()","row out of upper bound");
00821                         Q_ASSERT_X(row < rows,"QVImage::operator()","row out of upper bound");
00822                         int idx = row*step/sizeof(Type) + Channels*col+channel;
00823                         Q_ASSERT_X(idx >= 0,"QVImage::operator()","accessing below data");
00824                         Q_ASSERT_X(idx < dataSize,"QVImage::operator()","accessing above data");
00825                         return data[idx];
00826                         }
00827 
00834                 inline Type &operator()(const QPoint point, const uInt channel = 0)
00835                         {
00836                         Type * data = imageBuffer->getWriteData();
00837                         uInt cols = getCols(), rows = getRows(), step = getStep();
00838                         int dataSize = getDataSize();
00839 
00840                         Q_ASSERT_X(point.x() < (int) cols,"QVImage::operator()","col further upper bound");
00841                         Q_ASSERT_X(point.y() < (int) rows,"QVImage::operator()","row further upper bound");
00842                         int idx = point.y()*step/sizeof(Type) + Channels*point.x()+channel;
00843                         Q_ASSERT_X(idx >= 0,"QVImage::operator()","accessing below data");
00844                         Q_ASSERT_X(idx < dataSize,"QVImage::operator()","accessing above data");
00845                         return data[idx];
00846                         }
00847 
00848                 inline Type operator()(const QPoint point, const uInt channel = 0) const
00849                         {
00850                         Type const * data = imageBuffer->getReadData();
00851                         uInt cols = getCols(), rows = getRows(), step = getStep();
00852                         int dataSize = getDataSize();
00853 
00854                         Q_ASSERT_X(point.x() < (int) cols,"QVImage::operator()","row out of upper bound");
00855                         Q_ASSERT_X(point.y() < (int) rows,"QVImage::operator()","row out of upper bound");
00856                         int idx = point.y()*step/sizeof(Type) + Channels*point.x()+channel;
00857                         Q_ASSERT_X(idx >= 0,"QVImage::operator()","accessing below data");
00858                         Q_ASSERT_X(idx < dataSize,"QVImage::operator()","accessing above data");
00859                         return data[idx];
00860                         }
00861 
00870                 QVImage<Type, 1> operator()(const uInt channel = 0) const;
00871 
00888                 QVImage<Type, Channels> & operator=(const QVImage<uChar, 1> &sourceImage);
00889 
00891                 QVImage<Type, Channels> & operator=(const QVImage<uChar, 3> &sourceImage);
00892 
00894                 QVImage<Type, Channels> & operator=(const QVImage<uShort, 1> &sourceImage);
00895 
00897                 QVImage<Type, Channels> & operator=(const QVImage<uShort, 3> &sourceImage);
00898 
00900                 QVImage<Type, Channels> & operator=(const QVImage<sShort, 1> &sourceImage);
00901 
00903                 QVImage<Type, Channels> & operator=(const QVImage<sShort, 3> &sourceImage);
00904 
00906                 QVImage<Type, Channels> & operator=(const QVImage<sInt, 1> &sourceImage);
00907 
00909                 QVImage<Type, Channels> & operator=(const QVImage<sInt, 3> &sourceImage);
00910 
00912                 QVImage<Type, Channels> & operator=(const QVImage<sFloat, 1> &sourceImage);
00913 
00915                 QVImage<Type, Channels> & operator=(const QVImage<sFloat, 3> &sourceImage);
00916 
00927                 bool operator==(const QVImage<Type, Channels> &img) const;
00928 
00942                 bool operator!=(const QVImage<Type, Channels> &img) const { return !(*this == img); }
00943 
00949                 QVImage<uChar, 1> operator<(const QVImage<uChar, Channels> &img) const;
00950 
00956                 QVImage<uChar, 1> operator<(const QVImage<uShort, Channels> &img) const;
00957 
00963                 QVImage<uChar, 1> operator<(const QVImage<sShort, Channels> &img) const;
00964 
00970                 QVImage<uChar, 1> operator<(const QVImage<sInt, Channels> &img) const;
00971 
00977                 QVImage<uChar, 1> operator<(const QVImage<sFloat, Channels> &img) const;
00978 
00984                 QVImage<uChar, 1> operator>(const QVImage<uChar, Channels> &img) const;
00985 
00991                 QVImage<uChar, 1> operator>(const QVImage<uShort, Channels> &img) const;
00992 
00998                 QVImage<uChar, 1> operator>(const QVImage<sShort, Channels> &img) const;
00999 
01005                 QVImage<uChar, 1> operator>(const QVImage<sInt, Channels> &img) const;
01006 
01012                 QVImage<uChar, 1> operator>(const QVImage<sFloat, Channels> &img) const;
01013 
01019                 QVImage<uChar, 1> operator<=(const QVImage<uChar, Channels> &img) const;
01020 
01026                 QVImage<uChar, 1> operator<=(const QVImage<uShort, Channels> &img) const;
01027 
01033                 QVImage<uChar, 1> operator<=(const QVImage<sShort, Channels> &img) const;
01034 
01040                 QVImage<uChar, 1> operator<=(const QVImage<sInt, Channels> &img) const;
01041 
01047                 QVImage<uChar, 1> operator<=(const QVImage<sFloat, Channels> &img) const;
01048 
01054                 QVImage<uChar, 1> operator>=(const QVImage<uChar, Channels> &img) const;
01055 
01061                 QVImage<uChar, 1> operator>=(const QVImage<uShort, Channels> &img) const;
01062 
01068                 QVImage<uChar, 1> operator>=(const QVImage<sShort, Channels> &img) const;
01069 
01075                 QVImage<uChar, 1> operator>=(const QVImage<sInt, Channels> &img) const;
01076 
01082                 QVImage<uChar, 1> operator>=(const QVImage<sFloat, Channels> &img) const;
01083 
01093                 QVImage<Type, Channels> operator+(const Type constant) const;
01094 
01104                 QVImage<Type, Channels> operator*(const Type constant) const;
01105 
01115                 QVImage<Type, Channels> operator-(const Type constant) const;
01116 
01126                 QVImage<Type, Channels> operator/(const Type constant) const;
01127 
01137                 QVImage<Type, Channels> operator<<(const Type constant) const;
01138 
01148                 QVImage<Type, Channels> operator>>(const Type constant) const;
01149 
01155                 QVImage<Type, Channels> operator!() const;
01156 
01163                 QVImage<Type, Channels> operator&(const Type constant) const;
01164 
01171                 QVImage<Type, Channels> operator|(const Type constant) const;
01172 
01179                 QVImage<Type, Channels> operator^(const Type constant) const;
01180 
01188                 QVImage<Type, Channels> operator+(const QVImage<Type, Channels> &img) const;
01189 
01197                 QVImage<Type, Channels> operator*(const QVImage<Type, Channels> &img) const;
01198 
01206                 QVImage<Type, Channels> operator-(const QVImage<Type, Channels> &img) const;
01207 
01215                 QVImage<Type, Channels> operator/(const QVImage<Type, Channels> &img) const;
01216 
01217         protected:
01218                 QSharedDataPointer< QVImageBuffer<Type,Channels> > imageBuffer;
01219         };
01220 
01221 template <typename Type, int C> bool QVImage<Type, C>::operator==(const QVImage<Type, C> &img) const
01222         {
01223         Q_ASSERT_X(img.getChannels() == this->getChannels(), "QVImage::operator==", "different number of planes");
01224         if (this->getCols() != img.getCols()) return false;
01225         if (this->getRows() != img.getRows()) return false;
01226         if (this->getChannels() != img.getChannels()) return false;
01227         if (this->getROI() != img.getROI()) return false;
01228         QVIMAGE_INIT_READ(Type,img);
01229         QVIMAGE_PTR_INIT_READ(Type,this);
01230 
01231         uInt x0 = (uInt) img.getROI().x(), y0 = (uInt) img.getROI().y(); 
01232         uInt x1 = (uInt) img.getROI().width(), y1 = (uInt) img.getROI().height(); 
01233 
01234         uInt lineSize = x1 * img.getChannels();
01235         for(uInt row = y0; row < y1; row++)
01236                 if (memcmp(&QVIMAGE_PIXEL(img, x0, row, 0),&QVIMAGE_PIXEL(this, x0, row, 0), lineSize) != 0)
01237                         return false;   
01238         return true;
01239         };
01240 
01241 
01242 typedef QVImage<uChar,1> QVImageUCharC1;
01243 typedef QVImage<uChar,3> QVImageUCharC3;
01244 typedef QVImage<uShort,1> QVImageUShortC1;
01245 typedef QVImage<uShort,3> QVImageUShortC3;
01246 typedef QVImage<sShort,1> QVImageSShortC1;
01247 typedef QVImage<sShort,3> QVImageSShortC3;
01248 typedef QVImage<sInt,1> QVImageSIntC1;
01249 typedef QVImage<sInt,3> QVImageSIntC3;
01250 typedef QVImage<sFloat,1> QVImageSFloatC1;
01251 typedef QVImage<sFloat,3> QVImageSFloatC3;
01252 
01253 Q_DECLARE_METATYPE(QVImageUCharC1);
01254 Q_DECLARE_METATYPE(QVImageUCharC3);
01255 Q_DECLARE_METATYPE(QVImageUShortC1);
01256 Q_DECLARE_METATYPE(QVImageUShortC3);
01257 Q_DECLARE_METATYPE(QVImageSShortC1);
01258 Q_DECLARE_METATYPE(QVImageSShortC3);
01259 Q_DECLARE_METATYPE(QVImageSIntC1);
01260 Q_DECLARE_METATYPE(QVImageSIntC3);
01261 Q_DECLARE_METATYPE(QVImageSFloatC1);
01262 Q_DECLARE_METATYPE(QVImageSFloatC3);
01263 
01264 #endif // QVIMAGE_H