#include "core/image/Convert.h" #include #include #include "core/image/ColorImageT.h" #include namespace NICE { template ImageT

* rgbToGray(const ColorImageT

& src, ImageT

* dst, const ImageT* rgbToGrayLUT) { ImageT

* result = createResultBuffer(src.width(), src.height(), dst); #ifdef NICE_USELIB_IPP UNUSED_PARAMETER(rgbToGrayLUT); IppStatus ret = ippiRGBToGray_C3C1R(src.getPixelPointer(), src.getStepsize(), result->getPixelPointer(), result->getStepsize(), makeROIFullImage(src)); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP const P *pSrc; P *pDst; // use lut if given if(sizeof(P)==1 && rgbToGrayLUT!=NULL) for(int y=0; yheight(); ++y) { pSrc = src.getPixelPointerY(y); pDst = result->getPixelPointerY(y); for (int x=0; xwidth(); ++x,pSrc+=3,++pDst) *pDst = static_cast

( rgbToGrayLUT->getPixelQuick(static_cast(*pSrc),0) + rgbToGrayLUT->getPixelQuick(static_cast(*(pSrc+1)),1) + rgbToGrayLUT->getPixelQuick(static_cast(*(pSrc+2)),2) ); } // else calculate values else for(int y=0; yheight(); ++y) { pSrc = src.getPixelPointerY(y); pDst = result->getPixelPointerY(y); for(int i=0; iwidth(); ++i,pSrc+=3,++pDst) *pDst = static_cast

(*pSrc*0.299+*(pSrc+1)*0.587+*(pSrc+2)*0.114); } #endif // NICE_USELIB_IPP return result; } template ColorImageT

* grayToRGB(const ImageT

& src, ColorImageT

* dst) { ColorImageT

* result = createResultBuffer(src.width(), src.height(), dst); #ifdef NICE_USELIB_IPP const P* buf[3]; for(int i=0; i<=2; ++i) buf[i] = src.getPixelPointer(); IppStatus ret = ippiCopy_P3C3R(buf, src.getStepsize(), result->getPixelPointer(), result->getStepsize(), makeROIFullImage(src)); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP int i; const P* pSrcStart = src.getPixelPointer(); P* pDstStart = result->getPixelPointer(); // FIXME only works if getStepsize() is a multiple of sizeof(P) // (same problem probably in many other functions) // however, without IPP, this is usually ok (no guarantees, however) int sStep = src.getStepsize()/sizeof(P); int dStep = result->getStepsize()/sizeof(Ipp32f); const P* pSrc; P* pDst; for (int y=0; yheight(); ++y) { pSrc = pSrcStart; pDst = pDstStart; for (int x=0; xwidth(); ++x,++pSrc) { i=3; do { *pDst = *pSrc; ++pDst; --i; } while(i!=0); } pSrcStart += sStep; pDstStart += dStep; } #endif // NICE_USELIB_IPP return(result); } template void matrixToPseudoColor ( const NICE::MatrixT

& m, NICE::ColorImage & img ) { img.resize ( m.cols(), m.rows() ); double max = - std::numeric_limits::max(); double min = std::numeric_limits::max(); for ( size_t x = 0 ; x < ( size_t ) m.cols(); x++ ) for ( size_t y = 0 ; y < ( size_t ) m.rows() ; y++ ) { if ( m ( y, x ) > max ) max = m ( y, x ); if ( m ( y, x ) < min ) min = m ( y, x ); } for ( size_t y = 0 ; y < ( size_t ) m.rows() ; y++ ) for ( size_t x = 0 ; x < ( size_t ) m.cols(); x++ ) { double val = ( m ( y, x ) - min ) / ( max - min ); double r, g, b; convertToPseudoColor ( val, r, g, b ); img.setPixel ( x, y, 0, ( int ) ( r*255 ) ); img.setPixel ( x, y, 1, ( int ) ( g*255 ) ); img.setPixel ( x, y, 2, ( int ) ( b*255 ) ); } } template void imageToPseudoColor ( const NICE::ImageT

& src, NICE::ColorImage & img ) { img.resize ( src.width(), src.height() ); // determine maximum and minimum value in the source image // for appropiate scaling double max = - std::numeric_limits::max(); double min = std::numeric_limits::max(); for ( size_t x = 0 ; x < ( size_t ) src.width(); x++ ) for ( size_t y = 0 ; y < ( size_t ) src.height() ; y++ ) { double v = src.getPixel ( x, y ); if ( v > max ) max = v; if ( v < min ) min = v; } for ( size_t y = 0 ; y < ( size_t ) src.height() ; y++ ) for ( size_t x = 0 ; x < ( size_t ) src.width(); x++ ) { // scale the grayvalue double val = ( src.getPixel ( x, y ) - min ) / ( max - min ); double r, g, b; // determine the RGB values convertToPseudoColor ( val, r, g, b ); img.setPixel ( x, y, 0, ( int ) ( r*255 ) ); img.setPixel ( x, y, 1, ( int ) ( g*255 ) ); img.setPixel ( x, y, 2, ( int ) ( b*255 ) ); } } template void imageToPseudoColorWithRangeSpecification ( const NICE::ImageT

& src, NICE::ColorImage & img, const double & _min, const double & _max ) { img.resize ( src.width(), src.height() ); double max ( _max ); double min ( _min ); //consistency check if (max < min ) { min = max; max = _min; } //to avoid division by numerical zero double rangeSpecified ( fabs(max - min) ); if ( rangeSpecified < 10e-10 ) { max = min + 10e-10; rangeSpecified = fabs(max - min); } for ( size_t y = 0 ; y < ( size_t ) src.height() ; y++ ) for ( size_t x = 0 ; x < ( size_t ) src.width(); x++ ) { // scale the grayvalue double val = ( src.getPixel ( x, y ) - min ); val = std::max( val , min ); // check for lower bound val = std::min( val , max ); //check for upper bound val /= rangeSpecified; //appropriate scaling double r, g, b; // determine the RGB values convertToPseudoColor ( val, r, g, b ); img.setPixel ( x, y, 0, ( int ) ( r*255 ) ); img.setPixel ( x, y, 1, ( int ) ( g*255 ) ); img.setPixel ( x, y, 2, ( int ) ( b*255 ) ); } } template FloatImage* grayToFloat(const ImageT

& src, FloatImage* dst) { FloatImage* result = createResultBuffer(src.width(), src.height(), dst); #ifdef NICE_USELIB_IPP IppStatus ret = ippiConvert_C1R(src.getPixelPointer(), src.getStepsize(), result->getPixelPointer(), result->getStepsize(), makeROIFullImage(src)); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else const P* pSrcStart = src.getPixelPointer(); Ipp32f* pDstStart = result->getPixelPointer(); int sStep = src.getStepsize()/sizeof(P); int dStep = result->getStepsize()/sizeof(Ipp32f); const P *pSrc; FloatImage::Pixel *pDst; for(int y=0; y ImageT

* floatToGray(const FloatImage& src, ImageT

* dst, IppRoundMode roundMode) { ImageT

* result = createResultBuffer(src, dst); #ifdef NICE_USELIB_IPP IppStatus ret = ippiConvert_C1R(src.getPixelPointer(), src.getStepsize(), result->getPixelPointer(), result->getStepsize(), makeROIFullImage(src), roundMode); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else const Ipp32f* pSrcStart = src.getPixelPointer(); P* pDstStart = result->getPixelPointer(); int sStep = src.getStepsize()/sizeof(Ipp32f); int dStep = result->getStepsize()/sizeof(P); const Ipp32f* pSrc; P* pDst; for(int y=0; y::min()) *pDst = std::numeric_limits

::min(); else if(*pSrc > std::numeric_limits

::max()) *pDst = std::numeric_limits

::max(); else if(roundMode == ippRndZero) *pDst = static_cast

(*pSrc); else *pDst = static_cast

(round(*pSrc)); pSrcStart += sStep; pDstStart += dStep; } #endif // NICE_USELIB_IPP return result; } // bitdepth conversion without scaling template ImageT* convertBitDepth(const ImageT& src, ImageT* dst) { ImageT* result = createResultBuffer(src.width(), src.height(), dst); #ifdef NICE_USELIB_IPP IppStatus ret = ippiConvert_C1R(src.getPixelPointer(), src.getStepsize(), result->getPixelPointer(), result->getStepsize(), makeROIFullImage(src)); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP const P1* pSrc; P2* pDst; if(sizeof(P1)getPixelPointerY(y); for(int x=0; x(*pSrc); } else for(int y=0; ygetPixelPointerY(y); for(int x=0; x::min()) *pDst = std::numeric_limits::min(); else if(*pSrc > std::numeric_limits::max()) *pDst = std::numeric_limits::max(); else *pDst = static_cast(round(*pSrc)); } #endif // NICE_USELIB_IPP return result; } // specialication for convertBitDepth to decrease bitdepth from 32f to 8u/8s/16u/16s template ImageT

* convertBitDepth(const ImageT& src, ImageT

* dst) { ImageT

* result = createResultBuffer(src.width(), src.height(), dst); #ifdef NICE_USELIB_IPP if(sizeof(Ipp32f)getPixelPointer(), result->getStepsize(), makeROIFullImage(src), ippRndNear); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP const FloatImage::Pixel* pSrc; P* pDst; if(sizeof(Ipp32f)getPixelPointerY(y); for(int x=0; x(*pSrc); } else for(int y=0; ygetPixelPointerY(y); for(int x=0; x::min()) *pDst = std::numeric_limits

::min(); else if(*pSrc > std::numeric_limits

::max()) *pDst = std::numeric_limits

::max(); else *pDst = static_cast

(round(*pSrc)); } #endif // NICE_USELIB_IPP return result; } // bitdepth conversion without scaling template ColorImageT* convertBitDepth(const ColorImageT& src, ColorImageT* dst) { ColorImageT* result = createResultBuffer(src.width(), src.height(), dst); #ifdef NICE_USELIB_IPP IppStatus ret = ippiConvert_C3R(src.getPixelPointer(), src.getStepsize(), result->getPixelPointer(), result->getStepsize(), makeROIFullImage(src)); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP const P1* pSrc; P2* pDst; if(sizeof(P1)getPixelPointerY(y); for(int x=0; x<3*src.width(); ++x,++pSrc,++pDst) *pDst = static_cast(*pSrc); } else for(int y=0; ygetPixelPointerY(y); for(int x=0; x<3*src.width(); ++x,++pSrc,++pDst) if(*pSrc < std::numeric_limits::min()) *pDst = std::numeric_limits::min(); else if(*pSrc > std::numeric_limits::max()) *pDst = std::numeric_limits::max(); else *pDst = static_cast(round(*pSrc)); } #endif // NICE_USELIB_IPP return result; } // specialication for convertBitDepth to decrease bitdepth from 32f to 8u/8s/16u/16s template ColorImageT

* convertBitDepth(const ColorImageT &src, ColorImageT

* dst) { ColorImageT

* result = createResultBuffer(src.width(), src.height(), dst); #ifdef NICE_USELIB_IPP if(sizeof(Ipp32f)getPixelPointer(), result->getStepsize(), makeROIFullImage(src), ippRndNear); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); #else // NICE_USELIB_IPP const Ipp32f* pSrc; P* pDst; if(sizeof(Ipp32f)getPixelPointerY(y); for(int x=0; x<3*src.width(); ++x,++pSrc,++pDst) *pDst = static_cast

(*pSrc); } else for(int y=0; ygetPixelPointerY(y); for(int x=0; x<3*src.width(); ++x,++pSrc,++pDst) if(*pSrc < std::numeric_limits

::min()) *pDst = std::numeric_limits

::min(); else if(*pSrc > std::numeric_limits

::max()) *pDst = std::numeric_limits

::max(); else *pDst = static_cast

(round(*pSrc)); } #endif // NICE_USELIB_IPP return result; } template ImageT

* scale(const ImageT

& src, ImageT

* dst, double xFactor, double yFactor, int interpolation) { #ifdef NICE_USELIB_IPP IppiRect rect = makeRectFullImage(src); IppiSize dstSize; if(isZero(xFactor) && dst!=NULL) { dstSize.width = dst->width(); xFactor=dst->width()/(double)src.width(); } else dstSize.width = (int) ceil ((double) src.width () * xFactor); if(isZero(yFactor) && dst!=NULL) { dstSize.height = dst->height(); yFactor=dst->height()/(double)src.height(); } else dstSize.height = (int) ceil ((double)src.height () * yFactor); ImageT

* result = createResultBuffer(dstSize.width, dstSize.height, dst); IppStatus ret = ippiResize_C1R(src.getPixelPointer(), makeROIFullImage(src), src.getStepsize(), rect, result->getPixelPointer(), result->getStepsize(), dstSize, xFactor, yFactor, interpolation); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); return result; #else // NICE_USELIB_IPP fthrow(ImageException,"Not yet supported without IPP."); #endif // NICE_USELIB_IPP } template ColorImageT

* scale(const ColorImageT

& src, ColorImageT

* dst, double xFactor, double yFactor, int interpolation) { #ifdef NICE_USELIB_IPP IppiRect rect = makeRectFullImage(src); IppiSize dstSize; if(isZero(xFactor) && dst!=NULL) { dstSize.width = dst->width(); xFactor=dst->width()/(double)src.width(); } else dstSize.width = (int) ceil ((double) src.width () * xFactor); if(isZero(yFactor) && dst!=NULL) { dstSize.height = dst->height(); yFactor=dst->height()/(double)src.height(); } else dstSize.height = (int) ceil ((double)src.height () * yFactor); ColorImageT

* result = createResultBuffer(dstSize.width, dstSize.height, dst); IppStatus ret = ippiResize_C3R(src.getPixelPointer(), makeROIFullImage(src), src.getStepsize(), rect, result->getPixelPointer(), result->getStepsize(), dstSize, xFactor, yFactor, interpolation); if(ret!=ippStsNoErr) fthrow(ImageException, ippGetStatusString(ret)); return result; #else // NICE_USELIB_IPP fthrow(ImageException,"Not yet supported without IPP."); #endif // NICE_USELIB_IPP } template ColorImageT* signedImageToRGB(const ImageT

& image, ColorImageT* colored) { //fthrow(ImageException, "signedImageToRGB() not supported for this pixel type"); ColorImageT *result = createResultBuffer(image, colored); P vmin; P vmax; image.minmax(vmin, vmax); const P scale = std::max(vmax, static_cast

(-vmin)); const Ipp8u black[3] = {0,0,0}; *result = black; if (vmax == 0) { return result; } // FIXME not efficient for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { const P pixel = image.getPixel(x, y); if (pixel < P(0)) { const Ipp8u newPixel = static_cast(-pixel * P(255) / scale); (*result)(x,y,0) = newPixel; } else { const Ipp8u newPixel = static_cast(pixel * P(255) / scale); (*result)(x,y,0) = newPixel; (*result)(x,y,1) = newPixel; (*result)(x,y,2) = newPixel; } } } return result; } } // namespace