diff --git a/lib/CalypFrame.cpp b/lib/CalypFrame.cpp index fddfd54..a6ddf4f 100644 --- a/lib/CalypFrame.cpp +++ b/lib/CalypFrame.cpp @@ -102,6 +102,7 @@ public: int m_iPixelFormat; //!< Pixel format number (it follows the list of supported pixel formats) unsigned int m_uiBitsPel; //!< Bits per pixel/channel unsigned int m_uiHalfPelValue; //!< Bits per pixel/channel + bool m_bHasNegativeValues; //!< Half of the scale correspond to negative values ClpPel*** m_pppcInputPel; @@ -118,15 +119,12 @@ public: /** Numbers of histogram segments depending of image bytes depth*/ unsigned int m_uiHistoSegments; - /** - * Common constructor function of a frame - * - * @param width width of the frame - * @param height height of the frame - * @param pel_format pixel format index (always use PixelFormats enum) - * - */ void init( unsigned int width, unsigned int height, int pel_format, unsigned bitsPixel ) + { + init( width, height, pel_format, bitsPixel, false ); + } + + void init( unsigned int width, unsigned int height, int pel_format, unsigned bitsPixel, bool has_negative_values ) { m_bInit = false; m_bHasRGBPel = false; @@ -137,6 +135,7 @@ public: m_iPixelFormat = pel_format; m_uiBitsPel = bitsPixel < 8 ? 8 : bitsPixel; m_uiHalfPelValue = 1 << ( m_uiBitsPel - 1 ); + m_bHasNegativeValues = has_negative_values; if( m_uiWidth == 0 || m_uiHeight == 0 || m_iPixelFormat == -1 || bitsPixel > 16 ) { @@ -265,10 +264,16 @@ CalypFrame::CalypFrame( unsigned int width, unsigned int height, int pelFormat, d->init( width, height, pelFormat, bitsPixel ); } +CalypFrame::CalypFrame( unsigned int width, unsigned int height, int pelFormat, unsigned bitsPixel, bool has_negative_values ) + : d( new CalypFramePrivate ) +{ + d->init( width, height, pelFormat, bitsPixel, has_negative_values ); +} + CalypFrame::CalypFrame( const CalypFrame& other ) : d( new CalypFramePrivate ) { - d->init( other.getWidth(), other.getHeight(), other.getPelFormat(), other.getBitsPel() ); + d->init( other.getWidth(), other.getHeight(), other.getPelFormat(), other.getBitsPel(), other.getHasNegativeValues() ); copyFrom( &other ); } @@ -277,7 +282,7 @@ CalypFrame::CalypFrame( const CalypFrame* other ) { if( other ) { - d->init( other->getWidth(), other->getHeight(), other->getPelFormat(), other->getBitsPel() ); + d->init( other->getWidth(), other->getHeight(), other->getPelFormat(), other->getBitsPel(), other->getHasNegativeValues() ); copyFrom( other ); } } @@ -397,6 +402,11 @@ unsigned CalypFrame::getHeight( unsigned channel ) const return CHROMASHIFT( d->m_uiHeight, channel > 0 ? d->m_pcPelFormat->log2ChromaHeight : 0 ); } +bool CalypFrame::getHasNegativeValues() const +{ + return d->m_bHasNegativeValues; +} + ClpULong CalypFrame::getPixels( unsigned channel ) const { return getWidth( channel ) * getHeight( channel ); @@ -490,19 +500,24 @@ unsigned char* CalypFrame::getRGBBuffer() const return NULL; } -ClpPel CalypFrame::operator()( unsigned int ch, unsigned int xPos, unsigned int yPos ) +ClpPel CalypFrame::operator()( unsigned int ch, unsigned int xPos, unsigned int yPos, bool absolute ) const { + int retValue = 0; if( ch < d->m_pcPelFormat->numberChannels ) - return d->m_pppcInputPel[ch][yPos][xPos]; - return 0; + { + retValue = d->m_pppcInputPel[ch][yPos][xPos]; + if( !absolute && d->m_bHasNegativeValues ) + retValue = retValue - int(d->m_uiHalfPelValue); + } + return ClpPel( retValue ); } -CalypPixel CalypFrame::operator()( unsigned int xPos, unsigned int yPos ) +CalypPixel CalypFrame::operator()( unsigned int xPos, unsigned int yPos ) const { return getPixel( xPos, yPos ); } -CalypPixel CalypFrame::getPixel( unsigned int xPos, unsigned int yPos ) +CalypPixel CalypFrame::getPixel( unsigned int xPos, unsigned int yPos ) const { CalypPixel PixelValue( d->m_pcPelFormat->colorSpace ); for( unsigned int ch = 0; ch < d->m_pcPelFormat->numberChannels; ch++ ) diff --git a/lib/CalypFrame.h b/lib/CalypFrame.h index 7554cc6..ce35178 100644 --- a/lib/CalypFrame.h +++ b/lib/CalypFrame.h @@ -113,6 +113,17 @@ public: */ CalypFrame( unsigned int width, unsigned int height, int pelFormat, unsigned bitsPixel = 8 ); + /** + * Creates a new frame using the following configuration + * + * @param width width of the frame + * @param height height of the frame + * @param pel_format pixel format index (always use PixelFormats enum) + * + * @note this function might misbehave if the pixel format enum is not correct + */ + CalypFrame( unsigned int width, unsigned int height, int pelFormat, unsigned bitsPixel, bool has_negative_values ); + /** * Copy contructor * @@ -197,6 +208,12 @@ public: */ unsigned int getHeight( unsigned channel = 0 ) const; + /** + * Check if frame has negative values + * @return Boolean with the flag value + */ + bool getHasNegativeValues() const; + /** * Get number of pixels of the frame * @param channel/component @@ -257,13 +274,14 @@ public: unsigned char* getRGBBuffer() const; /** - * Get pixel value at coordinates + * Get pixel value at coordinates * @param ch frame channel * @param xPos position in X axis * @param yPos position in Y axis + * @param absolute whether it should return positive/negative values * @return pixel value */ - ClpPel operator()( unsigned int ch, unsigned int xPos, unsigned int yPos ); + ClpPel operator()( unsigned int ch, unsigned int xPos, unsigned int yPos, bool absolute = true ) const; /** * Get pixel value at coordinates @@ -271,7 +289,7 @@ public: * @param yPos position in Y axis * @return pixel value */ - CalypPixel operator()( unsigned int xPos, unsigned int yPos ); + CalypPixel operator()( unsigned int xPos, unsigned int yPos ) const; /** * Get pixel value at coordinates @@ -279,7 +297,8 @@ public: * @param yPos position in Y axis * @return pixel value */ - CalypPixel getPixel( unsigned int xPos, unsigned int yPos ); + CalypPixel getPixel( unsigned int xPos, unsigned int yPos ) const; + /** * Get pixel value at coordinates diff --git a/modules/FrameDifference.cpp b/modules/FrameDifference.cpp index 2acb61a..1e68e90 100644 --- a/modules/FrameDifference.cpp +++ b/modules/FrameDifference.cpp @@ -38,9 +38,12 @@ FrameDifference::FrameDifference() m_uiNumberOfFrames = 2; m_cModuleOptions.addOptions() /**/ - ( "Bits per pixel", m_uiBitsPixel, "Bits per pixel (use zero to avoid scaling) [0]" ); + ( "BitsPerpixel", m_uiBitsPixel, "Bits per pixel (use zero to avoid scaling) [0]" ) /**/ + ( "SumOperation", m_uiSumOperation, "Sum instead of difference [0]" ); m_uiBitsPixel = 0; + m_uiSumOperation = 0; + m_iOperation = 1; m_pcFrameDifference = NULL; } @@ -49,6 +52,8 @@ bool FrameDifference::create( std::vector apcFrameList ) { _BASIC_MODULE_API_2_CHECK_ + m_uiSumOperation = m_uiSumOperation > 1 ? 0 : m_uiSumOperation; + unsigned int uiMaxBitsPixel = 0; for( unsigned int i = 0; i < apcFrameList.size(); i++ ) { @@ -57,42 +62,46 @@ bool FrameDifference::create( std::vector apcFrameList ) if( apcFrameList[i]->getBitsPel() > uiMaxBitsPixel ) { uiMaxBitsPixel = apcFrameList[i]->getBitsPel(); + if( apcFrameList[i]->getHasNegativeValues() ) + uiMaxBitsPixel -= 1; } } - if( !m_uiBitsPixel ) - { - m_uiBitsPixel = ( uiMaxBitsPixel + 1 ) & 0x0F; - } + uiMaxBitsPixel = m_uiSumOperation ? uiMaxBitsPixel : uiMaxBitsPixel + 1; + m_uiBitsPixel = !m_uiBitsPixel ? uiMaxBitsPixel & 0x0F : m_uiBitsPixel; - m_iDiffBitShift = ( uiMaxBitsPixel + 1 ) - m_uiBitsPixel; - m_iMaxDiffValue = ( 1 << ( m_uiBitsPixel - 1 ) ); + m_iDiffBitShift = uiMaxBitsPixel - m_uiBitsPixel; + m_iMaxDiffValue = ( 1 << ( m_uiSumOperation ? m_uiBitsPixel : m_uiBitsPixel - 1 ) ); m_pcFrameDifference = new CalypFrame( apcFrameList[0]->getWidth(), apcFrameList[0]->getHeight(), - apcFrameList[0]->getPelFormat(), m_uiBitsPixel ); + apcFrameList[0]->getPelFormat(), m_uiBitsPixel, m_uiSumOperation == 1 ? false : true ); + + m_iOperation = m_uiSumOperation == 0 ? -1 : 1 ; return true; } CalypFrame* FrameDifference::process( std::vector apcFrameList ) { - ClpPel* pInput1PelYUV = apcFrameList[0]->getPelBufferYUV()[0][0]; - ClpPel* pInput2PelYUV = apcFrameList[1]->getPelBufferYUV()[0][0]; + const CalypFrame& frame1 = apcFrameList[0]; + const CalypFrame& frame2 = apcFrameList[1]; ClpPel* pOutputPelYUV = m_pcFrameDifference->getPelBufferYUV()[0][0]; - int aux_pel_1, aux_pel_2; - int diff = 0; + short aux_pel_1, aux_pel_2; + short diff = 0; for( unsigned int ch = 0; ch < m_pcFrameDifference->getNumberChannels(); ch++ ) - for( unsigned int y = 0; y < m_pcFrameDifference->getHeight(); y++ ) - for( unsigned int x = 0; x < m_pcFrameDifference->getWidth(); x++ ) + for( unsigned int y = 0; y < m_pcFrameDifference->getHeight( ch ); y++ ) + for( unsigned int x = 0; x < m_pcFrameDifference->getWidth( ch ); x++ ) { - aux_pel_1 = *pInput1PelYUV++; - aux_pel_2 = *pInput2PelYUV++; - diff = aux_pel_1 - aux_pel_2; - diff = m_iDiffBitShift > 0 ? diff >> m_iDiffBitShift : diff << m_iDiffBitShift; - diff = std::min( diff, m_iMaxDiffValue - 1 ); - diff = std::max( diff, -m_iMaxDiffValue ); - - diff += m_iMaxDiffValue; + aux_pel_1 = frame1(ch, x, y, false ); + aux_pel_2 = frame2(ch, x, y, false ); + diff = aux_pel_1 + m_iOperation * aux_pel_2; + diff = m_iDiffBitShift > 0 ? diff >> m_iDiffBitShift : diff << -m_iDiffBitShift; + diff = std::min( diff, m_iMaxDiffValue - 1 ); + if( m_uiSumOperation == 0 ) + { + diff = std::max( diff, -m_iMaxDiffValue ); + diff += m_iMaxDiffValue; + } *pOutputPelYUV++ = diff; } return m_pcFrameDifference; diff --git a/modules/FrameDifference.h b/modules/FrameDifference.h index 6bdbcd2..309a0aa 100644 --- a/modules/FrameDifference.h +++ b/modules/FrameDifference.h @@ -34,8 +34,10 @@ class FrameDifference : public CalypModuleIf private: unsigned int m_uiBitsPixel; + unsigned int m_uiSumOperation; + int m_iOperation; int m_iDiffBitShift; - int m_iMaxDiffValue; + short m_iMaxDiffValue; CalypFrame* m_pcFrameDifference; public: