diff --git a/app/VideoHandle.cpp b/app/VideoHandle.cpp index 24bd95f..70c6b42 100644 --- a/app/VideoHandle.cpp +++ b/app/VideoHandle.cpp @@ -42,6 +42,7 @@ #include "SubWindowSelectorDialog.h" #include "VideoStreamSubWindow.h" #include "VideoSubWindow.h" +#include "lib/CalypFrame.h" VideoHandle::VideoHandle( QWidget* parent, SubWindowHandle* windowManager ) : m_pcParent( parent ), m_pcMainWindowManager( windowManager ) @@ -123,6 +124,24 @@ void VideoHandle::createActions() connect( m_pcFrameSlider, SIGNAL( valueChanged( int ) ), this, SLOT( seekSliderEvent( int ) ) ); // ------------ Image ------------ + m_mapperComponent = new QSignalMapper( this ); + m_actionGroupComponent = new QActionGroup( this ); + m_actionGroupComponent->setExclusive( true ); + m_mapperComponent->setMapping( m_actionGroupComponent->addAction( "All" ), -1 ); + m_mapperComponent->setMapping( m_actionGroupComponent->addAction( "Red" ), 0 ); + m_mapperComponent->setMapping( m_actionGroupComponent->addAction( "Green" ), 1 ); + m_mapperComponent->setMapping( m_actionGroupComponent->addAction( "Blue" ), 2 ); + m_mapperComponent->setMapping( m_actionGroupComponent->addAction( "Alpha" ), 3 ); + for( int i = 0; i < m_actionGroupComponent->actions().size(); i++ ) + { + m_actionGroupComponent->actions().at( i )->setCheckable( true ); + m_actionGroupComponent->actions().at( i )->setVisible( false ); + connect( m_actionGroupComponent->actions().at( i ), SIGNAL( triggered() ), m_mapperComponent, SLOT( map() ) ); + } + m_actionGroupComponent->actions().at( 0 )->setChecked( true ); + m_actionGroupComponent->actions().at( 0 )->setVisible( true ); + connect( m_mapperComponent, SIGNAL( mapped( int ) ), this, SLOT( setComponent( int ) ) ); + m_actionGroupTools = new QActionGroup( this ); m_actionGroupTools->setExclusive( true ); @@ -158,9 +177,11 @@ void VideoHandle::createActions() m_mapperGrid = new QSignalMapper( this ); m_actionGroupGrid = new QActionGroup( this ); m_actionGroupGrid->setExclusive( true ); + m_mapperGrid->setMapping( m_actionGroupGrid->addAction( "4x4" ), 4 ); m_mapperGrid->setMapping( m_actionGroupGrid->addAction( "8x8" ), 8 ); m_mapperGrid->setMapping( m_actionGroupGrid->addAction( "16x16" ), 16 ); m_mapperGrid->setMapping( m_actionGroupGrid->addAction( "64x64" ), 64 ); + m_mapperGrid->setMapping( m_actionGroupGrid->addAction( "128x128" ), 128 ); for( int i = 0; i < m_actionGroupGrid->actions().size(); i++ ) { @@ -194,6 +215,8 @@ QMenu* VideoHandle::createVideoMenu() QMenu* VideoHandle::createImageMenu() { m_pcMenuImage = new QMenu( "Image", m_pcParent ); + m_menuComponent = m_pcMenuImage->addMenu( "Component" ); + m_menuComponent->addActions( m_actionGroupComponent->actions() ); m_pcMenuImage->addAction( m_arrayActions[NAVIGATION_TOOL_ACT] ); m_pcMenuImage->addAction( m_arrayActions[SELECTION_TOOL_ACT] ); m_pcMenuImage->addAction( m_arrayActions[BLOCK_SELECTION_TOOL_ACT] ); @@ -268,6 +291,62 @@ QWidget* VideoHandle::createStatusBarMessage() return pcStatusBarWidget; } +void VideoHandle::updateComponentMenu() +{ + VideoSubWindow* pcSubWindow = m_pcMainWindowManager->activeSubWindow(); + if( pcSubWindow == nullptr ) + { + m_menuComponent->setEnabled( false ); + return; + } + + const auto* frame = pcSubWindow->getCurrFrame(); + if( frame == nullptr ) + { + m_menuComponent->setEnabled( false ); + return; + } + + m_menuComponent->setEnabled( true ); + for( int i = 1; i < m_actionGroupComponent->actions().size(); i++ ) + { + m_actionGroupComponent->actions()[i]->setChecked( false ); + m_actionGroupComponent->actions()[i]->setVisible( false ); + } + switch( frame->getColorSpace() ) + { + case CLP_COLOR_GRAY: + m_actionGroupComponent->actions().at( 1 )->setText( QStringLiteral( "Gray" ) ); + m_actionGroupComponent->actions().at( 1 )->setVisible( true ); + break; + case CLP_COLOR_YUV: + m_actionGroupComponent->actions().at( 1 )->setText( QStringLiteral( "Luminance" ) ); + m_actionGroupComponent->actions().at( 1 )->setVisible( true ); + m_actionGroupComponent->actions().at( 2 )->setText( QStringLiteral( "Chrominance U (Cb)" ) ); + m_actionGroupComponent->actions().at( 2 )->setVisible( true ); + m_actionGroupComponent->actions().at( 3 )->setText( QStringLiteral( "Chrominance V (Cr)" ) ); + m_actionGroupComponent->actions().at( 3 )->setVisible( true ); + break; + case CLP_COLOR_RGBA: + m_actionGroupComponent->actions().at( 4 )->setText( QStringLiteral( "Alpha" ) ); + m_actionGroupComponent->actions().at( 4 )->setVisible( true ); + [[fallthrough]]; + case CLP_COLOR_RGB: + m_actionGroupComponent->actions().at( 1 )->setText( QStringLiteral( "Red" ) ); + m_actionGroupComponent->actions().at( 1 )->setVisible( true ); + m_actionGroupComponent->actions().at( 2 )->setText( QStringLiteral( "Green" ) ); + m_actionGroupComponent->actions().at( 2 )->setVisible( true ); + m_actionGroupComponent->actions().at( 3 )->setText( QStringLiteral( "Blue" ) ); + m_actionGroupComponent->actions().at( 3 )->setVisible( true ); + break; + default: + Q_ASSERT( false ); + } + auto component = pcSubWindow->getViewArea()->getFilteredChannel(); + int idx = component.has_value() ? *component : 0; + m_actionGroupComponent->actions().at( idx )->setChecked( true ); +} + void VideoHandle::updateMenus() { VideoSubWindow* pcSubWindow = m_pcMainWindowManager->activeSubWindow(); @@ -296,6 +375,8 @@ void VideoHandle::updateMenus() m_arrayActions[SELECTION_TOOL_ACT]->setEnabled( hasSubWindow ); m_arrayActions[BLOCK_SELECTION_TOOL_ACT]->setEnabled( hasSubWindow ); m_arrayActions[SHOW_GRID_ACT]->setEnabled( hasSubWindow ); + + updateComponentMenu(); } void VideoHandle::readSettings() @@ -860,6 +941,20 @@ void VideoHandle::videoSelectionButtonEvent() } } +void VideoHandle::setComponent( int component ) +{ + if( m_pcCurrentVideoSubWindow == nullptr ) + return; + if( component < 0 ) + { + m_pcCurrentVideoSubWindow->getViewArea()->clearFilteredChannel(); + } + else + { + m_pcCurrentVideoSubWindow->getViewArea()->setFilteredChannel( static_cast( component ) ); + } +} + void VideoHandle::setTool( int tool ) { m_uiViewTool = tool; diff --git a/app/VideoHandle.h b/app/VideoHandle.h index 1b4063d..92bd824 100644 --- a/app/VideoHandle.h +++ b/app/VideoHandle.h @@ -97,6 +97,11 @@ private: QSlider* m_pcFrameSlider; FrameNumberWidget* m_pcFrameNumInfo; + // Filter component actions + QMenu* m_menuComponent; + QActionGroup* m_actionGroupComponent; + QSignalMapper* m_mapperComponent; + // Tools Actions QActionGroup* m_actionGroupTools; QSignalMapper* m_mapperTools; @@ -131,6 +136,7 @@ private: void calculateRealFrameRate(); unsigned long getMaxFrameNumber(); void setTimerStatus(); + void updateComponentMenu(); Q_SIGNALS: void changed(); @@ -150,6 +156,7 @@ private Q_SLOTS: void seekEvent( int direction ); void seekVideo(); void videoSelectionButtonEvent(); + void setComponent( int component ); void setTool( int tool ); void toggleGrid( bool checked ); void setGridSize( int size ); diff --git a/app/ViewArea.cpp b/app/ViewArea.cpp index 4ba0b63..b6eecf1 100644 --- a/app/ViewArea.cpp +++ b/app/ViewArea.cpp @@ -25,6 +25,7 @@ #include "ViewArea.h" +#include #include #include @@ -42,9 +43,11 @@ #include "GridManager.h" -static const QColor selectionColor = Qt::cyan; -static const QColor imageMaskColor = Qt::green; -static const QColor eraserColor = Qt::red; +constexpr auto kSelectionColor = QColorConstants::Cyan; +constexpr auto kImageMaskColor = QColorConstants::Green; +constexpr auto kEraserColor = QColorConstants::Red; +constexpr double kMaxZoom = 100.0; +constexpr double kMinZoom = 0.01; ViewArea::ViewArea( QWidget* parent ) : QWidget( parent ) @@ -53,15 +56,6 @@ ViewArea::ViewArea( QWidget* parent ) m_grid = GridManager(); m_mask = QBitmap(); m_selectedArea = QRect(); - m_dZoomFactor = 1; - m_xOffset = 0; - m_yOffset = 0; - m_mode = NormalMode; - m_eTool = NavigationTool; - m_bGridVisible = false; - m_snapToGrid = false; - m_blockTrackEnable = false; - m_visibleZoomRect = true; m_zoomWinTimer.setSingleShot( true ); m_zoomWinTimer.setInterval( 2000 ); @@ -72,7 +66,15 @@ void ViewArea::setImage( std::shared_ptr frame ) { m_nextFrame = frame; m_uiPixelHalfScale = 1 << ( m_nextFrame->getBitsPel() - 1 ); - m_nextFrame->fillRGBBuffer(); + if( m_filterSingleChannel.has_value() ) + { + m_nextFrame->fillRGBBuffer( m_filterSingleChannel ); + } + else + { + m_nextFrame->fillRGBBuffer(); + } + m_image = QImage( m_nextFrame->getRGBBuffer(), m_nextFrame->getWidth(), m_nextFrame->getHeight(), @@ -86,14 +88,47 @@ void ViewArea::setImage( std::shared_ptr frame ) initZoomWinRect(); } -void ViewArea::clear() +// void ViewArea::clear() +// { +// m_image = QImage(); +// m_mask = QBitmap(); +// m_mode = NormalMode; +// updateSize(); +// update(); +// updateGeometry(); +// } + +auto ViewArea::getFilteredChannel() -> std::optional { - m_image = QImage(); - m_mask = QBitmap(); - m_mode = NormalMode; - updateSize(); + return m_filterSingleChannel; +} + +void ViewArea::setFilteredChannel( std::size_t channel ) +{ + m_filterSingleChannel = channel; + if( m_nextFrame != nullptr ) + { + m_nextFrame->fillRGBBuffer( m_filterSingleChannel ); + m_image = QImage( m_nextFrame->getRGBBuffer(), + m_nextFrame->getWidth(), + m_nextFrame->getHeight(), + QImage::Format_ARGB32 ); + } + update(); +} + +void ViewArea::clearFilteredChannel() +{ + m_filterSingleChannel = {}; + if( m_nextFrame != nullptr ) + { + m_nextFrame->fillRGBBuffer( m_filterSingleChannel ); + m_image = QImage( m_nextFrame->getRGBBuffer(), + m_nextFrame->getWidth(), + m_nextFrame->getHeight(), + QImage::Format_ARGB32 ); + } update(); - updateGeometry(); } void ViewArea::setTool( unsigned int view ) @@ -161,14 +196,14 @@ void ViewArea::setZoomFactor( double f ) double ViewArea::scaleZoomFactor( double scale, QPoint center, QSize minimumSize ) { - double maxZoom = 100.0; - double minZoom = 0.01; //( 1.0 / m_image.width() ); + Q_ASSERT( !m_image.isNull() ); + double new_scale = 1.0; - if( ( m_dZoomFactor == minZoom ) && ( scale < 1 ) ) + if( ( m_dZoomFactor == kMinZoom ) && ( scale < 1 ) ) return new_scale; - if( ( m_dZoomFactor == maxZoom ) && ( scale > 1 ) ) + if( ( m_dZoomFactor == kMaxZoom ) && ( scale > 1 ) ) return new_scale; double newZoomFactor = m_dZoomFactor * scale * 100.0; @@ -209,16 +244,16 @@ double ViewArea::scaleZoomFactor( double scale, QPoint center, QSize minimumSize new_scale = scale; - if( newZoomFactor < minZoom ) + if( newZoomFactor < kMinZoom ) { - newZoomFactor = minZoom; + newZoomFactor = kMinZoom; new_scale = newZoomFactor / m_dZoomFactor; } else { - if( newZoomFactor > maxZoom ) + if( newZoomFactor > kMaxZoom ) { - newZoomFactor = maxZoom; + newZoomFactor = kMaxZoom; new_scale = newZoomFactor / m_dZoomFactor; } } @@ -474,12 +509,12 @@ void ViewArea::paintEvent( QPaintEvent* event ) // Draw a border around the image. /* if( m_xOffset || m_yOffset ) - { - painter.setPen( Qt::black ); - painter.drawRect( m_xOffset - 1, m_yOffset - 1, m_image.width() * - m_dZoomFactor + 1, m_image.height() * - m_dZoomFactor + 1 ); - }*/ + { + painter.setPen( Qt::black ); + painter.drawRect( m_xOffset - 1, m_yOffset - 1, m_image.width() * + m_dZoomFactor + 1, m_image.height() * + m_dZoomFactor + 1 ); + }*/ int frFormat = m_currFrame->getColorSpace(); @@ -567,16 +602,16 @@ void ViewArea::paintEvent( QPaintEvent* event ) QRect vr = windowToView( winRect ); QRect cVisibleImg = vr & cImg; - //cVisibleImg.moveTopLeft(vr.topLeft()); + // cVisibleImg.moveTopLeft(vr.topLeft()); QRect cVisibleWinRect; cVisibleWinRect.setLeft( floor( (double)cVisibleImg.x() / dRatio ) ); cVisibleWinRect.setTop( floor( (double)cVisibleImg.y() / dRatio ) ); cVisibleWinRect.setRight( round( (double)cVisibleImg.right() / dRatio ) ); cVisibleWinRect.setBottom( round( (double)cVisibleImg.bottom() / dRatio ) ); - //painter.fillRect( cImgWinRect, QBrush( QColor( 128, 128, 128, 128 ) ) ); + // painter.fillRect( cImgWinRect, QBrush( QColor( 128, 128, 128, 128 ) ) ); painter.setPen( QColor( 50, 50, 50, 128 ) ); - //painter.drawRect( cImgWinRect ); + // painter.drawRect( cImgWinRect ); painter.setOpacity( 0.7 ); painter.drawImage( cImgWinRect, m_image ); painter.setOpacity( 1 ); @@ -599,7 +634,7 @@ void ViewArea::paintEvent( QPaintEvent* event ) painter.setPen( QColor( 255, 255, 255, 128 ) ); painter.drawRect( cVisibleWinRect ); - //qDebug() << "Debug VisibleZoomRect: " << winRect << vr << cImgWinRect << cVisibleWinRect << cVisibleImg << dRatio; + // qDebug() << "Debug VisibleZoomRect: " << winRect << vr << cImgWinRect << cVisibleWinRect << cVisibleImg << dRatio; } QRect sr = viewToWindow( m_selectedArea ); @@ -610,7 +645,7 @@ void ViewArea::paintEvent( QPaintEvent* event ) if( m_newShape || m_blockTrackEnable ) { // Set the tool color - QColor selectColor = selectionColor; + QColor selectColor = kSelectionColor; selectColor.setAlpha( 120 ); @@ -664,7 +699,7 @@ void ViewArea::paintEvent( QPaintEvent* event ) if( m_maskColor.isValid() ) color = m_maskColor; else - color = imageMaskColor; + color = kImageMaskColor; color.setAlpha( 120 ); painter.setPen( color ); @@ -684,16 +719,16 @@ void ViewArea::paintEvent( QPaintEvent* event ) if( m_maskColor.isValid() ) color = m_maskColor; else - color = imageMaskColor; + color = kImageMaskColor; break; } case EraserTool: { - color = eraserColor; + color = kEraserColor; break; } default: - color = selectionColor; // ?Problems! + color = kSelectionColor; // ?Problems! } color.setAlpha( 120 ); @@ -898,18 +933,18 @@ void ViewArea::mouseMoveEvent( QMouseEvent* event ) } } /* else // if tool() == BlockSelectionTool || MaskTool || EraserTool - { - m_blockTrackEnable = false; - // If cursor is inside the selected area, we most redraw - // the selection rect because it may be smaller. - if( m_selectedArea.contains( actualPos ) ) - { - m_selectedArea = m_grid.rectContains( m_lastPos ); - } + { + m_blockTrackEnable = false; + // If cursor is inside the selected area, we most redraw + // the selection rect because it may be smaller. + if( m_selectedArea.contains( actualPos ) ) + { + m_selectedArea = m_grid.rectContains( m_lastPos ); + } - m_selectedArea = m_selectedArea.united( m_grid.rectContains( actualPos ) ); - } - */ + m_selectedArea = m_selectedArea.united( m_grid.rectContains( actualPos ) ); + } + */ if( tool() == SelectionTool ) { // intercept the selected area with the image area to limit the diff --git a/app/ViewArea.h b/app/ViewArea.h index 160bf00..9c1baa8 100644 --- a/app/ViewArea.h +++ b/app/ViewArea.h @@ -56,17 +56,15 @@ public: ViewArea( QWidget* parent = 0 ); - QImage& image() { return m_image; }; void setImage( std::shared_ptr frame ); + auto getFilteredChannel() -> std::optional; + void setFilteredChannel( std::size_t channel ); + void clearFilteredChannel(); + void setMode( int mode ); void setMaskColor( const QColor& color = QColor() ); - /** - * Clears any contents. - */ - void clear(); - /** * Select tool from the menu */ @@ -108,12 +106,12 @@ public Q_SLOTS: // void setSelectedArea( QRect &rect ); protected: - void paintEvent( QPaintEvent* event ); - void resizeEvent( QResizeEvent* event ); - void mousePressEvent( QMouseEvent* event ); - void mouseMoveEvent( QMouseEvent* event ); - void mouseReleaseEvent( QMouseEvent* event ); - void wheelEvent( QWheelEvent* event ); + void paintEvent( QPaintEvent* event ) override; + void resizeEvent( QResizeEvent* event ) override; + void mousePressEvent( QMouseEvent* event ) override; + void mouseMoveEvent( QMouseEvent* event ) override; + void mouseReleaseEvent( QMouseEvent* event ) override; + void wheelEvent( QWheelEvent* event ) override; void updateSize(); void updateOffset(); @@ -149,34 +147,35 @@ private: QRect viewToWindow( const QRect& rc ) const; std::shared_ptr m_currFrame; + QImage m_image; std::shared_ptr m_nextFrame; + std::optional m_filterSingleChannel; ClpPel m_uiPixelHalfScale; - Tool m_eTool; - bool m_bGridVisible; + Tool m_eTool{ NavigationTool }; + bool m_bGridVisible{ false }; QTimer m_zoomWinTimer; double m_dZoomWinRatio; - double m_dZoomFactor; + double m_dZoomFactor{ 1.0 }; - QImage m_image; - //QPixmap m_pixmap; + // QPixmap m_pixmap; QBitmap m_mask; QRect m_selectedArea; QPoint m_lastPos; QPoint m_lastWindowPos; GridManager m_grid; - ViewMode m_mode; + ViewMode m_mode{ NormalMode }; QColor m_maskColor; - int m_xOffset; - int m_yOffset; - bool m_blockTrackEnable; + int m_xOffset{ 0 }; + int m_yOffset{ 0 }; + bool m_blockTrackEnable{ false }; bool m_newShape; - bool m_snapToGrid; + bool m_snapToGrid{ false }; bool m_cursorInGrid; - bool m_visibleZoomRect; + bool m_visibleZoomRect{ true }; }; #endif // __VIEWAREA_H__ diff --git a/lib/CalypFrame.cpp b/lib/CalypFrame.cpp index 211e108..227001b 100644 --- a/lib/CalypFrame.cpp +++ b/lib/CalypFrame.cpp @@ -24,6 +24,7 @@ #include "CalypFrame.h" +#include #include #include #include @@ -782,18 +783,20 @@ inline constexpr auto convert_to_pel_argb( const T r, const T g, const T b ) -> template inline constexpr void convert_yuv_to_rgb( const T iY, const T iU, const T iV, T& iR, T& iG, T& iB ) { - auto clamp_pel_value = []( auto X ) {if( X < 0 ) - return 0; - if( X > 255 ) - return 255; - return X; }; + auto clamp_pel_value = []( auto X ) { + if( X < 0 ) + return 0; + if( X > 255 ) + return 255; + return X; + }; iR = iY + ( ( 1436 * ( iV - 128 ) ) >> 10 ); iG = iY - ( ( 352 * ( iU - 128 ) + 731 * ( iV - 128 ) ) >> 10 ); iB = iY + ( ( 1812 * ( iU - 128 ) ) >> 10 ); - clamp_pel_value( iR ); - clamp_pel_value( iG ); - clamp_pel_value( iB ); + iR = clamp_pel_value( iR ); + iG = clamp_pel_value( iG ); + iB = clamp_pel_value( iB ); } void fillRGBBufferYUV420p( ClpPel*** pppInputPel, uint32_t* pARGB, unsigned uiWidth, unsigned uiHeight, int shiftBits ) @@ -828,25 +831,42 @@ void fillRGBBufferYUV420p( ClpPel*** pppInputPel, uint32_t* pARGB, unsigned uiWi } } -void CalypFrame::fillRGBBuffer() const +void CalypFrame::fillRGBBuffer( std::optional channel ) const { - if( d->m_bHasRGBPel ) - return; - int shiftBits = d->m_uiBitsPel - 8; + auto shiftBits = static_cast( d->m_uiBitsPel ) - 8; d->m_bHasRGBPel = true; // 4 bytes for A, R, G and B uint32_t* pARGB = (uint32_t*)d->m_pcARGB32.data(); - if( d->m_pcPelFormat->colorSpace == CLP_COLOR_GRAY ) + if( d->m_pcPelFormat->colorSpace == CLP_COLOR_GRAY || ( channel.has_value() && *channel == 0 ) ) { - ClpPel* pY = d->m_pppcInputPel[CLP_LUMA][0]; - unsigned char finalPel{ 0 }; + ClpPel* pY = d->m_pppcInputPel[0][0]; for( unsigned int i = 0; i < d->m_uiHeight * d->m_uiWidth; i++ ) { - finalPel = ( *pY++ ) >> shiftBits; + unsigned char finalPel = ( *pY++ ) >> shiftBits; *pARGB++ = convert_to_pel_argb( finalPel, finalPel, finalPel ); } } + else if( channel.has_value() && *channel > 0 ) + { + ClpPel* pLine = d->m_pppcInputPel[*channel][0]; + for( unsigned y = 0; y < CHROMASHIFT( d->m_uiHeight, d->m_pcPelFormat->log2ChromaHeight ); y++ ) + { + for( int i = 0; i < 1 << d->m_pcPelFormat->log2ChromaHeight; i++ ) + { + ClpPel* pPel = pLine; + for( unsigned x = 0; x < CHROMASHIFT( d->m_uiWidth, d->m_pcPelFormat->log2ChromaWidth ); x++ ) + { + unsigned char finalPel = ( *pPel++ ) >> shiftBits; + for( int j = 0; j < ( 1 << d->m_pcPelFormat->log2ChromaWidth ); j++ ) + { + *pARGB++ = convert_to_pel_argb( finalPel, finalPel, finalPel ); + } + } + } + pLine += CHROMASHIFT( d->m_uiWidth, d->m_pcPelFormat->log2ChromaWidth ); + } + } else if( d->m_pcPelFormat->colorSpace == CLP_COLOR_RGB ) { ClpPel* pR = d->m_pppcInputPel[CLP_COLOR_R][0]; @@ -910,6 +930,14 @@ void CalypFrame::fillRGBBuffer() const } } +void CalypFrame::fillRGBBuffer() const +{ + if( d->m_bHasRGBPel ) + return; + + fillRGBBuffer( {} ); +} + /** * Histogram */ diff --git a/lib/CalypFrame.h b/lib/CalypFrame.h index d8ba4db..e6a2fbc 100644 --- a/lib/CalypFrame.h +++ b/lib/CalypFrame.h @@ -26,7 +26,6 @@ #ifndef __CALYPFRAME_H__ #define __CALYPFRAME_H__ -#include #include #include #include @@ -492,6 +491,7 @@ public: void frameFromBuffer( const std::vector&, int ); void frameToBuffer( std::vector&, int ) const; + void fillRGBBuffer( std::optional channel ) const; void fillRGBBuffer() const; /**