void flipVertical( const ChannelT<T> &srcChannel, ChannelT<T> *destChannel ) { std::pair<Area,ivec2> srcDst = clippedSrcDst( srcChannel.getBounds(), destChannel->getBounds(), destChannel->getBounds(), ivec2(0,0) ); if( srcChannel.isPlanar() && destChannel->isPlanar() ) { // both channels are planar, so do a series of memcpy()'s const int32_t srcPixelInc = srcChannel.getIncrement(); const size_t copyBytes = srcDst.first.getWidth() * srcPixelInc * sizeof(T); for( int32_t y = 0; y < srcDst.first.getHeight(); ++y ) { const T *srcPtr = srcChannel.getData( ivec2( 0, y ) ); T *dstPtr = destChannel->getData( ivec2( 0, srcDst.first.getHeight() - y - 1 ) ); memcpy( dstPtr, srcPtr, copyBytes ); } } else { const int8_t srcInc = srcChannel.getIncrement(); const int8_t destInc = destChannel->getIncrement(); const int32_t width = srcDst.first.getWidth(); for( int y = 0; y < srcDst.first.getHeight(); ++y ) { const T* src = srcChannel.getData( 0, y ); T* dest = destChannel->getData( 0, srcDst.first.getHeight() - 1 - y ); for ( int x = 0; x < width; ++x ) { *dest = *src; src += srcInc; dest += destInc; } } } }
void calculateIntegralImage( const ChannelT<T> &channel, typename CHANTRAIT<T>::Accum *integralImage ) { int32_t imageWidth = channel.getWidth(), imageHeight = channel.getHeight(); ptrdiff_t srcRowBytes = channel.getRowBytes(); uint8_t srcInc = channel.getIncrement(); const T *src = channel.getData(); /*for( int32_t i = 0; i < imageWidth; i++ ) { // reset this column sum typename CHANTRAIT<T>::Accum sum = 0; for( int32_t j = 0; j < imageHeight; j++ ) { uint32_t index = j * imageWidth + i; sum += src[j*srcRowBytes+i*srcInc]; if( i == 0 ) integralImage[index] = sum; else integralImage[index] = integralImage[index-1] + sum; } }*/ for( int32_t j = 0; j < imageHeight; j++ ) { // reset this column sum typename CHANTRAIT<T>::Accum sum = 0; for( int32_t i = 0; i < imageWidth; i++ ) { uint32_t index = j * imageWidth + i; sum += src[j*srcRowBytes+i*srcInc]; if( j == 0 ) integralImage[index] = sum; else integralImage[index] = integralImage[index-imageWidth] + sum; } } }
void edgeDetectSobel( const ChannelT<T> &srcChannel, const Area &srcArea, const Vec2i &dstLT, ChannelT<T> *dstChannel ) { std::pair<Area,Vec2i> srcDst = clippedSrcDst( srcChannel.getBounds(), srcArea, dstChannel->getBounds(), dstLT ); const Area &area( srcDst.first ); const Vec2i &dstOffset( srcDst.second ); typename CHANTRAIT<T>::Sum sumX, sumY; int32_t srcRowBytes = srcChannel.getRowBytes(); int8_t srcPixelBytes = srcChannel.getIncrement() * sizeof(T); int8_t dstPixelBytes = dstChannel->getIncrement() * sizeof(T); const T maxValue = CHANTRAIT<T>::max(); for( int32_t y = 1; y < area.getHeight() - 1; ++y ) { const uint8_t *srcLine = reinterpret_cast<const uint8_t*>( srcChannel.getData( area.getX1() + 1, area.getY1() + y ) ); uint8_t *dstLine = reinterpret_cast<uint8_t*>( dstChannel->getData( dstOffset.x + area.getX1() + 1, dstOffset.y + y ) ); for( int32_t x = area.getX1() + 1; x < area.getX2() - 1; ++x ) { // sumX = -srcLine[-srcRowPixels-srcPixelStride] + srcLine[-srcRowPixels+srcPixelStride] - 2 * srcLine[-srcPixelStride] + 2 * srcLine[srcPixelStride] - srcLine[srcRowPixels-srcPixelStride] + srcLine[srcRowPixels+srcPixelStride]; sumX = -*(T*)(srcLine-srcRowBytes-srcPixelBytes) + *(T*)(srcLine-srcRowBytes+srcPixelBytes) - 2 * *(T*)(srcLine-srcPixelBytes) + 2 * *(T*)(srcLine+srcPixelBytes) - *(T*)(srcLine+srcRowBytes-srcPixelBytes) + *(T*)(srcLine+srcRowBytes+srcPixelBytes); // sumY = srcLine[-srcRowPixels-srcPixelStride] + 2 * srcLine[-srcRowPixels] + srcLine[-srcRowPixels + srcPixelStride] - srcLine[srcRowPixels-srcPixelStride] - 2 * srcLine[srcRowPixels] - srcLine[srcRowPixels+srcPixelStride]; sumY = *(T*)(srcLine-srcRowBytes-srcPixelBytes) + 2 * *(T*)(srcLine-srcRowBytes) + *(T*)(srcLine-srcRowBytes+srcPixelBytes) - *(T*)(srcLine+srcRowBytes-srcPixelBytes) - 2 * *(T*)(srcLine+srcPixelBytes) - *(T*)(srcLine+srcRowBytes+srcPixelBytes); sumX = static_cast<typename CHANTRAIT<T>::Sum>( math<float>::sqrt( float( sumX * sumX + sumY * sumY ) ) ); if( sumX > maxValue ) sumX = maxValue; *dstLine = static_cast<uint8_t>( sumX ); dstLine += dstPixelBytes; srcLine += srcPixelBytes; } } }
ImageSourceChannel( const ChannelT<T> &channel ) : ImageSource() { mWidth = channel.getWidth(); mHeight = channel.getHeight(); setColorModel( ImageIo::CM_GRAY ); setChannelOrder( ImageIo::Y ); if( channel.getIncrement() != 1 ) setCustomPixelInc( channel.getIncrement() ); if( boost::is_same<T,uint8_t>::value ) { setDataType( ImageIo::UINT8 ); mChannel8u = *reinterpret_cast<const Channel8u*>( &channel ); // register reference to 'channel' } else if( boost::is_same<T,uint16_t>::value ) { setDataType( ImageIo::UINT16 ); mChannel16u = *reinterpret_cast<const Channel16u*>( &channel ); // register reference to 'channel' } else if( boost::is_same<T,float>::value ) { setDataType( ImageIo::FLOAT32 ); mChannel32f = *reinterpret_cast<const Channel32f*>( &channel ); // register reference to 'channel' } else throw; // this channel seems to be a type we've never met mRowBytes = channel.getRowBytes(); mData = reinterpret_cast<const uint8_t*>( channel.getData() ); }
void thresholdImpl( const ChannelT<T> &srcChannel, T value, const Area &srcArea, const ivec2 &dstLT, ChannelT<T> *dstChannel ) { std::pair<Area,ivec2> srcDst = clippedSrcDst( srcChannel.getBounds(), srcArea, dstChannel->getBounds(), dstLT ); const Area &area( srcDst.first ); const ivec2 &dstOffset( srcDst.second ); uint8_t srcInc = srcChannel.getIncrement(); uint8_t dstInc = dstChannel->getIncrement(); const T maxValue = CHANTRAIT<T>::max(); for( int32_t y = 0; y < area.getHeight(); ++y ) { T *dstPtr = dstChannel->getData( ivec2( area.getX1(), y ) + dstOffset ); const T *srcPtr = srcChannel.getData( ivec2( area.getX1(), y ) ); for( int32_t x = area.getX1(); x < area.getX2(); ++x ) { *dstPtr = ( *srcPtr > value ) ? maxValue : 0; dstPtr += dstInc; srcPtr += srcInc; } } }