src/qvip/qvipp/macros.h

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