From 09f37fa31ed380683c524f3cf5284a1a0aaa34ec Mon Sep 17 00:00:00 2001 From: wang-bin Date: Sun, 13 Oct 2013 21:09:32 +0800 Subject: [PATCH] region of interest support. gl and xv not ready TODO: aspect ratio change if roi changes. setContentRect? --- src/Direct2DRenderer.cpp | 9 +++++++- src/GDIRenderer.cpp | 11 ++++----- src/GraphicsItemRenderer.cpp | 7 +++--- src/QtAV/VideoRenderer.h | 17 ++++++++++++++ src/QtAV/private/VideoRenderer_p.h | 2 +- src/VideoRenderer.cpp | 36 ++++++++++++++++++++++++++++++ src/WidgetRenderer.cpp | 7 +++--- 7 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/Direct2DRenderer.cpp b/src/Direct2DRenderer.cpp index 70b7a7a1..c34bdf50 100644 --- a/src/Direct2DRenderer.cpp +++ b/src/Direct2DRenderer.cpp @@ -103,12 +103,19 @@ void Direct2DRenderer::drawFrame() (FLOAT)d.out_rect.right(), (FLOAT)d.out_rect.bottom() }; + QRect roi = realROI(); + D2D1_RECT_F roi_d2d = { + (FLOAT)roi.left(), + (FLOAT)roi.top(), + (FLOAT)roi.right(), + (FLOAT)roi.bottom() + }; //d.render_target->SetTransform d.render_target->DrawBitmap(d.bitmap , &out_rect , 1 //opacity , d.interpolation - , NULL);//&D2D1::RectF(0, 0, d.src_width, d.src_height)); + , &roi_d2d); } void Direct2DRenderer::paintEvent(QPaintEvent *) diff --git a/src/GDIRenderer.cpp b/src/GDIRenderer.cpp index 89b6e39e..450597dc 100644 --- a/src/GDIRenderer.cpp +++ b/src/GDIRenderer.cpp @@ -100,24 +100,25 @@ void GDIRenderer::drawFrame() } HDC hdc = d.device_context; HBITMAP hbmp_old = (HBITMAP)SelectObject(d.off_dc, d.off_bitmap); + QRect roi = realROI(); // && image.size() != size() //assume that the image data is already scaled to out_size(NOT renderer size!) - if (!d.scale_in_renderer || (d.src_width == d.out_rect.width() && d.src_height == d.out_rect.height())) { + /*if (!d.scale_in_renderer || (roi.size() == d.out_rect.size())) { BitBlt(hdc , d.out_rect.left(), d.out_rect.top() , d.out_rect.width(), d.out_rect.height() , d.off_dc , 0, 0 , SRCCOPY); - } else { + } else {*/ StretchBlt(hdc , d.out_rect.left(), d.out_rect.top() , d.out_rect.width(), d.out_rect.height() , d.off_dc - , 0, 0 - , d.src_width, d.src_height + , roi.x(), roi.y() + , roi.width(), roi.height() , SRCCOPY); - } + //} SelectObject(d.off_dc, hbmp_old); DeleteObject(d.off_bitmap); //avoid mem leak #endif diff --git a/src/GraphicsItemRenderer.cpp b/src/GraphicsItemRenderer.cpp index b62ef8fa..f4e62918 100644 --- a/src/GraphicsItemRenderer.cpp +++ b/src/GraphicsItemRenderer.cpp @@ -110,11 +110,12 @@ void GraphicsItemRenderer::drawFrame() d.image = QImage(rendererSize(), QImage::Format_RGB32); d.image.fill(Qt::black); //maemo 4.7.0: QImage.fill(uint) } + QRect roi = realROI(); //assume that the image data is already scaled to out_size(NOT renderer size!) - if (!d.scale_in_renderer || d.image.size() == d.out_rect.size()) { - d.painter->drawImage(d.out_rect.topLeft(), d.image); + if (!d.scale_in_renderer || roi.size() == d.out_rect.size()) { + d.painter->drawImage(d.out_rect.topLeft(), d.image, roi); } else { - d.painter->drawImage(d.out_rect, d.image); + d.painter->drawImage(d.out_rect, d.image, roi); } } diff --git a/src/QtAV/VideoRenderer.h b/src/QtAV/VideoRenderer.h index c3eb335d..b460bdc2 100644 --- a/src/QtAV/VideoRenderer.h +++ b/src/QtAV/VideoRenderer.h @@ -24,6 +24,7 @@ #include #include +#include #include /*TODO: @@ -60,6 +61,7 @@ class Q_EXPORT VideoRenderer : public AVOutput DPTR_DECLARE_PRIVATE(VideoRenderer) public: //TODO: original video size mode + // fillmode: keepsize enum OutAspectRatioMode { RendererAspectRatio //Use renderer's aspect ratio, i.e. stretch to fit the renderer rect , VideoAspectRatio //Use video's aspect ratio and align center in renderer. @@ -104,6 +106,21 @@ public: int frameHeight() const; //The video frame rect in renderer you shoud paint to. e.g. in RendererAspectRatio mode, the rect equals to renderer's QRect videoRect() const; + /* + * region of interest, ROI + * invalid rect means the whole source rect + * null rect is the whole available source rect. e.g. (0, 0, 0, 0) equals whole source rect + * (20, 30, 0, 0) equals (20, 30, sourceWidth - 20, sourceHeight - 30) + * if |x|<=1, |y|<=1, |width|<1, |height|<1 means the ratio of source rect + * call realROI() to get the frame rect actually to be render + * TODO: nagtive width or height means invert direction. is nagtive necessary? + */ + QRectF regionOfInterest() const; + // TODO: reset aspect ratio to roi.width/roi/heghit + void setRegionOfInterest(qreal x, qreal y, qreal width, qreal height); + void setRegionOfInterest(const QRectF& roi); + // compute the real ROI + QRect realROI() const; QWidget* widget(); QGraphicsItem* graphicsItem(); diff --git a/src/QtAV/private/VideoRenderer_p.h b/src/QtAV/private/VideoRenderer_p.h index 4ee41f87..4d565d17 100644 --- a/src/QtAV/private/VideoRenderer_p.h +++ b/src/QtAV/private/VideoRenderer_p.h @@ -106,7 +106,7 @@ public: VideoRenderer::Quality quality; //out_rect: the displayed video frame out_rect in the renderer QRect out_rect; //TODO: out_out_rect - + QRectF roi; /* Stores but not own the ptr if renderer is a subclass of QWidget. * Some operations are based on QWidget */ diff --git a/src/VideoRenderer.cpp b/src/VideoRenderer.cpp index 3f2e1c00..4766277c 100644 --- a/src/VideoRenderer.cpp +++ b/src/VideoRenderer.cpp @@ -218,6 +218,42 @@ QRect VideoRenderer::videoRect() const return d_func().out_rect; } +QRectF VideoRenderer::regionOfInterest() const +{ + return d_func().roi; +} + +void VideoRenderer::setRegionOfInterest(qreal x, qreal y, qreal width, qreal height) +{ + DPTR_D(VideoRenderer); + d.roi = QRectF(x, y, width, height); +} + +void VideoRenderer::setRegionOfInterest(const QRectF &roi) +{ + d_func().roi = roi; +} + +QRect VideoRenderer::realROI() const +{ + DPTR_D(const VideoRenderer); + if (!d.roi.isValid()) { + return QRect(0, 0, d.src_width, d.src_height); + } + QRect r = d.roi.toRect(); + if (qAbs(d.roi.x()) <= 1) + r.setX(d.roi.x()*qreal(frameWidth())); + if (qAbs(d.roi.y()) <= 1) + r.setY(d.roi.y()*qreal(frameHeight())); + // whole size use width or height = 0, i.e. null size + if (qAbs(d.roi.width()) < 1) + r.setWidth(d.roi.width()*qreal(frameWidth())); + if (qAbs(d.roi.height() < 1)) + r.setHeight(d.roi.height()*qreal(frameHeight())); + //TODO: insect with source rect? + return r; +} + QWidget* VideoRenderer::widget() { return d_func().widget_holder; diff --git a/src/WidgetRenderer.cpp b/src/WidgetRenderer.cpp index cd92d2a7..378e5362 100644 --- a/src/WidgetRenderer.cpp +++ b/src/WidgetRenderer.cpp @@ -104,14 +104,15 @@ void WidgetRenderer::drawFrame() d.image = QImage(rendererSize(), QImage::Format_RGB32); d.image.fill(Qt::black); //maemo 4.7.0: QImage.fill(uint) } + QRect roi = realROI(); //assume that the image data is already scaled to out_size(NOT renderer size!) - if (!d.scale_in_renderer || d.image.size() == d.out_rect.size()) { + if (!d.scale_in_renderer || roi.size() == d.out_rect.size()) { //d.preview = d.image; - d.painter->drawImage(d.out_rect.topLeft(), d.image); + d.painter->drawImage(d.out_rect.topLeft(), d.image, roi); } else { //qDebug("size not fit. may slow. %dx%d ==> %dx%d" // , d.image.size().width(), image.size().height(), d.renderer_width, d.renderer_height); - d.painter->drawImage(d.out_rect, d.image); + d.painter->drawImage(d.out_rect, d.image, roi); //what's the difference? //d.painter->drawImage(QPoint(), image.scaled(d.renderer_width, d.renderer_height)); }