00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #ifndef QVIMAGE_H
00026 #define QVIMAGE_H
00027
00028 #include <QMetaType>
00029 #include <qvcore/qvimagebuffer.h>
00030
00038 #define QVIMAGE_INIT_READ(TYPE, IMAGE) \
00039 const TYPE * __qv_data_##IMAGE##__ = IMAGE.getReadData(); \
00040 const uInt __qv_step_##IMAGE##__ = IMAGE.getStep()/sizeof(TYPE); \
00041 const uChar __qv_planes_##IMAGE##__ = IMAGE.getChannels();
00042
00050 #define QVIMAGE_INIT_WRITE(TYPE, IMAGE) \
00051 TYPE * __qv_data_##IMAGE##__ = IMAGE.getWriteData(); \
00052 const uInt __qv_step_##IMAGE##__ = IMAGE.getStep()/sizeof(TYPE); \
00053 const uChar __qv_planes_##IMAGE##__ = IMAGE.getChannels();
00054
00062 #define QVIMAGE_PTR_INIT_READ(TYPE, IMAGE) \
00063 const TYPE * __qv_data_##IMAGE##__ = IMAGE->getReadData(); \
00064 const uInt __qv_step_##IMAGE##__ = IMAGE->getStep()/sizeof(TYPE); \
00065 const uChar __qv_planes_##IMAGE##__ = IMAGE->getChannels();
00066
00074 #define QVIMAGE_PTR_INIT_WRITE(TYPE, IMAGE) \
00075 TYPE * __qv_data_##IMAGE##__ = IMAGE->getWriteData(); \
00076 const uInt __qv_step_##IMAGE##__ = IMAGE->getStep()/sizeof(TYPE); \
00077 const uChar __qv_planes_##IMAGE##__ = IMAGE->getChannels();
00078
00087 #define QVIMAGE_PIXEL(IMAGE, Col, Row, Channel) \
00088 (__qv_data_##IMAGE##__ [(Row)* __qv_step_##IMAGE##__ + __qv_planes_##IMAGE##__ *(Col)+(Channel)])
00089
00121 class QVGenericImage
00122 {
00123 public:
00127 QVGenericImage (): roi(0,0,0,0), anchor(QPoint(0,0)) { }
00128
00132 QVGenericImage(QVGenericImage const &img): roi(img.getROI()), anchor(img.getAnchor()) { }
00133
00135 virtual ~QVGenericImage () { };
00136
00140 virtual uInt getCols() const = 0;
00141
00145 virtual uInt getRows() const = 0;
00146
00155 virtual uInt getStep() const = 0;
00156
00163 virtual uInt getChannels() const = 0;
00164
00171 virtual uInt getTypeSize() const = 0;
00172
00179 virtual uInt getDataSize() const = 0;
00180
00187 const QRect & getROI() const { return roi; }
00188
00195 const QPoint & getAnchor() const { return anchor; }
00196
00197
00206 void resetROI() { setROI(0,0,getCols(), getRows()); }
00207
00217 void erodeROI(uInt cols, uInt rows)
00218 { setROI(getROI().x()+cols, getROI().y()+rows, getROI().width()-2*cols, getROI().height()-2*rows); }
00219
00229 void dilateROI(uInt cols, uInt rows)
00230 { setROI(getROI().x()-cols, getROI().y()-rows, getROI().width()+2*cols, getROI().height()+2*rows); }
00231
00244 void setROI(int x, int y, uInt w, uInt h) { setROI(QRect(x,y,w,h)); }
00245
00249 void setMarginROI(int margin)
00250 { setROI(margin, margin, getCols() - 2*margin, getRows() -2*margin); }
00251
00255 void setROI(const QRect &rect)
00256 {
00257 Q_ASSERT_X(rect.x() >= 0,"QVGenericImage::setROI()","QRect.x() is less than zero");
00258 Q_ASSERT_X(rect.y() >= 0,"QVGenericImage::setROI()","QRect.y() is less than zero");
00259 Q_ASSERT_X(rect.width() > 0,"QVGenericImage::setROI()","QRect.width() is less or equal to zero");
00260 Q_ASSERT_X(rect.height() > 0,"QVGenericImage::setROI()","QRect.height() is less or equal to zero");
00261 Q_ASSERT_X(rect.x()+rect.width() <= (int) getCols(),"QVGenericImage::setROI()","x + width > columns");
00262 Q_ASSERT_X(rect.y()+rect.height() <= (int) getRows(),"QVGenericImage::setROI()","y + height > rows");
00263 roi = rect;
00264 }
00265
00266
00269 void resetAnchor() { setAnchor(0,0); }
00270
00275 void setAnchor(int col, int row) { setAnchor(QPoint(col,row)); }
00276
00280 void setAnchor(const QPoint &point)
00281 {
00282 Q_ASSERT_X(point.x()>=0,"QVGenericImage::setAnchor()","horizontal value for anchor is less than zero");
00283 Q_ASSERT_X(point.y()>=0,"QVGenericImage::setAnchor()","vertical value for anchor is less than zero");
00284 Q_ASSERT_X(point.x() < (int) getCols(),"QVGenericImage::setAnchor()","horizontal value exceeds cols");
00285 Q_ASSERT_X(point.y() < (int) getRows(),"QVGenericImage::setAnchor()","vertical value exceeds rows");
00286 anchor = point;
00287 }
00288
00293 virtual const char * getTypeQString() const = 0;
00294
00323 bool isCompatibleWith(const char *qvImageClassName) const
00324 {
00325 Q_ASSERT_X(qvImageClassName!= NULL,"QVGenericImage::isCompatibleWith()","class name string is NULL");
00326 return (0 == strcmp(this->getTypeQString(),qvImageClassName));
00327 }
00328
00339 bool isCompatibleWith(const QVGenericImage *image) const
00340 {
00341 Q_ASSERT_X(image!= NULL,"QVGenericImage::isCompatibleWith()","NULL pointer");
00342 return this->isCompatibleWith(image->getTypeQString());
00343 }
00344
00345 protected:
00346 QRect roi;
00347 QPoint anchor;
00348 };
00349
00507 template <typename Type, int Channels = 1> class QVImage: public QVGenericImage
00508 {
00509 public:
00515 QVImage():QVGenericImage()
00516 {
00517 this->imageBuffer = new QVImageBuffer<Type, Channels>(1, 1);
00518 setROI(0,0, this->imageBuffer->getCols(), this->imageBuffer->getRows());
00519 setAnchor(0,0);
00520 }
00521
00558 QVImage(uInt cols, uInt rows, uInt step = 0, const Type * buffer = NULL):QVGenericImage()
00559 {
00560 this->imageBuffer = new QVImageBuffer<Type, Channels>(cols, rows, step, buffer);
00561 setROI(0,0, cols, rows);
00562 setAnchor(0,0);
00563 }
00564
00581 QVImage(QVImage<uChar,1> const &img);
00582
00584 QVImage(QVImage<uChar,3> const &img);
00585
00587 QVImage(QVImage<uShort,1> const &img);
00588
00590 QVImage(QVImage<uShort,3> const &img);
00591
00593 QVImage(QVImage<sShort,1> const &img);
00594
00596 QVImage(QVImage<sShort,3> const &img);
00597
00599 QVImage(QVImage<sInt,1> const &img);
00600
00602 QVImage(QVImage<sInt,3> const &img);
00603
00605 QVImage(QVImage<sFloat,1> const &img);
00606
00608 QVImage(QVImage<sFloat,3> const &img);
00609
00619 QVImage(QVImage<uChar,1> const &red, QVImage<uChar,1> const &green, QVImage<uChar,1> const &blue);
00620
00622 QVImage(QVImage<uShort,1> const &red, QVImage<uShort,1> const &green, QVImage<uShort,1> const &blue);
00623
00625 QVImage(QVImage<sShort,1> const &red, QVImage<sShort,1> const &green, QVImage<sShort,1> const &blue);
00626
00628 QVImage(QVImage<sInt,1> const &red, QVImage<sInt,1> const &green, QVImage<sInt,1> const &blue);
00629
00631 QVImage(QVImage<sFloat,1> const &red, QVImage<sFloat,1> const &green, QVImage<sFloat,1> const &blue);
00632
00633
00635 const char * getTypeQString() const;
00636
00638 uInt getRows() const { return imageBuffer->getRows(); }
00639
00641 uInt getCols() const { return imageBuffer->getCols(); }
00642
00644 inline uInt getStep() const { return imageBuffer->getStep(); }
00645
00647 inline uInt getChannels() const { return imageBuffer->getChannels(); }
00648
00650 uInt getDataSize() const { return imageBuffer->getDataSize(); }
00651
00653 uInt getTypeSize() const { return imageBuffer->getTypeSize(); }
00654
00665 const Type * getReadData() const { return imageBuffer->getReadData(); }
00666
00677 Type * getWriteData() { return imageBuffer->getWriteData(); }
00678
00693 void set(Type c1 = 0, Type c2 = 0, Type c3 = 0);
00694
00703 inline Type &operator()(const uInt col, const uInt row, const uInt channel = 0)
00704 {
00705 Type * data = imageBuffer->getWriteData();
00706 uInt step = getStep();
00707
00708 Q_ASSERT_X(col < getCols(),"QVImage::operator()","col further upper bound");
00709 Q_ASSERT_X(row < getRows(),"QVImage::operator()","row further upper bound");
00710 int idx = row*step/sizeof(Type) + Channels*col+channel;
00711 Q_ASSERT_X(idx >= 0,"QVImage::operator()","accessing below data");
00712 Q_ASSERT_X(idx < imageBuffer->getDataSize(),"QVImage::operator()","accessing above data");
00713 return data[idx];
00714 }
00715
00716 inline Type operator()(const uInt col, const uInt row, const uInt channel = 0) const
00717 {
00718 Type const * data = imageBuffer->getReadData();
00719 uInt cols = getCols(), rows = getRows();
00720 uInt step = getStep();
00721 int dataSize = getDataSize();
00722
00723 Q_ASSERT_X(col < cols,"QVImage::operator()","row out of upper bound");
00724 Q_ASSERT_X(row < rows,"QVImage::operator()","row out of upper bound");
00725 int idx = row*step/sizeof(Type) + Channels*col+channel;
00726 Q_ASSERT_X(idx >= 0,"QVImage::operator()","accessing below data");
00727 Q_ASSERT_X(idx < dataSize,"QVImage::operator()","accessing above data");
00728 return data[idx];
00729 }
00730
00737 inline Type &operator()(const QPoint point, const uInt channel = 0)
00738 {
00739 Type * data = imageBuffer->getWriteData();
00740 uInt cols = getCols(), rows = getRows(), step = getStep();
00741 int dataSize = getDataSize();
00742
00743 Q_ASSERT_X(point.x() < (int) cols,"QVImage::operator()","col further upper bound");
00744 Q_ASSERT_X(point.y() < (int) rows,"QVImage::operator()","row further upper bound");
00745 int idx = point.y()*step/sizeof(Type) + Channels*point.x()+channel;
00746 Q_ASSERT_X(idx >= 0,"QVImage::operator()","accessing below data");
00747 Q_ASSERT_X(idx < dataSize,"QVImage::operator()","accessing above data");
00748 return data[idx];
00749 }
00750
00751 inline Type operator()(const QPoint point, const uInt channel = 0) const
00752 {
00753 Type const * data = imageBuffer->getReadData();
00754 uInt cols = getCols(), rows = getRows(), step = getStep();
00755 int dataSize = getDataSize();
00756
00757 Q_ASSERT_X(point.x() < (int) cols,"QVImage::operator()","row out of upper bound");
00758 Q_ASSERT_X(point.y() < (int) rows,"QVImage::operator()","row out of upper bound");
00759 int idx = point.y()*step/sizeof(Type) + Channels*point.x()+channel;
00760 Q_ASSERT_X(idx >= 0,"QVImage::operator()","accessing below data");
00761 Q_ASSERT_X(idx < dataSize,"QVImage::operator()","accessing above data");
00762 return data[idx];
00763 }
00764
00773 QVImage<Type, 1> operator()(const uInt channel = 0) const;
00774
00791 QVImage<Type, Channels> & operator=(const QVImage<uChar, 1> &sourceImage);
00792
00794 QVImage<Type, Channels> & operator=(const QVImage<uChar, 3> &sourceImage);
00795
00797 QVImage<Type, Channels> & operator=(const QVImage<uShort, 1> &sourceImage);
00798
00800 QVImage<Type, Channels> & operator=(const QVImage<uShort, 3> &sourceImage);
00801
00803 QVImage<Type, Channels> & operator=(const QVImage<sShort, 1> &sourceImage);
00804
00806 QVImage<Type, Channels> & operator=(const QVImage<sShort, 3> &sourceImage);
00807
00809 QVImage<Type, Channels> & operator=(const QVImage<sInt, 1> &sourceImage);
00810
00812 QVImage<Type, Channels> & operator=(const QVImage<sInt, 3> &sourceImage);
00813
00815 QVImage<Type, Channels> & operator=(const QVImage<sFloat, 1> &sourceImage);
00816
00818 QVImage<Type, Channels> & operator=(const QVImage<sFloat, 3> &sourceImage);
00819
00830 bool operator==(const QVImage<Type, Channels> &img) const;
00831
00845 bool operator!=(const QVImage<Type, Channels> &img) const { return !(*this == img); }
00846
00852 QVImage<uChar, 1> operator<(const QVImage<uChar, Channels> &img) const;
00853
00859 QVImage<uChar, 1> operator<(const QVImage<uShort, Channels> &img) const;
00860
00866 QVImage<uChar, 1> operator<(const QVImage<sShort, Channels> &img) const;
00867
00873 QVImage<uChar, 1> operator<(const QVImage<sInt, Channels> &img) const;
00874
00880 QVImage<uChar, 1> operator<(const QVImage<sFloat, Channels> &img) const;
00881
00887 QVImage<uChar, 1> operator>(const QVImage<uChar, Channels> &img) const;
00888
00894 QVImage<uChar, 1> operator>(const QVImage<uShort, Channels> &img) const;
00895
00901 QVImage<uChar, 1> operator>(const QVImage<sShort, Channels> &img) const;
00902
00908 QVImage<uChar, 1> operator>(const QVImage<sInt, Channels> &img) const;
00909
00915 QVImage<uChar, 1> operator>(const QVImage<sFloat, Channels> &img) const;
00916
00922 QVImage<uChar, 1> operator<=(const QVImage<uChar, Channels> &img) const;
00923
00929 QVImage<uChar, 1> operator<=(const QVImage<uShort, Channels> &img) const;
00930
00936 QVImage<uChar, 1> operator<=(const QVImage<sShort, Channels> &img) const;
00937
00943 QVImage<uChar, 1> operator<=(const QVImage<sInt, Channels> &img) const;
00944
00950 QVImage<uChar, 1> operator<=(const QVImage<sFloat, Channels> &img) const;
00951
00957 QVImage<uChar, 1> operator>=(const QVImage<uChar, Channels> &img) const;
00958
00964 QVImage<uChar, 1> operator>=(const QVImage<uShort, Channels> &img) const;
00965
00971 QVImage<uChar, 1> operator>=(const QVImage<sShort, Channels> &img) const;
00972
00978 QVImage<uChar, 1> operator>=(const QVImage<sInt, Channels> &img) const;
00979
00985 QVImage<uChar, 1> operator>=(const QVImage<sFloat, Channels> &img) const;
00986
00996 QVImage<Type, Channels> operator+(const Type constant) const;
00997
01007 QVImage<Type, Channels> operator*(const Type constant) const;
01008
01018 QVImage<Type, Channels> operator-(const Type constant) const;
01019
01029 QVImage<Type, Channels> operator/(const Type constant) const;
01030
01040 QVImage<Type, Channels> operator<<(const Type constant) const;
01041
01051 QVImage<Type, Channels> operator>>(const Type constant) const;
01052
01058 QVImage<Type, Channels> operator!() const;
01059
01066 QVImage<Type, Channels> operator&(const Type constant) const;
01067
01074 QVImage<Type, Channels> operator|(const Type constant) const;
01075
01082 QVImage<Type, Channels> operator^(const Type constant) const;
01083
01091 QVImage<Type, Channels> operator+(const QVImage<Type, Channels> &img) const;
01092
01100 QVImage<Type, Channels> operator*(const QVImage<Type, Channels> &img) const;
01101
01109 QVImage<Type, Channels> operator-(const QVImage<Type, Channels> &img) const;
01110
01118 QVImage<Type, Channels> operator/(const QVImage<Type, Channels> &img) const;
01119
01120 protected:
01121 QSharedDataPointer< QVImageBuffer<Type,Channels> > imageBuffer;
01122 };
01123
01124 template <typename Type, int C> bool QVImage<Type, C>::operator==(const QVImage<Type, C> &img) const
01125 {
01126 Q_ASSERT_X(img.getChannels() == this->getChannels(), "QVImage::operator==", "different number of planes");
01127 if (this->getCols() != img.getCols()) return false;
01128 if (this->getRows() != img.getRows()) return false;
01129 if (this->getChannels() != img.getChannels()) return false;
01130 if (this->getROI() != img.getROI()) return false;
01131 QVIMAGE_INIT_READ(Type,img);
01132 QVIMAGE_PTR_INIT_READ(Type,this);
01133
01134 uInt x0 = (uInt) img.getROI().x(), y0 = (uInt) img.getROI().y();
01135 uInt x1 = (uInt) img.getROI().width(), y1 = (uInt) img.getROI().height();
01136
01137 uInt lineSize = x1 * img.getChannels();
01138 for(uInt row = y0; row < y1; row++)
01139 if (memcmp(&QVIMAGE_PIXEL(img, x0, row, 0),&QVIMAGE_PIXEL(this, x0, row, 0), lineSize) != 0)
01140 return false;
01141 return true;
01142 };
01143
01144
01145 typedef QVImage<uChar,1> QVImageUCharC1;
01146 typedef QVImage<uChar,3> QVImageUCharC3;
01147 typedef QVImage<uShort,1> QVImageUShortC1;
01148 typedef QVImage<uShort,3> QVImageUShortC3;
01149 typedef QVImage<sShort,1> QVImageSShortC1;
01150 typedef QVImage<sShort,3> QVImageSShortC3;
01151 typedef QVImage<sInt,1> QVImageSIntC1;
01152 typedef QVImage<sInt,3> QVImageSIntC3;
01153 typedef QVImage<sFloat,1> QVImageSFloatC1;
01154 typedef QVImage<sFloat,3> QVImageSFloatC3;
01155
01156 Q_DECLARE_METATYPE(QVImageUCharC1);
01157 Q_DECLARE_METATYPE(QVImageUCharC3);
01158 Q_DECLARE_METATYPE(QVImageUShortC1);
01159 Q_DECLARE_METATYPE(QVImageUShortC3);
01160 Q_DECLARE_METATYPE(QVImageSShortC1);
01161 Q_DECLARE_METATYPE(QVImageSShortC3);
01162 Q_DECLARE_METATYPE(QVImageSIntC1);
01163 Q_DECLARE_METATYPE(QVImageSIntC3);
01164 Q_DECLARE_METATYPE(QVImageSFloatC1);
01165 Q_DECLARE_METATYPE(QVImageSFloatC3);
01166
01167 #endif // QVIMAGE_H