diff --git a/source/app/ModulesHandle.cpp b/source/app/ModulesHandle.cpp index 4a5a838..348d7a6 100644 --- a/source/app/ModulesHandle.cpp +++ b/source/app/ModulesHandle.cpp @@ -66,7 +66,7 @@ SubWindowHandle* ModulesHandle::processModuleHandlingOpt() if( m_iOptionSelected >= 0 ) { PlaYUVerModuleIf* pcCurrModuleIf = m_pcPlaYUVerModules.at( m_iOptionSelected ); - + m_iOptionSelected = INVALID_OPT; if( pcCurrModuleIf->m_pcAction->isChecked() ) { return enableModuleIf( pcCurrModuleIf ); diff --git a/source/app/PropertiesSidebar.cpp b/source/app/PropertiesSidebar.cpp index 1344f87..69d7a03 100644 --- a/source/app/PropertiesSidebar.cpp +++ b/source/app/PropertiesSidebar.cpp @@ -491,22 +491,25 @@ Void FramePropertiesSideBar::setSelection( const QRect &selectionArea ) // This is necessary to stop computation because image.bits() is // currently used by threaded histogram algorithm. - m_cSelectionArea = selectionArea; + if( m_pcFrame ) + { + m_cSelectionArea = selectionArea; - if( selectionArea.isValid() ) - { - histogramWidget->stopHistogramComputation(); - histogramWidget->updateSelectionData( new PlaYUVerFrame(m_pcFrame, selectionArea)); - fullImageButton->show(); - selectionImageButton->show(); - selectionImageButton->click(); - slotRenderingChanged( HistogramWidget::ImageSelectionHistogram ); - } - else - { - fullImageButton->hide(); - selectionImageButton->hide(); - slotRenderingChanged( HistogramWidget::FullImageHistogram ); + if( selectionArea.isValid() ) + { + histogramWidget->stopHistogramComputation(); + histogramWidget->updateSelectionData( new PlaYUVerFrame(m_pcFrame, selectionArea)); + fullImageButton->show(); + selectionImageButton->show(); + selectionImageButton->click(); + slotRenderingChanged( HistogramWidget::ImageSelectionHistogram ); + } + else + { + fullImageButton->hide(); + selectionImageButton->hide(); + slotRenderingChanged( HistogramWidget::FullImageHistogram ); + } } } diff --git a/source/app/SubWindowHandle.cpp b/source/app/SubWindowHandle.cpp index 87f91a4..2f9317c 100644 --- a/source/app/SubWindowHandle.cpp +++ b/source/app/SubWindowHandle.cpp @@ -52,6 +52,7 @@ SubWindowHandle::SubWindowHandle( QWidget * parent, Bool isModule ) : m_cViewArea = new ViewArea( m_cScrollArea ); connect( m_cViewArea, SIGNAL( zoomFactorChanged( double , QPoint) ), this, SLOT( adjustScrollBarByZoom(double, QPoint) ) ); connect( m_cViewArea, SIGNAL( moveScroll( QPoint ) ), this, SLOT( adjustScrollBarByOffset(QPoint) ) ); + connect( m_cViewArea, SIGNAL( selectionChanged( QRect ) ), this, SLOT( updateSelectedArea( QRect ) ) ); connect( m_cScrollArea->horizontalScrollBar(), SIGNAL( actionTriggered( int ) ), this, SLOT( updateLastScrollValue() ) ); connect( m_cScrollArea->verticalScrollBar(), SIGNAL( actionTriggered( int ) ), this, SLOT( updateLastScrollValue() ) ); @@ -145,6 +146,11 @@ Bool SubWindowHandle::loadFile( PlaYUVerStreamInfo* streamInfo ) return true; } +Void SubWindowHandle::updateSelectedArea( QRect area ) +{ + m_cSelectedArea = area; +} + /** * Functions to enable a module in the * current SubWindow @@ -230,31 +236,17 @@ Bool SubWindowHandle::save( QString filename ) { Bool iRet = false; QApplication::setOverrideCursor( Qt::WaitCursor ); - if( !m_pCurrStream ) + + PlaYUVerFrame* saveFrame = m_pcCurrFrame; + if( m_cSelectedArea.isValid() ) { - if( !m_pcCurrFrame ) - { - return false; - } - Int iFileFormat = PlaYUVerStream::INVALID_INPUT; - QStringList formatsExt = PlaYUVerStream::supportedReadFormatsExt(); - QString currExt = QFileInfo( filename ).suffix(); - if( formatsExt.contains( currExt ) ) - { - iFileFormat = formatsExt.indexOf( currExt ); - } - if( iFileFormat == PlaYUVerStream::YUVINPUT ) - { - return false; - } - m_pcCurrFrame->FrametoRGB8(); - QImage qimg = QImage( m_pcCurrFrame->getQImageBuffer(), m_pcCurrFrame->getWidth(), m_pcCurrFrame->getHeight(), QImage::Format_RGB888 ); - iRet = qimg.save( filename ); + saveFrame = new PlaYUVerFrame( m_pcCurrFrame, m_cSelectedArea ); } - else + if( !saveFrame ) { - iRet = m_pCurrStream->saveFrame( filename ); + return false; } + iRet = PlaYUVerStream::saveFrame( filename, saveFrame ); QApplication::restoreOverrideCursor(); return iRet; } diff --git a/source/app/SubWindowHandle.h b/source/app/SubWindowHandle.h index 34c2f5d..d94715a 100644 --- a/source/app/SubWindowHandle.h +++ b/source/app/SubWindowHandle.h @@ -52,6 +52,7 @@ private: PlaYUVerStream* m_pCurrStream; PlaYUVerFrame* m_pcCurrFrame; + QRect m_cSelectedArea; QString m_cFilename; PlaYUVerModuleIf* m_pcCurrentModule; @@ -214,6 +215,7 @@ protected: void closeEvent( QCloseEvent *event ); public Q_SLOTS: + void updateSelectedArea( QRect area ); void adjustScrollBarByZoom( double factor, QPoint center ); void adjustScrollBarByOffset( QPoint Offset ); void updateLastScrollValue(); diff --git a/source/app/ViewArea.cpp b/source/app/ViewArea.cpp index e787fe9..80414b3 100644 --- a/source/app/ViewArea.cpp +++ b/source/app/ViewArea.cpp @@ -436,7 +436,7 @@ void ViewArea::paintEvent( QPaintEvent *event ) QRect imgr = viewToWindow( QRect( 0, 0, m_pixmap.width(), m_pixmap.height() ) ); myPath.addRect( imgr ); - myPath.addRect( sr/*m_selectedArea*/); + myPath.addRect( sr); //m_selectedArea painter.drawPath( myPath ); // 2) Draw the selection rectangle @@ -641,7 +641,7 @@ void ViewArea::mouseMoveEvent( QMouseEvent *event ) { // If the selection is only vertical or horizontal then we have one // of the dimentions null. - if( actualPos.x() == m_lastPos.x() || actualPos.y() == m_lastPos.y() ) + if( actualPos.x() == m_lastPos.x() && actualPos.y() == m_lastPos.y() ) { m_selectedArea = QRect(); } @@ -651,14 +651,14 @@ void ViewArea::mouseMoveEvent( QMouseEvent *event ) // From left to right if( m_lastPos.x() < actualPos.x() ) { - QPoint bottomR = actualPos - QPoint( 1, 1 ); + QPoint bottomR = actualPos;// - QPoint( 1, 1 ); m_selectedArea = QRect( m_lastPos, bottomR ); } // From right to left else { QPoint topL( actualPos.x(), m_lastPos.y() ); - QPoint bottomR( m_lastPos.x() - 1, actualPos.y() - 1 ); + QPoint bottomR( m_lastPos.x(), actualPos.y() ); m_selectedArea = QRect( topL, bottomR ); } @@ -670,13 +670,13 @@ void ViewArea::mouseMoveEvent( QMouseEvent *event ) if( m_lastPos.x() < actualPos.x() ) { QPoint topL( m_lastPos.x(), actualPos.y() ); - QPoint bottomR( actualPos.x() - 1, m_lastPos.y() - 1 ); + QPoint bottomR( actualPos.x(), m_lastPos.y() ); m_selectedArea = QRect( topL, bottomR ); } // From right to left else { - QPoint bottomR = m_lastPos - QPoint( 1, 1 ); + QPoint bottomR = m_lastPos;// - QPoint( 1, 1 ); m_selectedArea = QRect( actualPos, bottomR ); } } @@ -702,15 +702,16 @@ void ViewArea::mouseMoveEvent( QMouseEvent *event ) m_selectedArea &= QRect( 0, 0, m_pixmap.width(), m_pixmap.height() ); // Update only the united area - updateRect = updateRect.united( viewToWindow( m_selectedArea ) ); +// updateRect = updateRect.united( viewToWindow( m_selectedArea ) ); // "When rendering with a one pixel wide pen the QRect's // boundary line will be rendered to the right and below the // mathematical rectangle's boundary line.", in QT4 doc. // Our selection pen width is 1, let's adjust the rendering area. - updateRect.adjust( 0, 0, 1, 1 ); +// updateRect.adjust( 0, 0, 1, 1 ); - update( updateRect.normalized() ); +// update( updateRect.normalized() ); + update(); } return; } diff --git a/source/lib/PlaYUVerFrame.cpp b/source/lib/PlaYUVerFrame.cpp index 05f8b58..a68f797 100644 --- a/source/lib/PlaYUVerFrame.cpp +++ b/source/lib/PlaYUVerFrame.cpp @@ -80,6 +80,7 @@ PlaYUVerFrame::PlaYUVerFrame( PlaYUVerFrame *other ) PlaYUVerFrame::PlaYUVerFrame( PlaYUVerFrame *other, QRect area ) { + adjustSelectedAreaDims( area , other->getPelFormat() ); init( area.width(), area.height(), other->getPelFormat() ); copyFrom( other, area.x(), area.y() ); } @@ -95,6 +96,54 @@ PlaYUVerFrame::~PlaYUVerFrame() closePixfc(); } +Void PlaYUVerFrame::adjustSelectedAreaDims( QRect &area, Int pel_format ) +{ + Int posX = area.x(); + Int posY = area.y(); + Int width = area.width(); + Int height = area.height(); + + switch( pel_format ) + { + case YUV420p: + if( posX%2 ) + area.setX(posX-1); + if( posY%2 ) + area.setY(posY-1); + + if( (posX+width)%2 ) + area.setWidth((posX+width)-area.x()+1); + else + area.setWidth((posX+width)-area.x()); + + if( (posY+height)%2 ) + area.setHeight((posY+height)-area.y()+1); + else + area.setHeight((posY+height)-area.y()); + + break; + case YUV444p: + break; + case YUV422p: + case YUYV422: + if( posX%2 ) + area.setX(posX-1); + + if( (posX+width)%2 ) + area.setWidth((posX+width)-area.x()+1); + else + area.setWidth((posX+width)-area.x()); + + break; + case GRAY: + break; + case RGB8: + break; + default: + break; + } +} + Void PlaYUVerFrame::init( UInt width, UInt height, Int pel_format ) { m_pppcInputPel = NULL; @@ -476,42 +525,41 @@ Void PlaYUVerFrame::copyFrom( PlaYUVerFrame* input_frame, UInt xPos, UInt yPos ) case YUV420p: for( UInt i = 0; i < m_uiHeight / 2; i++ ) { - memcpy( m_pppcInputPel[LUMA][0], &( input_frame->getPelBufferYUV()[LUMA][yPos + ( i << 1 )][xPos] ), m_uiWidth * sizeof(Pel) ); - memcpy( m_pppcInputPel[LUMA][0], &( input_frame->getPelBufferYUV()[LUMA][yPos + ( i << 1 ) + 1][xPos] ), m_uiWidth * sizeof(Pel) ); - memcpy( m_pppcInputPel[CHROMA_U][0], &( input_frame->getPelBufferYUV()[CHROMA_U][yPos / 2 + i][xPos / 2] ), m_uiWidth / 2 * sizeof(Pel) ); - memcpy( m_pppcInputPel[CHROMA_V][0], &( input_frame->getPelBufferYUV()[CHROMA_V][yPos / 2 + i][xPos / 2] ), m_uiWidth / 2 * sizeof(Pel) ); + memcpy( m_pppcInputPel[LUMA][(i<<1)], &( input_frame->getPelBufferYUV()[LUMA][yPos + ( i << 1 )][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[LUMA][(i<<1) + 1], &( input_frame->getPelBufferYUV()[LUMA][yPos + ( i << 1 ) + 1][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[CHROMA_U][i], &( input_frame->getPelBufferYUV()[CHROMA_U][yPos / 2 + i][xPos / 2] ), m_uiWidth / 2 * sizeof(Pel) ); + memcpy( m_pppcInputPel[CHROMA_V][i], &( input_frame->getPelBufferYUV()[CHROMA_V][yPos / 2 + i][xPos / 2] ), m_uiWidth / 2 * sizeof(Pel) ); } break; case YUV444p: for( UInt i = 0; i < m_uiHeight; i++ ) { - memcpy( m_pppcInputPel[LUMA][0], &( input_frame->getPelBufferYUV()[LUMA][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); - memcpy( m_pppcInputPel[CHROMA_U][0], &( input_frame->getPelBufferYUV()[CHROMA_U][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); - memcpy( m_pppcInputPel[CHROMA_V][0], &( input_frame->getPelBufferYUV()[CHROMA_V][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[LUMA][i], &( input_frame->getPelBufferYUV()[LUMA][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[CHROMA_U][i], &( input_frame->getPelBufferYUV()[CHROMA_U][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[CHROMA_V][i], &( input_frame->getPelBufferYUV()[CHROMA_V][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); } break; case YUV422p: case YUYV422: - for( UInt i = 0; i < m_uiHeight / 2; i++ ) + for( UInt i = 0; i < m_uiHeight; i++ ) { - memcpy( m_pppcInputPel[LUMA][0], &( input_frame->getPelBufferYUV()[LUMA][yPos + ( i << 1 )][xPos] ), m_uiWidth * sizeof(Pel) ); - memcpy( m_pppcInputPel[LUMA][0], &( input_frame->getPelBufferYUV()[LUMA][yPos + ( i << 1 ) + 1][xPos] ), m_uiWidth * sizeof(Pel) ); - memcpy( m_pppcInputPel[CHROMA_U][0], &( input_frame->getPelBufferYUV()[CHROMA_U][yPos + i][xPos / 2] ), m_uiWidth / 2 * sizeof(Pel) ); - memcpy( m_pppcInputPel[CHROMA_V][0], &( input_frame->getPelBufferYUV()[CHROMA_V][yPos + i][xPos / 2] ), m_uiWidth / 2 * sizeof(Pel) ); + memcpy( m_pppcInputPel[LUMA][i], &( input_frame->getPelBufferYUV()[LUMA][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[CHROMA_U][i], &( input_frame->getPelBufferYUV()[CHROMA_U][yPos + i][xPos / 2] ), m_uiWidth / 2 * sizeof(Pel) ); + memcpy( m_pppcInputPel[CHROMA_V][i], &( input_frame->getPelBufferYUV()[CHROMA_V][yPos + i][xPos / 2] ), m_uiWidth / 2 * sizeof(Pel) ); } break; case GRAY: for( UInt i = 0; i < m_uiHeight; i++ ) { - memcpy( m_pppcInputPel[LUMA][0], &( input_frame->getPelBufferYUV()[LUMA][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[LUMA][i], &( input_frame->getPelBufferYUV()[LUMA][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); } break; case RGB8: for( UInt i = 0; i < m_uiHeight; i++ ) { - memcpy( m_pppcInputPel[COLOR_R][0], &( input_frame->getPelBufferYUV()[LUMA][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); - memcpy( m_pppcInputPel[COLOR_G][0], &( input_frame->getPelBufferYUV()[CHROMA_U][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); - memcpy( m_pppcInputPel[COLOR_B][0], &( input_frame->getPelBufferYUV()[CHROMA_V][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[COLOR_R][i], &( input_frame->getPelBufferYUV()[LUMA][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[COLOR_G][i], &( input_frame->getPelBufferYUV()[CHROMA_U][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); + memcpy( m_pppcInputPel[COLOR_B][i], &( input_frame->getPelBufferYUV()[CHROMA_V][yPos + i][xPos] ), m_uiWidth * sizeof(Pel) ); } break; default: diff --git a/source/lib/PlaYUVerFrame.h b/source/lib/PlaYUVerFrame.h index 8a508b8..e5fcd61 100644 --- a/source/lib/PlaYUVerFrame.h +++ b/source/lib/PlaYUVerFrame.h @@ -201,6 +201,7 @@ private: Pel*** m_pppcInputPel; UChar* m_pcRGBPelInterlaced; + Void adjustSelectedAreaDims( QRect &area, Int pel_format ); Void init( UInt width, UInt height, Int pel_format ); Void openPixfc(); Void closePixfc(); diff --git a/source/lib/PlaYUVerStream.cpp b/source/lib/PlaYUVerStream.cpp index 8d06d41..05029c9 100644 --- a/source/lib/PlaYUVerStream.cpp +++ b/source/lib/PlaYUVerStream.cpp @@ -581,30 +581,35 @@ Void PlaYUVerStream::writeFrame( PlaYUVerFrame *pcFrame ) Bool PlaYUVerStream::saveFrame( const QString& filename ) { - Int iFileFormat = INVALID_INPUT; + return saveFrame( filename, m_pcCurrFrame ); +} - QStringList formatsExt = PlaYUVerStream::supportedReadFormatsExt(); +Bool PlaYUVerStream::saveFrame( const QString& filename, PlaYUVerFrame *saveFrame ) +{ + Int iFileFormat = INVALID_OUTPUT; + + QStringList formatsExt = PlaYUVerStream::supportedSaveFormatsExt(); QString currExt = QFileInfo( filename ).suffix(); if( formatsExt.contains( currExt ) ) { iFileFormat = formatsExt.indexOf( currExt ); } - if( iFileFormat == YUVINPUT ) + if( iFileFormat < TOTAL_OUTPUT_FORMATS ) { PlaYUVerStream auxFrameStream; - if( !auxFrameStream.open( filename, m_uiWidth, m_uiHeight, m_iPixelFormat, m_uiFrameRate, false ) ) + if( !auxFrameStream.open( filename, saveFrame->getWidth(), saveFrame->getHeight(), saveFrame->getPelFormat(), 1, false ) ) { return false; } - auxFrameStream.writeFrame( m_pcCurrFrame ); + auxFrameStream.writeFrame( saveFrame ); auxFrameStream.close(); return true; } else { - m_pcCurrFrame->FrametoRGB8(); - QImage qimg = QImage( m_pcCurrFrame->getQImageBuffer(), m_pcCurrFrame->getWidth(), m_pcCurrFrame->getHeight(), QImage::Format_RGB888 ); + saveFrame->FrametoRGB8(); + QImage qimg = QImage( saveFrame->getQImageBuffer(), saveFrame->getWidth(), saveFrame->getHeight(), QImage::Format_RGB888 ); return qimg.save( filename ); } return false; diff --git a/source/lib/PlaYUVerStream.h b/source/lib/PlaYUVerStream.h index 60f2f2b..7c43941 100644 --- a/source/lib/PlaYUVerStream.h +++ b/source/lib/PlaYUVerStream.h @@ -174,21 +174,23 @@ public: static QStringList supportedSaveFormatsExt() { QStringList formatsExt; - formatsExt << "yuv" + formatsExt << supportedWriteFormatsExt() << "bmp" << "jpeg" << "png" // portable network graphics ; + formatsExt.removeDuplicates(); return formatsExt; } static QStringList supportedSaveFormatsName() { QStringList formatsName; - formatsName << "Raw Video" + formatsName << supportedWriteFormatsName() << "Windows Bitmap" << "Joint Photographic Experts Group" << "Portable Network Graphics"; + formatsName.removeDuplicates(); return formatsName; } @@ -248,6 +250,7 @@ public: Void writeFrame( PlaYUVerFrame *pcFrame ); Bool saveFrame( const QString& filename ); + static Bool saveFrame( const QString& filename, PlaYUVerFrame *saveFrame ); Void setNextFrame(); PlaYUVerFrame* getCurrFrame();