diff --git a/app/FramePropertiesDock.cpp b/app/FramePropertiesDock.cpp index b26358d..5cb5b1f 100644 --- a/app/FramePropertiesDock.cpp +++ b/app/FramePropertiesDock.cpp @@ -359,8 +359,7 @@ Void FramePropertiesDock::setSelection( const QRect &selectionArea ) if( selectionArea.isValid() ) { histogramWidget->stopHistogramComputation(); - histogramWidget->updateSelectionData( - new PlaYUVerFrame( m_pcFrame, selectionArea.x(), selectionArea.y(), selectionArea.width(), selectionArea.height() ) ); + histogramWidget->updateSelectionData( new PlaYUVerFrame( m_pcFrame, selectionArea.x(), selectionArea.y(), selectionArea.width(), selectionArea.height() ) ); fullImageButton->show(); selectionImageButton->show(); selectionImageButton->click(); @@ -414,28 +413,28 @@ Void FramePropertiesDock::updateStatistiques() if( channel == HistogramWidget::ColorChannelsHistogram ) channel = colorsCB->currentIndex() + 1; - PlaYUVerFrameStats* histogram; + PlaYUVerFrame* frame; if( histogramWidget->m_renderingType == HistogramWidget::FullImageHistogram ) - histogram = histogramWidget->m_imageHistogram; + frame = histogramWidget->m_fullImage; else - histogram = histogramWidget->m_selectionHistogram; + frame = histogramWidget->m_selectionImage; - if( histogram ) + if( frame ) { - double mean = histogram->getMean( channel, min, max ); + double mean = frame->getMean( channel, min, max ); labelMeanValue->setText( value.setNum( mean, 'f', 1 ) ); - double pixels = histogram->getPixels(); + double pixels = frame->getPixels(); labelPixelsValue->setText( value.setNum( ( float )pixels, 'f', 0 ) ); - double stddev = histogram->getStdDev( channel, min, max ); + double stddev = frame->getStdDev( channel, min, max ); labelStdDevValue->setText( value.setNum( stddev, 'f', 1 ) ); - double counts = histogram->getCount( channel, min, max ); + double counts = frame->getCount( channel, min, max ); labelCountValue->setText( value.setNum( ( float )counts, 'f', 0 ) ); - double median = histogram->getMedian( channel, min, max ); + double median = frame->getMedian( channel, min, max ); labelMedianValue->setText( value.setNum( median, 'f', 1 ) ); double percentile = ( pixels > 0 ? ( 100.0 * counts / pixels ) : 0.0 ); diff --git a/app/HistogramWidget.cpp b/app/HistogramWidget.cpp index a121991..483d152 100644 --- a/app/HistogramWidget.cpp +++ b/app/HistogramWidget.cpp @@ -38,24 +38,24 @@ class HistogramWorker: public QThread { private: QObject* m_parent; - PlaYUVerFrameStats* m_histogram; + PlaYUVerFrame* m_pcFrame; public: HistogramWorker( QObject* parent ) { - m_histogram = NULL; + m_pcFrame = NULL; m_parent = parent; } - Void setup( PlaYUVerFrameStats* hist ) + Void setup( PlaYUVerFrame* frame ) { - m_histogram = hist; + m_pcFrame = frame; run(); } Void run() { - if( m_histogram && m_parent ) + if( m_pcFrame && m_parent ) { EventData *eventData = new EventData(); // eventDm_imageHistogramata->starting = true; @@ -63,11 +63,11 @@ public: // eventData->histogram = m_histogram; // QCoreApplication::postEvent( m_parent, eventData ); - m_histogram->calcHistogram(); + m_pcFrame->calcHistogram(); eventData->starting = false; - eventData->success = m_histogram->getHasHistogram(); - eventData->histogram = m_histogram; + eventData->success = m_pcFrame->getHasHistogram(); + eventData->frame = m_pcFrame; QCoreApplication::postEvent( m_parent, eventData ); } } @@ -85,12 +85,12 @@ public: { starting = false; success = false; - histogram = 0; + frame = NULL; } bool starting; bool success; - PlaYUVerFrameStats *histogram; + PlaYUVerFrame *frame; }; }; @@ -192,8 +192,8 @@ HistogramWidget::HistogramWidget( Int width, Int height, QWidget *parent ) : connect( d->blinkTimer, SIGNAL( timeout() ), this, SLOT( slotBlinkTimerDone() ) ); - m_imageHistogram = 0; - m_selectionHistogram = 0; + m_fullImage = NULL; + m_selectionImage = NULL; m_imageWorker = new HistogramWorker( this ); m_selectionWorker = new HistogramWorker( this ); @@ -208,11 +208,11 @@ HistogramWidget::~HistogramWidget() { d->blinkTimer->stop(); - if( m_imageHistogram ) - delete m_imageHistogram; - - if( m_selectionHistogram ) - delete m_selectionHistogram; +// if( m_imageHistogram ) +// delete m_imageHistogram; +// +// if( m_selectionHistogram ) +// delete m_selectionHistogram; delete m_imageWorker; delete m_selectionWorker; @@ -243,8 +243,8 @@ Void HistogramWidget::reset() d->guideVisible = false; d->clearFlag = HistogramWidgetPrivate::HistogramNone; // Remove histogram data from memory. - m_imageHistogram = NULL; - m_selectionHistogram = NULL; + m_fullImage = NULL; + m_selectionImage = NULL; update(); } @@ -266,7 +266,7 @@ Void HistogramWidget::customEvent( QEvent *event ) return; } - if( ed->histogram != m_imageHistogram && ed->histogram != m_selectionHistogram ) + if( ed->frame != m_fullImage && ed->frame != m_selectionImage ) { return; } @@ -322,16 +322,18 @@ Void HistogramWidget::customEvent( QEvent *event ) update(); unsetCursor(); // Remove old histogram data from memory. - if( m_imageHistogram ) - { - delete m_imageHistogram; - m_imageHistogram = 0; - } - if( m_selectionHistogram ) - { - delete m_selectionHistogram; - m_selectionHistogram = 0; - } + m_fullImage = NULL; + m_selectionImage = NULL; +// if( m_imageHistogram ) +// { +// delete m_imageHistogram; +// m_imageHistogram = 0; +// } +// if( m_selectionHistogram ) +// { +// delete m_selectionHistogram; +// m_selectionHistogram = 0; +// } emit signalHistogramComputationFailed(); } } @@ -391,7 +393,7 @@ Void HistogramWidget::stopHistogramComputation() // Update Data Methods //////////////////////////////////////////////////////////////////////////////// -Void HistogramWidget::updateData( const PlaYUVerFrame *pcFrame, const PlaYUVerFrame *pcFrameSelection ) +Void HistogramWidget::updateData( PlaYUVerFrame *pcFrame, PlaYUVerFrame *pcFrameSelection ) { d->imageBits = pcFrame->getBitsPel(); //d->imageColorSpace = image.getPelFormat(); @@ -408,18 +410,18 @@ Void HistogramWidget::updateData( const PlaYUVerFrame *pcFrame, const PlaYUVerFr d->range = ( 1 << d->imageBits ) - 1; emit signalMaximumValueChanged( d->range ); - m_imageHistogram = ( PlaYUVerFrameStats* )pcFrame; - m_imageWorker->setup( m_imageHistogram ); + m_fullImage = pcFrame; + m_imageWorker->setup( pcFrame ); - m_selectionHistogram = ( PlaYUVerFrameStats* )pcFrameSelection; - m_selectionWorker->setup( m_selectionHistogram ); + m_selectionImage = pcFrameSelection; + m_selectionWorker->setup( pcFrameSelection ); } -Void HistogramWidget::updateSelectionData( const PlaYUVerFrame *pcFrameSelection ) +Void HistogramWidget::updateSelectionData( PlaYUVerFrame *pcFrameSelection ) { - m_selectionHistogram = ( PlaYUVerFrame* )pcFrameSelection; - m_selectionWorker->setup( m_selectionHistogram ); + m_selectionImage = pcFrameSelection; + m_selectionWorker->setup( pcFrameSelection ); } //////////////////////////////////////////////////////////////////////////////// @@ -503,14 +505,14 @@ Void HistogramWidget::paintEvent( QPaintEvent * ) int wWidth = width() - 1; int wHeight = height() - 1; double max; - PlaYUVerFrameStats *histogram; + PlaYUVerFrame *frame; - if( m_renderingType == ImageSelectionHistogram && m_selectionHistogram ) - histogram = m_selectionHistogram; + if( m_renderingType == ImageSelectionHistogram && m_selectionImage ) + frame = m_selectionImage; else - histogram = m_imageHistogram; + frame = m_fullImage; - if( !histogram ) + if( !frame ) return; x = 0; @@ -523,24 +525,23 @@ Void HistogramWidget::paintEvent( QPaintEvent * ) switch( m_channelType ) { case HistogramWidget::FirstChannelHistogram: // Y channel. - max = histogram->getMaximum( LUMA ); + max = frame->getMaximum( LUMA ); break; case HistogramWidget::SecondChannelHistogram: // Cb channel. - max = histogram->getMaximum( CHROMA_U ); + max = frame->getMaximum( CHROMA_U ); break; case HistogramWidget::ThirdChannelHistogram: // Cr channel. - max = histogram->getMaximum( CHROMA_V ); + max = frame->getMaximum( CHROMA_V ); break; case HistogramWidget::AlphaChannelHistogram: // Alpha channel. - max = histogram->getMaximum( COLOR_A ); + max = frame->getMaximum( COLOR_A ); break; case HistogramWidget::ColorChannelsHistogram: // All color channels. - max = qMax( qMax( histogram->getMaximum( LUMA ), histogram->getMaximum( CHROMA_U ) ), - histogram->getMaximum( CHROMA_V ) ); + max = qMax( qMax( frame->getMaximum( LUMA ), frame->getMaximum( CHROMA_U ) ), frame->getMaximum( CHROMA_V ) ); break; case HistogramWidget::LumaHistogram: // Luminance. - max = histogram->getMaximum( LUMA ); + max = frame->getMaximum( LUMA ); break; } @@ -571,8 +572,8 @@ Void HistogramWidget::paintEvent( QPaintEvent * ) double value_r = 0.0, value_g = 0.0, value_b = 0.0; // For all channels. int i, j; - i = ( x * histogram->getHistogramSegment() ) / wWidth; - j = ( ( x + 1 ) * histogram->getHistogramSegment() ) / wWidth; + i = ( x * frame->getHistogramSegment() ) / wWidth; + j = ( ( x + 1 ) * frame->getHistogramSegment() ) / wWidth; do { @@ -587,24 +588,24 @@ Void HistogramWidget::paintEvent( QPaintEvent * ) switch( m_channelType ) { case HistogramWidget::FirstChannelHistogram: // Y channel. - v = histogram->getHistogramValue( LUMA, i++ ); + v = frame->getHistogramValue( LUMA, i++ ); break; case HistogramWidget::SecondChannelHistogram: // Cb channel. - v = histogram->getHistogramValue( CHROMA_U, i++ ); + v = frame->getHistogramValue( CHROMA_U, i++ ); break; case HistogramWidget::ThirdChannelHistogram: // Cr channel. - v = histogram->getHistogramValue( CHROMA_V, i++ ); + v = frame->getHistogramValue( CHROMA_V, i++ ); break; case HistogramWidget::AlphaChannelHistogram: // Alpha channel. - v = histogram->getHistogramValue( COLOR_A, i++ ); + v = frame->getHistogramValue( COLOR_A, i++ ); break; case HistogramWidget::ColorChannelsHistogram: // All color. - vr = histogram->getHistogramValue( LUMA, i ); - vg = histogram->getHistogramValue( CHROMA_U, i ); - vb = histogram->getHistogramValue( CHROMA_U, i++ ); + vr = frame->getHistogramValue( LUMA, i ); + vg = frame->getHistogramValue( CHROMA_U, i ); + vb = frame->getHistogramValue( CHROMA_U, i++ ); break; case HistogramWidget::LumaHistogram: // Luminance. - v = histogram->getHistogramValue( LUMA, i++ ); + v = frame->getHistogramValue( LUMA, i++ ); break; } @@ -916,7 +917,7 @@ Void HistogramWidget::paintEvent( QPaintEvent * ) if( guidePos != -1 ) { - int xGuide = ( guidePos * wWidth ) / histogram->getHistogramSegment(); + int xGuide = ( guidePos * wWidth ) / frame->getHistogramSegment(); p1.drawLine( xGuide, 0, xGuide, wHeight ); QString string = tr( "x:%1" ).arg( guidePos ); @@ -953,23 +954,23 @@ Void HistogramWidget::paintEvent( QPaintEvent * ) tipText = ""; tipText += cellBeg + tr( "Mean:" ) + cellMid; - double mean = histogram->getMean( m_channelType, 0, histogram->getHistogramSegment() - 1 ); + double mean = frame->getMean( m_channelType, 0, frame->getHistogramSegment() - 1 ); tipText += value.setNum( mean, 'f', 1 ) + cellEnd; tipText += cellBeg + tr( "Pixels:" ) + cellMid; - double pixels = histogram->getPixels(); + double pixels = frame->getPixels(); tipText += value.setNum( ( float )pixels, 'f', 0 ) + cellEnd; tipText += cellBeg + tr( "Std dev.:" ) + cellMid; - double stddev = histogram->getStdDev( m_channelType, 0, histogram->getHistogramSegment() - 1 ); + double stddev = frame->getStdDev( m_channelType, 0, frame->getHistogramSegment() - 1 ); tipText += value.setNum( stddev, 'f', 1 ) + cellEnd; tipText += cellBeg + tr( "Selected:" ) + cellMid; - double counts = histogram->getCount( m_channelType, 0, histogram->getHistogramSegment() - 1 ); + double counts = frame->getCount( m_channelType, 0, frame->getHistogramSegment() - 1 ); tipText += value.setNum( ( float )counts, 'f', 0 ) + cellEnd; tipText += cellBeg + tr( "Median:" ) + cellMid; - double median = histogram->getMedian( m_channelType, 0, histogram->getHistogramSegment() - 1 ); + double median = frame->getMedian( m_channelType, 0, frame->getHistogramSegment() - 1 ); tipText += value.setNum( median, 'f', 1 ) + cellEnd; tipText += cellBeg + tr( "Percent:" ) + cellMid; diff --git a/app/HistogramWidget.h b/app/HistogramWidget.h index ead8a80..ad941a5 100644 --- a/app/HistogramWidget.h +++ b/app/HistogramWidget.h @@ -114,11 +114,11 @@ public : /** Stop current histogram computations.*/ Void stopHistogramComputation(); - /** Update full image histogram data from SImage.*/ - Void updateData( const PlaYUVerFrame *pcFrame, const PlaYUVerFrame *pcFrameSelection ); + /** Update full image histogram data. */ + Void updateData( PlaYUVerFrame *pcFrame, PlaYUVerFrame *pcFrameSelection ); - /** Update image selection histogram data from SImage.*/ - Void updateSelectionData( const PlaYUVerFrame *pcFrameSelection ); + /** Update image selection histogram data.*/ + Void updateSelectionData( PlaYUVerFrame *pcFrameSelection ); /** @see @p HistogramOption */ Void setOptions( HistogramOptions options = AllOptions ); @@ -141,10 +141,12 @@ public: /** Full image */ HistogramWorker* m_imageWorker; - PlaYUVerFrameStats* m_imageHistogram; + //PlaYUVerFrameStats* m_imageHistogram; + PlaYUVerFrame* m_fullImage; /** Histogram area selection */ HistogramWorker* m_selectionWorker; - PlaYUVerFrameStats* m_selectionHistogram; + //PlaYUVerFrameStats* m_selectionHistogram; + PlaYUVerFrame* m_selectionImage; Q_SIGNALS: void signalIntervalChanged( int min, int max ); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8d5ed49..c0af06d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -8,7 +8,7 @@ set(plaYUver_Lib_SRCS # Frame PlaYUVerFrame.cpp PlaYUVerFramePixelFormats.cpp - PlaYUVerFrameStats.cpp + # PlaYUVerFrameStats.cpp # Stream PlaYUVerStream.cpp # Command Parser @@ -28,7 +28,7 @@ ENDIF() set(plaYUver_Lib_HEADERS PlaYUVerDefs.h PlaYUVerProgramOptions.h - PlaYUVerFrameStats.h + # PlaYUVerFrameStats.h PlaYUVerFrame.h PlaYUVerStream.h PlaYUVerModuleIf.h diff --git a/lib/PlaYUVerFrame.cpp b/lib/PlaYUVerFrame.cpp index 15cbcb2..40dc3a2 100644 --- a/lib/PlaYUVerFrame.cpp +++ b/lib/PlaYUVerFrame.cpp @@ -209,7 +209,13 @@ Void PlaYUVerFrame::init( UInt width, UInt height, Int pel_format, Int bitsPixel } getMem1D( &m_pcARGB32, m_uiHeight * m_uiWidth * 4 ); - xSetupStatistics( this ); + m_uiHistoSegments = 1 << m_iBitsPel; + + if( m_pcPelFormat->colorSpace == PlaYUVerFrame::COLOR_RGB || m_pcPelFormat->colorSpace == PlaYUVerFrame::COLOR_ARGB ) + m_uiHistoChannels = m_pcPelFormat->numberChannels + 1; + else + m_uiHistoChannels = m_pcPelFormat->numberChannels; + m_cPelFmtName = PlaYUVerFrame::supportedPixelFormatListNames()[m_iPixelFormat].c_str(); } @@ -241,6 +247,11 @@ UInt64 PlaYUVerFrame::getBytesPerFrame( UInt uiWidth, UInt uiHeight, Int iPixelF return numberBytes * bytesPerPixel; } +UInt PlaYUVerFrame::getPixels() const +{ + return ( m_uiWidth * m_uiHeight ); +} + UInt PlaYUVerFrame::getChromaWidth() const { if( m_pcPelFormat->colorSpace == GRAY ) @@ -260,6 +271,11 @@ UInt PlaYUVerFrame::getChromaLength() const return getChromaWidth() * getChromaHeight(); } +UInt PlaYUVerFrame::getChromaSize() const +{ + return getChromaWidth() * getChromaHeight(); +} + Void PlaYUVerFrame::frameFromBuffer( Byte *Buff, UInt64 uiBuffSize ) { if( uiBuffSize != getBytesPerFrame() ) @@ -428,6 +444,342 @@ Void PlaYUVerFrame::fillRGBBuffer() m_bHasRGBPel = true; } +// statistics +Void PlaYUVerFrame::calcHistogram() +{ + if( m_bHasHistogram ) + return; + + if( !m_puiHistogram ) + { + //m_puiHistogram = new UInt[m_uiHistoSegments * histoChannels]; + getMem1D( &( m_puiHistogram ), m_uiHistoSegments * m_uiHistoChannels ); + if( !m_puiHistogram ) + { + return; + } + } + m_bRunningFlag = true; + + UInt i, j; + UInt numberChannels = m_pcPelFormat->numberChannels; + Int colorSpace = m_pcPelFormat->colorSpace; + if( colorSpace == PlaYUVerFrame::COLOR_YUV ) + { + const Pel *data[3]; + data[LUMA] = m_pppcInputPel[LUMA][0]; + data[CHROMA_U] = m_pppcInputPel[CHROMA_U][0]; + data[CHROMA_V] = m_pppcInputPel[CHROMA_V][0]; + for( i = 0; i < m_uiHeight * m_uiWidth && m_bRunningFlag; i++ ) + { + m_puiHistogram[*( data[LUMA] ) + LUMA * m_uiHistoSegments]++; + data[LUMA] += 1; + } + for( i = 0; ( i < getChromaSize() ) && m_bRunningFlag; i++ ) + { + for( j = 1; j < numberChannels; j++ ) + { + m_puiHistogram[*( data[j] ) + j * m_uiHistoSegments]++; + data[j] += 1; + } + } + } + else + { + const Pel* data[3]; + Pel luma; + data[COLOR_R] = m_pppcInputPel[COLOR_R][0]; + data[COLOR_G] = m_pppcInputPel[COLOR_G][0]; + data[COLOR_B] = m_pppcInputPel[COLOR_B][0]; + + for( i = 0; ( i < m_uiHeight * m_uiWidth ) && m_bRunningFlag; i++ ) + { + for( j = 0; j < numberChannels; j++ ) + { + m_puiHistogram[*( data[j] ) + j * m_uiHistoSegments]++; + } + if( ( colorSpace == PlaYUVerFrame::COLOR_RGB || colorSpace == PlaYUVerFrame::COLOR_ARGB ) ) + { + PlaYUVerFrame::Pixel currPixel( colorSpace, *( data[COLOR_R] ), *( data[COLOR_G] ), *( data[COLOR_B] ) ); + luma = PlaYUVerFrame::ConvertPixel( currPixel, PlaYUVerFrame::COLOR_YUV ).Y(); + m_puiHistogram[luma + j * m_uiHistoSegments]++; + } + for( j = 0; j < numberChannels; j++ ) + data[j] += 1; + } + } + m_bHasHistogram = true; + m_bRunningFlag = false; +} + +Int PlaYUVerFrame::getHistogramSegment() +{ + return m_uiHistoSegments; +} + +Int PlaYUVerFrame::getRealHistoChannel( Int channel ) +{ + Int histoChannel; + + switch( getColorSpace() ) + { + case PlaYUVerFrame::COLOR_GRAY: + if( channel != LUMA ) + { + return -1; + } + histoChannel = 0; + break; + case PlaYUVerFrame::COLOR_RGB: + if( channel != COLOR_R && channel != COLOR_G && channel != COLOR_B && channel != LUMA ) + { + return -1; + } + else + { + if( channel == LUMA ) + { + histoChannel = 3; + } + else + { + histoChannel = channel; + } + } + break; + case PlaYUVerFrame::COLOR_ARGB: + if( channel != COLOR_R && channel != COLOR_G && channel != COLOR_B && channel != COLOR_A && channel != LUMA ) + { + return -1; + } + else + { + if( channel == LUMA ) + { + histoChannel = 4; + } + else + { + histoChannel = channel; + } + } + break; + case PlaYUVerFrame::COLOR_YUV: + if( channel != LUMA && channel != CHROMA_U && channel != CHROMA_V ) + { + return -1; + } + else + { + histoChannel = channel; + } + break; + default: + histoChannel = -1; + } + return histoChannel; +} + +Double PlaYUVerFrame::getCount( Int channel, UInt start, UInt end ) +{ + UInt i; + Int histoChannel; + Int indexStart; + Double count = 0.0; + + if( !m_bHasHistogram || start < 0 || end > m_uiHistoSegments - 1 || start > end ) + { + return 0.0; + } + + histoChannel = getRealHistoChannel( channel ); + + if( histoChannel == -1 ) + { + return 0.0; + } + + indexStart = histoChannel * m_uiHistoSegments; + + for( i = start; i <= end; i++ ) + { + count += m_puiHistogram[indexStart + i]; + } + return count; +} + + + +Double PlaYUVerFrame::getMean( Int channel, UInt start, UInt end ) +{ + Int indexStart; + Int histoChannel; + Double mean = 0.0; + Double count; + + if( !m_bHasHistogram || start < 0 || end > m_uiHistoSegments - 1 || start > end ) + { + return 0.0; + } + + histoChannel = getRealHistoChannel( channel ); + + if( histoChannel == -1 ) + { + return 0.0; + } + + indexStart = histoChannel * m_uiHistoSegments; + + for( UInt i = start; i <= end; i++ ) + { + mean += i * m_puiHistogram[indexStart + i]; + } + + count = getCount( channel, start, end ); + + if( count > 0.0 ) + { + return mean / count; + } + + return mean; +} + +Int PlaYUVerFrame::getMedian( Int channel, UInt start, UInt end ) +{ + Int histoChannel; + Int indexStart; + Double sum = 0.0; + Double count; + + if( !m_bHasHistogram || start < 0 || end > m_uiHistoSegments - 1 || start > end ) + { + return 0; + } + + histoChannel = getRealHistoChannel( channel ); + + if( histoChannel == -1 ) + { + return 0; + } + + indexStart = histoChannel * m_uiHistoSegments; + + count = getCount( channel, start, end ); + + for( UInt i = start; i <= end; i++ ) + { + sum += m_puiHistogram[indexStart + i]; + if( sum * 2 > count ) + return i; + } + + return 0; +} + +Double PlaYUVerFrame::getStdDev( Int channel, UInt start, UInt end ) +{ + Int histoChannel; + Int indexStart; + Double dev = 0.0; + Double count; + Double mean; + + if( !m_bHasHistogram || start < 0 || end > m_uiHistoSegments - 1 || start > end ) + { + return 0.0; + } + + histoChannel = getRealHistoChannel( channel ); + + if( histoChannel == -1 ) + { + return 0.0; + } + + indexStart = histoChannel * m_uiHistoSegments; + mean = getMean( channel, start, end ); + count = getCount( channel, start, end ); + + if( count == 0.0 ) + count = 1.0; + + /*------------ original + + for ( i = start ; i <= end ; i++ ) + { + dev += ( i - mean ) * ( i - mean ) * m_puiHistogram[indexStart +i]; + } + + return sqrt( dev / count ); + + -----------------------*/ + + for( UInt i = start; i <= end; i++ ) + { + dev += ( i * i ) * m_puiHistogram[indexStart + i]; + } + + return sqrt( ( dev - count * mean * mean ) / ( count - 1 ) ); + +} + +Double PlaYUVerFrame::getHistogramValue( Int channel, UInt bin ) +{ + Double value; + Int histoChannel; + Int indexStart; + + if( !m_bHasHistogram || bin < 0 || bin > m_uiHistoSegments - 1 ) + return 0.0; + + histoChannel = getRealHistoChannel( channel ); + + if( histoChannel == -1 ) + { + return 0.0; + } + + indexStart = histoChannel * m_uiHistoSegments; + + value = m_puiHistogram[indexStart + bin]; + + return value; +} + +Double PlaYUVerFrame::getMaximum( Int channel ) +{ + Double max = 0.0; + + Int histoChannel; + Int indexStart; + + if( !m_bHasHistogram ) + return 0.0; + + histoChannel = getRealHistoChannel( channel ); + + if( histoChannel == -1 ) + { + return 0.0; + } + + indexStart = histoChannel * m_uiHistoSegments; + + for( UInt x = 0; x < m_uiHistoSegments; x++ ) + { + if( m_puiHistogram[indexStart + x] > max ) + { + max = m_puiHistogram[indexStart + x]; + } + } + + return max; +} + + Void PlaYUVerFrame::copyFrom( PlaYUVerFrame* input_frame ) { if( m_iPixelFormat != input_frame->getPelFormat() && m_uiWidth == input_frame->getWidth() && m_uiHeight == input_frame->getHeight() ) diff --git a/lib/PlaYUVerFrame.h b/lib/PlaYUVerFrame.h index 593d9ee..d25aa25 100644 --- a/lib/PlaYUVerFrame.h +++ b/lib/PlaYUVerFrame.h @@ -51,7 +51,8 @@ struct PlaYUVerPixFmtDescriptor; * \ingroup PlaYUVerLib PlaYUVerLib_Frame * \brief Frame handling class */ -class PlaYUVerFrame: public PlaYUVerFrameStats +class PlaYUVerFrame + //: public PlaYUVerFrameStats { public: @@ -214,15 +215,52 @@ public: Int getColorSpace() const; UInt getNumberChannels() const; + + UInt getPixels() const; UInt getChromaWidth() const; UInt getChromaHeight() const; UInt getChromaLength() const; + UInt getChromaSize() const; Void frameFromBuffer( Byte*, UInt64 ); Void frameToBuffer( Byte* ); Void fillRGBBuffer(); + Void calcHistogram(); + + // Methods for to manipulate the histogram data. + Double getCount( Int channel, UInt start, UInt end ); + Double getMean( Int channel, UInt start, UInt end ); + Int getMedian( Int channel, UInt start, UInt end ); + + /** + * @return Number of image pixels + */ + + Double getStdDev( Int channel, UInt start, UInt end ); + Double getHistogramValue( Int channel, UInt bin ); + Double getMaximum( Int channel ); + + /** + * @return Number of histogram segments: 256 or 65536 for 8 or 16 bits per + * sample. + */ + Int getHistogramSegment(); + + /** + * Control calculation + */ + Void setRunningFlag( Bool bFlag ) + { + m_bRunningFlag = bFlag; + } + Bool getHasHistogram() + { + return m_bHasHistogram; + } + + Void copyFrom( PlaYUVerFrame* ); Void copyFrom( PlaYUVerFrame*, UInt, UInt ); @@ -350,6 +388,22 @@ private: Bool m_bHasRGBPel; //!< Flag indicating that the ARGB buffer was computed UChar* m_pcARGB32; //!< Buffer with the ARGB pixels used in Qt libs + /** The histogram data.*/ + UInt* m_puiHistogram; + + /** If the image is RGB and calcLuma is true, we have 1 more channel */ + UInt m_uiHistoChannels; + + /** Numbers of histogram segments depending of image bytes depth*/ + UInt m_uiHistoSegments; + + /** Used to stop thread during calculations.*/ + Bool m_bRunningFlag; + + Int getRealHistoChannel( Int channel ); + + Bool m_bHasHistogram; + /** * Common constructor function of a frame * diff --git a/lib/PlaYUVerFrameStats.cpp b/lib/PlaYUVerFrameStats.cpp deleted file mode 100644 index c6d36f9..0000000 --- a/lib/PlaYUVerFrameStats.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* This file is a part of plaYUVer project - * Copyright (C) 2014-2015 by Luis Lucas (luisfrlucas@gmail.com) - * Joao Carreira (jfmcarreira@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/** - * \file PlaYUVerFrameStats.cpp - * \ingroup PlaYUVerLib - * \brief Measure PlaYUVerFrame statistics - * Based on the work of Ricardo N. Rocha Sardo in SCode project - */ - -#include -#include -#include - -#include "PlaYUVerFrameStats.h" -#include "PlaYUVerFrame.h" -#include "LibMemory.h" - -namespace plaYUVer -{ - -PlaYUVerFrameStats::PlaYUVerFrameStats() : - m_puiHistogram( NULL ), - m_bHasHistogram( false ) -{ -} - -PlaYUVerFrameStats::~PlaYUVerFrameStats() -{ - if( m_puiHistogram ) - { - //delete[] m_puiHistogram; - freeMem1D( m_puiHistogram ); - } - m_puiHistogram = NULL; - m_bHasHistogram = false; -} - -// statistics -Void PlaYUVerFrameStats::xSetupStatistics( const PlaYUVerFrame *pcFrame ) -{ - m_pppImageData = pcFrame->getPelBufferYUV(); - m_uiImageWidth = pcFrame->getWidth(); - m_uiImageHeight = pcFrame->getHeight(); - m_uiChannels = pcFrame->getNumberChannels(); - - m_uiHistoSegments = 1 << pcFrame->getBitsPel(); - imageColorSpace = pcFrame->getColorSpace(); - imageChromaSize = pcFrame->getChromaLength(); - - if( imageColorSpace == PlaYUVerFrame::COLOR_RGB || imageColorSpace == PlaYUVerFrame::COLOR_ARGB ) - histoChannels = m_uiChannels + 1; - else - histoChannels = m_uiChannels; -} - -Void PlaYUVerFrameStats::calcHistogram() -{ - if( m_bHasHistogram ) - return; - - if( !m_puiHistogram ) - { - //m_puiHistogram = new UInt[m_uiHistoSegments * histoChannels]; - getMem1D( &( m_puiHistogram ), m_uiHistoSegments * histoChannels ); - if( !m_puiHistogram ) - { - return; - } - } - m_bRunningFlag = true; - - UInt i, j; - - if( imageColorSpace == PlaYUVerFrame::COLOR_YUV ) - { - const Pel *data[3]; - data[LUMA] = m_pppImageData[LUMA][0]; - data[CHROMA_U] = m_pppImageData[CHROMA_U][0]; - data[CHROMA_V] = m_pppImageData[CHROMA_V][0]; - for( i = 0; i < m_uiImageHeight * m_uiImageWidth && m_bRunningFlag; i++ ) - { - m_puiHistogram[*( data[LUMA] ) + LUMA * m_uiHistoSegments]++; - data[LUMA] += 1; - } - for( i = 0; ( i < imageChromaSize ) && m_bRunningFlag; i++ ) - { - for( j = 1; j < m_uiChannels; j++ ) - { - m_puiHistogram[*( data[j] ) + j * m_uiHistoSegments]++; - data[j] += 1; - } - } - } - else - { - const Pel* data[3]; - Pel luma; - data[COLOR_R] = m_pppImageData[COLOR_R][0]; - data[COLOR_G] = m_pppImageData[COLOR_G][0]; - data[COLOR_B] = m_pppImageData[COLOR_B][0]; - - for( i = 0; ( i < m_uiImageHeight * m_uiImageWidth ) && m_bRunningFlag; i++ ) - { - for( j = 0; j < m_uiChannels; j++ ) - { - m_puiHistogram[*( data[j] ) + j * m_uiHistoSegments]++; - } - if( ( imageColorSpace == PlaYUVerFrame::COLOR_RGB || imageColorSpace == PlaYUVerFrame::COLOR_ARGB ) ) - { - PlaYUVerFrame::Pixel currPixel( imageColorSpace, *( data[COLOR_R] ), *( data[COLOR_G] ), *( data[COLOR_B] ) ); - luma = PlaYUVerFrame::ConvertPixel( currPixel, PlaYUVerFrame::COLOR_YUV ).Y(); - m_puiHistogram[luma + j * m_uiHistoSegments]++; - } - for( j = 0; j < m_uiChannels; j++ ) - data[j] += 1; - } - } - m_bHasHistogram = true; - m_bRunningFlag = false; -} - -Int PlaYUVerFrameStats::getHistogramSegment() -{ - return m_uiHistoSegments; -} - -Int PlaYUVerFrameStats::getRealHistoChannel( Int channel ) -{ - Int histoChannel; - - switch( imageColorSpace ) - { - case PlaYUVerFrame::COLOR_GRAY: - if( channel != LUMA ) - { - return -1; - } - histoChannel = 0; - break; - case PlaYUVerFrame::COLOR_RGB: - if( channel != COLOR_R && channel != COLOR_G && channel != COLOR_B && channel != LUMA ) - { - return -1; - } - else - { - if( channel == LUMA ) - { - histoChannel = 3; - } - else - { - histoChannel = channel; - } - } - break; - case PlaYUVerFrame::COLOR_ARGB: - if( channel != COLOR_R && channel != COLOR_G && channel != COLOR_B && channel != COLOR_A && channel != LUMA ) - { - return -1; - } - else - { - if( channel == LUMA ) - { - histoChannel = 4; - } - else - { - histoChannel = channel; - } - } - break; - case PlaYUVerFrame::COLOR_YUV: - if( channel != LUMA && channel != CHROMA_U && channel != CHROMA_V ) - { - return -1; - } - else - { - histoChannel = channel; - } - break; - default: - histoChannel = -1; - } - return histoChannel; -} - -Double PlaYUVerFrameStats::getCount( Int channel, UInt start, UInt end ) -{ - UInt i; - Int histoChannel; - Int indexStart; - Double count = 0.0; - - if( !m_bHasHistogram || start < 0 || end > m_uiHistoSegments - 1 || start > end ) - { - return 0.0; - } - - histoChannel = getRealHistoChannel( channel ); - - if( histoChannel == -1 ) - { - return 0.0; - } - - indexStart = histoChannel * m_uiHistoSegments; - - for( i = start; i <= end; i++ ) - { - count += m_puiHistogram[indexStart + i]; - } - return count; -} - -Double PlaYUVerFrameStats::getPixels() -{ - if( !m_bHasHistogram ) - { - return 0.0; - } - - return ( m_uiImageWidth * m_uiImageHeight ); -} - -Double PlaYUVerFrameStats::getMean( Int channel, UInt start, UInt end ) -{ - Int indexStart; - Int histoChannel; - Double mean = 0.0; - Double count; - - if( !m_bHasHistogram || start < 0 || end > m_uiHistoSegments - 1 || start > end ) - { - return 0.0; - } - - histoChannel = getRealHistoChannel( channel ); - - if( histoChannel == -1 ) - { - return 0.0; - } - - indexStart = histoChannel * m_uiHistoSegments; - - for( UInt i = start; i <= end; i++ ) - { - mean += i * m_puiHistogram[indexStart + i]; - } - - count = getCount( channel, start, end ); - - if( count > 0.0 ) - { - return mean / count; - } - - return mean; -} - -Int PlaYUVerFrameStats::getMedian( Int channel, UInt start, UInt end ) -{ - Int histoChannel; - Int indexStart; - Double sum = 0.0; - Double count; - - if( !m_bHasHistogram || start < 0 || end > m_uiHistoSegments - 1 || start > end ) - { - return 0; - } - - histoChannel = getRealHistoChannel( channel ); - - if( histoChannel == -1 ) - { - return 0; - } - - indexStart = histoChannel * m_uiHistoSegments; - - count = getCount( channel, start, end ); - - for( UInt i = start; i <= end; i++ ) - { - sum += m_puiHistogram[indexStart + i]; - if( sum * 2 > count ) - return i; - } - - return 0; -} - -Double PlaYUVerFrameStats::getStdDev( Int channel, UInt start, UInt end ) -{ - Int histoChannel; - Int indexStart; - Double dev = 0.0; - Double count; - Double mean; - - if( !m_bHasHistogram || start < 0 || end > m_uiHistoSegments - 1 || start > end ) - { - return 0.0; - } - - histoChannel = getRealHistoChannel( channel ); - - if( histoChannel == -1 ) - { - return 0.0; - } - - indexStart = histoChannel * m_uiHistoSegments; - mean = getMean( channel, start, end ); - count = getCount( channel, start, end ); - - if( count == 0.0 ) - count = 1.0; - - /*------------ original - - for ( i = start ; i <= end ; i++ ) - { - dev += ( i - mean ) * ( i - mean ) * m_puiHistogram[indexStart +i]; - } - - return sqrt( dev / count ); - - -----------------------*/ - - for( UInt i = start; i <= end; i++ ) - { - dev += ( i * i ) * m_puiHistogram[indexStart + i]; - } - - return sqrt( ( dev - count * mean * mean ) / ( count - 1 ) ); - -} - -Double PlaYUVerFrameStats::getHistogramValue( Int channel, UInt bin ) -{ - Double value; - Int histoChannel; - Int indexStart; - - if( !m_bHasHistogram || bin < 0 || bin > m_uiHistoSegments - 1 ) - return 0.0; - - histoChannel = getRealHistoChannel( channel ); - - if( histoChannel == -1 ) - { - return 0.0; - } - - indexStart = histoChannel * m_uiHistoSegments; - - value = m_puiHistogram[indexStart + bin]; - - return value; -} - -Double PlaYUVerFrameStats::getMaximum( Int channel ) -{ - Double max = 0.0; - - Int histoChannel; - Int indexStart; - - if( !m_bHasHistogram ) - return 0.0; - - histoChannel = getRealHistoChannel( channel ); - - if( histoChannel == -1 ) - { - return 0.0; - } - - indexStart = histoChannel * m_uiHistoSegments; - - for( UInt x = 0; x < m_uiHistoSegments; x++ ) - { - if( m_puiHistogram[indexStart + x] > max ) - { - max = m_puiHistogram[indexStart + x]; - } - } - - return max; -} - -} // NAMESPACE - diff --git a/lib/PlaYUVerFrameStats.h b/lib/PlaYUVerFrameStats.h deleted file mode 100644 index 0d42fc3..0000000 --- a/lib/PlaYUVerFrameStats.h +++ /dev/null @@ -1,111 +0,0 @@ -/* This file is a part of plaYUVer project - * Copyright (C) 2014-2015 by Luis Lucas (luisfrlucas@gmail.com) - * Joao Carreira (jfmcarreira@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/** - * \file PlaYUVerFrameStats.h - * \ingroup PlaYUVerLib - * \brief Measure PlaYUVerFrame statistics - * Based on the work of Ricardo N. Rocha Sardo in SCode project - */ - -#ifndef __PLAYUVERFRAMESTATS_H__ -#define __PLAYUVERFRAMESTATS_H__ - -#include "PlaYUVerDefs.h" - -namespace plaYUVer -{ - -class PlaYUVerFrame; - -class PlaYUVerFrameStats -{ - -public: - - PlaYUVerFrameStats(); - ~PlaYUVerFrameStats(); - - Void calcHistogram(); - - // Methods for to manipulate the histogram data. - Double getCount( Int channel, UInt start, UInt end ); - Double getMean( Int channel, UInt start, UInt end ); - Int getMedian( Int channel, UInt start, UInt end ); - - /** - * @return Number of image pixels - */ - Double getPixels(); - Double getStdDev( Int channel, UInt start, UInt end ); - Double getHistogramValue( Int channel, UInt bin ); - Double getMaximum( Int channel ); - - /** - * @return Number of histogram segments: 256 or 65536 for 8 or 16 bits per - * sample. - */ - Int getHistogramSegment(); - - /** - * Control calculation - */ - Void setRunningFlag( Bool bFlag ) - { - m_bRunningFlag = bFlag; - } - Bool getHasHistogram() - { - return m_bHasHistogram; - } -private: - - /** The histogram data.*/ - UInt* m_puiHistogram; - - /** If the image is RGB and calcLuma is true, we have 1 more channel */ - Int histoChannels; - - /** Image information.*/ - Pel*** m_pppImageData; - UInt m_uiImageWidth; - UInt m_uiImageHeight; - UInt m_uiChannels; - Int imageColorSpace; - UInt imageChromaSize; - - /** Numbers of histogram segments dependaing of image bytes depth*/ - UInt m_uiHistoSegments; - - /** Used to stop thread during calculations.*/ - Bool m_bRunningFlag; - - Int getRealHistoChannel( Int channel ); - -protected: - - Bool m_bHasHistogram; - - Void xSetupStatistics( const PlaYUVerFrame *pcFrame ); - -}; - -} // NAMESPACE - -#endif // __PLAYUVERFRAMESTATS_H__