PARP Research Group University of Murcia, Spain


src/qvip/qvipp/macros.h

00001 /*
00002  *      Copyright (C) 2007, 2008, 2009. 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 #include <iostream>
00026 #include <qvipp.h>
00027 #include <QVMatrix>
00028 
00029 // Macro to call IPP functions
00030 #define IPP_DEBUG(function, ipp_function, ...)                          \
00031         {                                                               \
00032         IppStatus status = ipp_function(__VA_ARGS__);                   \
00033         Q_ASSERT_X(     status == ippStsNoErr, #ipp_function,           \
00034                         ippGetStatusString(status));                    \
00035         Q_UNUSED(status);                                               \
00036         }                                                               \
00037 
00038 // To actualize ROI for output images
00040 #define COMPOSE_ROI(DestImage, SrcImage, DestROIOffset, incW, incH)             \
00041         {                                                                       \
00042         const int       roiX = DestROIOffset.x(),                               \
00043                         roiY = DestROIOffset.y(),                               \
00044                         roiWidth = SrcImage.getROI().width() - incW,            \
00045                         roiHeight = SrcImage.getROI().height() - incH;          \
00046         if( roiX + roiWidth < 0 ||  roiY + roiHeight < 0) return;               \
00047         DestImage.resize(roiX + roiWidth, roiY + roiHeight);                    \
00048         DestImage.setROI(roiX, roiY, roiWidth, roiHeight);                      \
00049         }
00050 
00051 // Checks
00052 #define CHECK_SAME_STEP(Image1, Image2)                 Q_ASSERT(Image1.getStep() == Image2.getStep())
00053 #define CHECK_SAME_ROISIZE(Image1, Image2)              Q_ASSERT(Image1.getROI().size() == Image2.getROI().size())
00054 #define CHECK_COMPATIBLE_IMAGES(NAME, Image1, Image2)   Q_ASSERT(Image1.getROI().size() == Image2.getROI().size())
00055 
00056 // Reads a pointer to the image, counting the ROI
00057 #define PDATA_READ(Image)       (&Image.getReadData()[Image.getROI().y()*Image.getStep()/Image.getTypeSize() + Image.getChannels()*Image.getROI().x()])
00058 #define PDATA_WRITE(Image)      (&Image.getWriteData()[Image.getROI().y()*Image.getStep()/Image.getTypeSize() + Image.getChannels()*Image.getROI().x()])
00059 
00060 #define PDATA_READ_MARGIN(Image, marginCols, marginRows)                                \
00061         (&Image.getReadData()[                                                          \
00062                 (Image.getROI().y()+marginRows)*Image.getStep()/Image.getTypeSize()     \
00063                 + Image.getChannels()*(Image.getROI().x()+marginCols)]                  \
00064                 )
00065 
00066 // Get the size of the image
00067 #define IMAGE_ROISIZE(Image)    ((IppiSize){ Image.getROI().width(), Image.getROI().height() })
00068 #define IMAGE_ROIRECT(Image)    ((IppiRect){ Image.getROI().x(), Image.getROI().y(), Image.getROI().width(), Image.getROI().height() })
00069 #define IMAGE_SIZE(Image)       ((IppiSize){ Image.getCols(), Image.getRows() })
00070 #define IPP_SIZE(X,Y)           ( (IppiSize) { (X), (Y) })
00071 #define IPP_POINT(X,Y)          ( (IppiPoint) { (X), (Y) })
00072 #define IPP_SIZE_FROM_QSIZE(MaskSize)   IPP_SIZE(MaskSize.width(), MaskSize.height())
00073 #define IPP_POINT_FROM_QPOINT(Point)    IPP_POINT(Point.x(), Point.y())
00074 
00075 #define IPP_MASK_SIZE_ROWS(Size)(       (Size == ippMskSize3x1  || Size == ippMskSize5x1)? 1:   \
00076                                         (Size == ippMskSize1x3  || Size == ippMskSize3x3)? 3: 5 )
00077 
00078 #define IPP_MASK_SIZE_COLS(Size)(       (Size == ippMskSize1x3  || Size == ippMskSize1x5)? 1:   \
00079                                         (Size == ippMskSize3x1  || Size == ippMskSize3x3)? 3: 5 )
00081 // START OF MACROS
00083 
00084 // Funciones con una imagen de entrada y otra de salida, del mismo tipo.
00085 // Filtros que aplican una máscara de tamaño 3x3. El ROI de destino es más pequeño que el ROI origen.
00086 // Ejemplos: ippiFilterSharpen
00087 #define DEFINE_IPP_FUNCTION_SRCIMAGE_Ti_Cj_DESTIMAGE_Ti_Cj_ROIOFFSET_BORDER3x3(NAME, TYPE, C, SUBFIX)           \
00088 void NAME(const QVImage<TYPE, C> &src, QVImage<TYPE, C> &dest, const QPoint &destROIOffset)                     \
00089         {                                                                                                       \
00090         const int maskCols = 3, maskRows = 3;                                                                   \
00091                                                                                                                 \
00092         COMPOSE_ROI(dest, src, destROIOffset, maskCols-1, maskRows-1);                                          \
00093                                                                                                                 \
00094         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX,                                                         \
00095                                 PDATA_READ_MARGIN(src, (maskCols - 1)/2, (maskRows -1)/2), src.getStep(),       \
00096                                 PDATA_WRITE(dest), dest.getStep(),                                              \
00097                                 IMAGE_ROISIZE(dest)                                                             \
00098                                 );                                                                              \
00099         }
00100 
00101 // Tres imagenes de un canal de entrada, y una de varios canales de salida, todas del mismo tipo.
00102 // Para operaciones de composición de varias imágenes de un solo canal en una de tres canales.
00103 // Ejemplos: ippiCopy
00104 //
00105 // Comprobar: que las tres imagenes de entrada tienen el mismo step (sólo se le puede pasar uno
00106 // a la función de las IPP) y el mismo tamaño para el ROI.
00107 #define DEFINE_IPP_FUNCTION_SRCIMAGE_Ti_C1_SRCIMAGE_Ti_C1_SRCIMAGE_Ti_C1_DESTIMAGE_Ti_Cj_ROIOFFSET(NAME, TYPE, C, SUBFIX)                               \
00108 void NAME(const QVImage<TYPE, 1> &src1, const QVImage<TYPE, 1> &src2, const QVImage<TYPE, 1> &src3, QVImage<TYPE, C> &dest, const QPoint &destROIOffset)        \
00109         {                                                                                                                                               \
00110         CHECK_SAME_STEP(src1, src2);                                                                            \
00111         CHECK_SAME_STEP(src2, src3);                                                                            \
00112         CHECK_SAME_ROISIZE(src1, src2);                                                                         \
00113         CHECK_SAME_ROISIZE(src2, src3);                                                                         \
00114                                                                                                                 \
00115         COMPOSE_ROI(dest, src1, destROIOffset, 0, 0);                                                           \
00116         const TYPE      * pSrc[3] = { PDATA_READ(src1), PDATA_READ(src2), PDATA_READ(src3) };                   \
00117                                                                                                                 \
00118         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX,                                                         \
00119                                 pSrc, src1.getStep(),                                                           \
00120                                 PDATA_WRITE(dest), dest.getStep(),                                              \
00121                                 IMAGE_ROISIZE(dest));                                                           \
00122         }
00123 
00124 // Una imagen de tres canales de entrada, y tres imagenes de un canal de entrada, todas del mismo tipo.
00125 // Para operaciones de separación de los planos de una imagen en tres imágenes de un solo canal.
00126 // Ejemplos: ippiCopy_8u_P3C3R
00127 #define DEFINE_IPP_FUNCTION_SRCIMAGE_Ti_Cj_DESTIMAGE_Ti_C1_DESTIMAGE_Ti_C1_DESTIMAGE_Ti_C1_ROIOFFSET(NAME, TYPE, C, SUBFIX)                     \
00128 void NAME(const QVImage<TYPE, C> &src, QVImage<TYPE, 1> &dest1, QVImage<TYPE, 1> &dest2, QVImage<TYPE, 1> &dest3, const QPoint &destROIOffset)  \
00129         {                                                                                                                                       \
00130         CHECK_SAME_STEP(dest1, dest2);                                                                  \
00131         CHECK_SAME_STEP(dest2, dest3);                                                                  \
00132                                                                                                         \
00133         COMPOSE_ROI(dest1, src, destROIOffset, 0, 0);                                                   \
00134         COMPOSE_ROI(dest2, src, destROIOffset, 0, 0);                                                   \
00135         COMPOSE_ROI(dest3, src, destROIOffset, 0, 0);                                                   \
00136                                                                                                         \
00137         TYPE    * pDest[3] =    { PDATA_WRITE(dest1), PDATA_WRITE(dest2), PDATA_WRITE(dest3) };         \
00138                                                                                                         \
00139         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX,                                                 \
00140                                 PDATA_READ(src), src.getStep(),                                         \
00141                                 pDest, dest1.getStep(),                                                 \
00142                                 IMAGE_ROISIZE(dest3));                                                  \
00143         }
00144 
00145 // Imagen de entrada y de salida de distinto numero de canales, y mismo tipo,
00146 // con selector de canal para la de entrada. Para funciones que extraigan un canal de una imagen de 3 canales.
00147 // Ejemplos: ippiCopy_8u_C3C1R
00148 #define DEFINE_IPP_FUNCTION_SRCIMAGE_Ti_Cj_DESTIMAGE_Ti_Ck_CHANNELNUM_ROIOFFSET(NAME, TYPE, C1, C2, SUBFIX)             \
00149 void NAME(const QVImage<TYPE, C1> &src, const uChar channel, QVImage<TYPE, C2> &dest, const QPoint &destROIOffset)      \
00150         {                                                                                                               \
00151         COMPOSE_ROI(dest, src, destROIOffset, 0, 0);                                                                    \
00152                                                                                                                         \
00153         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX,                                                                 \
00154                                 PDATA_READ(src) + channel, src.getStep(),                                               \
00155                                 PDATA_WRITE(dest), dest.getStep(),                                                      \
00156                                 IMAGE_ROISIZE(dest));                                                                   \
00157         }
00158 
00159 // Dos imagenes de entrada, de mismo tipo y canales, y una de salida, de tipo char y un canal. Con método de comparación.
00160 // Para funciones de comparación.
00161 // Ejemplos: ippiCompare_8u_C3R
00162 #define DEFINE_IPP_FUNCTION_SRCIMAGE_Ti_Cj_SRCIMAGE_Ti_Cj_DESTIMAGE_C1_Tuchar_IPPCMPOP_ROIOFFSET(NAME, TYPE, C, SUBFIX)                         \
00163 void NAME(const QVImage<TYPE,C> &src1, const QVImage<TYPE,C> &src2, QVImage<uChar> &dest, const IppCmpOp ippCmpOp, const QPoint &destROIOffset) \
00164         {                                                                                                                                       \
00165         CHECK_SAME_ROISIZE(src1, src2);                                                                                                         \
00166                                                                                                                                                 \
00167         COMPOSE_ROI(dest, src1, destROIOffset, 0, 0);                                                                                           \
00168                                                                                                                                                 \
00169         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX,                                                                                         \
00170                                 PDATA_READ(src1), src1.getStep(),                                                                               \
00171                                 PDATA_READ(src2), src2.getStep(),                                                                               \
00172                                 PDATA_WRITE(dest), dest.getStep(),                                                                              \
00173                                 IMAGE_ROISIZE(dest),                                                                                            \
00174                                 ippCmpOp);                                                                                                      \
00175         }
00176 
00177 // Imagen de entrada y de salida con mismo tipo y canales. IPP_SIZE para tamaño de filtro.
00178 // Por ejemplo, todas las funciones de filtrado, que pueden usar tamaños variables de filtro.
00179 // Ejemplos: ippiFilterMax_8u_C1R, ippiFilterMin_8u_C1R
00180 #define DEFINE_IPP_FUNCTION_SRCIMAGE_Ti_Cj_DESTIMAGE_Ti_Cj_MASKDIMENSION_ROIOFFSET(NAME, TYPE, C, SUBFIX)                                       \
00181 void NAME(const QVImage<TYPE,C> &src, QVImage<TYPE,C> &dest, const QSize &maskSize, const QPoint &maskAnchor, const QPoint &destROIOffset)      \
00182         {                                                                                                                                       \
00183         const uInt colMaskRadius = maskSize.width(), rowMaskRadius = maskSize.height();                                                         \
00184                                                                                                                                                 \
00185         COMPOSE_ROI(dest, src, destROIOffset, colMaskRadius-1, rowMaskRadius-1);                                                                \
00186                                                                                                                                                 \
00187         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX,                                                                                         \
00188                                 PDATA_READ(src), src.getStep(),                                                                                 \
00189                                 PDATA_WRITE(dest), dest.getStep(),                                                                              \
00190                                 IMAGE_ROISIZE(dest),                                                                                            \
00191                                 IPP_SIZE(colMaskRadius, rowMaskRadius),                                                                         \
00192                                 IPP_POINT(maskAnchor.x(), maskAnchor.y()));                                                                     \
00193         }
00194 
00195 // Imagen de entrada y de salida con mismo tipo y canales. IPP_MASK_SIZE para tamaño de filtro.
00196 // Por ejemplo, todas las funciones de filtrado, que pueden usar tamaños fijos de filtro (3x3 o 5x5).
00197 // Ejemplos: ippiFilterGauss_8u_C1R
00198 #define DEFINE_IPP_FUNCTION_SRCIMAGE_Ti_Cj_DESTIMAGE_Ti_Cj_IPPMASKSIZE_ROIOFFSET(NAME, TYPE, C, SUBFIX)                         \
00199 void NAME(const QVImage<TYPE, C> &src, QVImage<TYPE, C> &dest, const IppiMaskSize maskSize, const QPoint &destROIOffset)        \
00200         {                                                                                                                       \
00201         const int maskCols = IPP_MASK_SIZE_COLS(maskSize), maskRows = IPP_MASK_SIZE_ROWS(maskSize);             \
00202                                                                                                                 \
00203         COMPOSE_ROI(dest, src, destROIOffset, maskCols-1, maskRows-1);                                          \
00204                                                                                                                 \
00205         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX,                                                         \
00206                                 PDATA_READ_MARGIN(src, (maskCols - 1)/2, (maskRows -1)/2), src.getStep(),       \
00207                                 PDATA_WRITE(dest), dest.getStep(),                                              \
00208                                 IMAGE_ROISIZE(dest), maskSize                                                   \
00209                                 );                                                                              \
00210         }
00211 
00212 // Imagen de entrada y de salida con mismo tipo y canales. IPP_MASK_SIZE para tamaño de filtro. Uso de buffer de datos.
00213 // Por ejemplo, todas las funciones de filtrado, que pueden usar tamaños fijos de filtro (3x3 o 5x5), que usan buffer de datos.
00214 // Ejemplos: ippiFilterSobelNegVertBorder_8u16s_C1R
00215 #define DEFINE_IPP_FUNCTION_SRCIMAGE_Ti_Cj_DESTIMAGE_Ti_Cj_BUFFERIMAGE_Ti_Cj_IPPMASKSIZE__ROIOFFSET(NAME, TYPE1, TYPE2, C, SUBFIX)      \
00216 void NAME(const QVImage<TYPE1,C> &src, QVImage<TYPE2,C> &dest, const IppiMaskSize maskSize,                                             \
00217         const IppiBorderType borderType, const TYPE1 borderValue, QVImage<uChar,C> &buffer, const QPoint &destROIOffset)                \
00218         {                                                                                                                               \
00219         const int maskCols = IPP_MASK_SIZE_COLS(maskSize), maskRows = IPP_MASK_SIZE_ROWS(maskSize);                                     \
00220                                                                                                                                         \
00221         COMPOSE_ROI(dest, src, destROIOffset, maskCols-1, maskRows-1);                                                                  \
00222                                                                                                                                         \
00223         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX,                                                                                 \
00224                                 PDATA_READ_MARGIN(src, (maskCols - 1)/2, (maskRows -1)/2), src.getStep(),                               \
00225                                 PDATA_WRITE(dest), dest.getStep(),                                                                      \
00226                                 IMAGE_ROISIZE(dest), maskSize,                                                                          \
00227                                 borderType, borderValue, buffer.getWriteData());                                                        \
00228         }
00229 
00230 // Imagen genérica de entrada, y de salida de tipo y canales dado. Tamaño de máscara (5 ó 3)
00231 // Para funciones que obtienen el buffer de trabajo de funciones de filtro que usan búfferes.
00232 // Ejemplo: ippiFilterSobelNegVertGetBufferSize_8u16s_C1R
00233 #define DEFINE_IPP_FUNCTION_SRCGENERICIMAGE_DESTBUFFERIMAGE_Ti_Cj_IPPMASKSIZE__ROIOFFSET(NAME, TYPE1, TYPE2, C, SUBFIX)         \
00234 void NAME(const QVGenericImage &src, const IppiMaskSize maskSize, QVImage<TYPE1, C> &buffer)                                    \
00235         {                                                                                                                       \
00236         int bufferSize;                                                                                                         \
00237                                                                                                                                 \
00238         IPP_DEBUG(NAME,         ippi ## NAME ## SUBFIX, IMAGE_ROISIZE(src),                                                     \
00239                                 maskSize, &bufferSize);                                                                         \
00240         buffer = QVImage<uChar>(bufferSize,1);                                                                                  \
00241         }



QVision framework. PARP research group, copyright 2007, 2008.