[{"id":31123,"web_url":"https://patchwork.libcamera.org/comment/31123/","msgid":"<172588523464.2319503.6724857365209443266@ping.linuxembedded.co.uk>","date":"2024-09-09T12:33:54","subject":"Re: [PATCH 1/2] qcam: viewfinder_qt: Draw the letterbox background\n\tblack","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Laurent Pinchart (2024-09-05 17:25:07)\n> When the widget's aspect ratio doesn't match the camera aspect ratio,\n> the viewfinder is rendered letter-boxed. The side rectangles are not\n> painted by the viewfinder, and Qt thus renders the parent widget\n> background to fill that space.\n> \n> To make it black, we have two options:\n> \n> - The simplest option is to set the widget's autoFillBackground property\n>   to true. This causes Qt to paint the whole widget with its background\n>   colour before calling paintEvent(). As the camera image typically\n>   covers most (if not all) of the viewfinder widget, this is less\n>   efficient.\n> \n> - The more complicated option is to pain the letterbox rectangles\n\ns/pain/paint/\n\n>   manually. We can additionally set the widget's WA_OpaquePaintEvent\n>   attribute to instruct Qt to skip painting the parent widget. This\n>   reduces CPU usage by about 1% (and may reduce GPU usage as well).\n> \n> Note that the WA_OpaquePaintEvent attribute has to be disabled when we\n> render the stopped icon, as the icon has a transparent background.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/apps/qcam/viewfinder_qt.cpp | 23 +++++++++++++++++++++--\n>  1 file changed, 21 insertions(+), 2 deletions(-)\n> \n> diff --git a/src/apps/qcam/viewfinder_qt.cpp b/src/apps/qcam/viewfinder_qt.cpp\n> index 492648cfa2ff..62b6f27fa23e 100644\n> --- a/src/apps/qcam/viewfinder_qt.cpp\n> +++ b/src/apps/qcam/viewfinder_qt.cpp\n> @@ -44,6 +44,10 @@ ViewFinderQt::ViewFinderQt(QWidget *parent)\n>         : QWidget(parent), place_(rect()), buffer_(nullptr)\n>  {\n>         icon_ = QIcon(\":camera-off.svg\");\n> +\n> +       QPalette pal = palette();\n> +       pal.setColor(QPalette::Window, Qt::black);\n> +       setPalette(pal);\n>  }\n>  \n>  ViewFinderQt::~ViewFinderQt()\n> @@ -118,6 +122,7 @@ void ViewFinderQt::render(libcamera::FrameBuffer *buffer, Image *image)\n>                 }\n>         }\n>  \n\nI would probably have a comment here ...\n\n> +       setAttribute(Qt::WA_OpaquePaintEvent, true);\n>         update();\n>  \n>         if (buffer)\n> @@ -133,6 +138,7 @@ void ViewFinderQt::stop()\n>                 buffer_ = nullptr;\n>         }\n>  \n\nand here ...\n\nto say why we are starting and sotpping the paint attributes.\n\n> +       setAttribute(Qt::WA_OpaquePaintEvent, false);\n>         update();\n>  }\n>  \n> @@ -147,8 +153,22 @@ void ViewFinderQt::paintEvent(QPaintEvent *)\n>  {\n>         QPainter painter(this);\n>  \n> -       /* If we have an image, draw it. */\n> +       painter.setBrush(palette().window());\n> +\n> +       /* If we have an image, draw it, with black letterbox rectangles. */\n>         if (!image_.isNull()) {\n> +               if (place_.width() < width()) {\n> +                       QRect rect{ 0, 0, (width() - place_.width()) / 2, height() };\n> +                       painter.drawRect(rect);\n> +                       rect.moveLeft(place_.right());\n> +                       painter.drawRect(rect);\n> +               } else {\n> +                       QRect rect{ 0, 0, width(), (height() - place_.height()) / 2 };\n> +                       painter.drawRect(rect);\n> +                       rect.moveTop(place_.bottom());\n> +                       painter.drawRect(rect);\n> +               }\n\nSeems easy enough.\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\nAnd tested on my X13s\n\nHowever, I can't currently test qcam -r gles it seems which is crashing\nbut that's on mainline too so not this series.\n\n> +\n>                 painter.drawImage(place_, image_, image_.rect());\n>                 return;\n>         }\n> @@ -174,7 +194,6 @@ void ViewFinderQt::paintEvent(QPaintEvent *)\n>         else\n>                 point.setY((height() - pixmap_.height()) / 2);\n>  \n> -       painter.setBackgroundMode(Qt::OpaqueMode);\n>         painter.drawPixmap(point, pixmap_);\n>  }\n>  \n> -- \n> Regards,\n> \n> Laurent Pinchart\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CE106BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  9 Sep 2024 12:34:00 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 63CC7634F7;\n\tMon,  9 Sep 2024 14:33:59 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3BBDE634EB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  9 Sep 2024 14:33:58 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E01303DA;\n\tMon,  9 Sep 2024 14:32:41 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"nqfN7GXv\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1725885162;\n\tbh=cpg8rqK38jqkoew7bT0Odh9REdpOCDGAEjOuekr8SEE=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=nqfN7GXvPel7ReKm/qTlXWdBBTkvJ2If83sVdNTJzDfwCGIdCSi4ngnqfRRyXw4j9\n\tTvkZ+wNrkkqFO0qAUYtaam12Rd2QPr9f7HcI0LZgFKiWmEC7dPllaPmeq9GLGlIbVr\n\t9rLAD5MbYbY3AlXOmGKjNGJgWyX7QkCcIXe+UwUo=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20240905162508.4169-2-laurent.pinchart@ideasonboard.com>","References":"<20240905162508.4169-1-laurent.pinchart@ideasonboard.com>\n\t<20240905162508.4169-2-laurent.pinchart@ideasonboard.com>","Subject":"Re: [PATCH 1/2] qcam: viewfinder_qt: Draw the letterbox background\n\tblack","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 09 Sep 2024 13:33:54 +0100","Message-ID":"<172588523464.2319503.6724857365209443266@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":31134,"web_url":"https://patchwork.libcamera.org/comment/31134/","msgid":"<20240909160331.GA2144@pendragon.ideasonboard.com>","date":"2024-09-09T16:03:31","subject":"Re: [PATCH 1/2] qcam: viewfinder_qt: Draw the letterbox background\n\tblack","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Mon, Sep 09, 2024 at 01:33:54PM +0100, Kieran Bingham wrote:\n> Quoting Laurent Pinchart (2024-09-05 17:25:07)\n> > When the widget's aspect ratio doesn't match the camera aspect ratio,\n> > the viewfinder is rendered letter-boxed. The side rectangles are not\n> > painted by the viewfinder, and Qt thus renders the parent widget\n> > background to fill that space.\n> > \n> > To make it black, we have two options:\n> > \n> > - The simplest option is to set the widget's autoFillBackground property\n> >   to true. This causes Qt to paint the whole widget with its background\n> >   colour before calling paintEvent(). As the camera image typically\n> >   covers most (if not all) of the viewfinder widget, this is less\n> >   efficient.\n> > \n> > - The more complicated option is to pain the letterbox rectangles\n> \n> s/pain/paint/\n> \n> >   manually. We can additionally set the widget's WA_OpaquePaintEvent\n> >   attribute to instruct Qt to skip painting the parent widget. This\n> >   reduces CPU usage by about 1% (and may reduce GPU usage as well).\n> > \n> > Note that the WA_OpaquePaintEvent attribute has to be disabled when we\n> > render the stopped icon, as the icon has a transparent background.\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  src/apps/qcam/viewfinder_qt.cpp | 23 +++++++++++++++++++++--\n> >  1 file changed, 21 insertions(+), 2 deletions(-)\n> > \n> > diff --git a/src/apps/qcam/viewfinder_qt.cpp b/src/apps/qcam/viewfinder_qt.cpp\n> > index 492648cfa2ff..62b6f27fa23e 100644\n> > --- a/src/apps/qcam/viewfinder_qt.cpp\n> > +++ b/src/apps/qcam/viewfinder_qt.cpp\n> > @@ -44,6 +44,10 @@ ViewFinderQt::ViewFinderQt(QWidget *parent)\n> >         : QWidget(parent), place_(rect()), buffer_(nullptr)\n> >  {\n> >         icon_ = QIcon(\":camera-off.svg\");\n> > +\n> > +       QPalette pal = palette();\n> > +       pal.setColor(QPalette::Window, Qt::black);\n> > +       setPalette(pal);\n> >  }\n> >  \n> >  ViewFinderQt::~ViewFinderQt()\n> > @@ -118,6 +122,7 @@ void ViewFinderQt::render(libcamera::FrameBuffer *buffer, Image *image)\n> >                 }\n> >         }\n> >  \n> \n> I would probably have a comment here ...\n> \n> > +       setAttribute(Qt::WA_OpaquePaintEvent, true);\n> >         update();\n> >  \n> >         if (buffer)\n> > @@ -133,6 +138,7 @@ void ViewFinderQt::stop()\n> >                 buffer_ = nullptr;\n> >         }\n> >  \n> \n> and here ...\n> \n> to say why we are starting and sotpping the paint attributes.\n> \n> > +       setAttribute(Qt::WA_OpaquePaintEvent, false);\n> >         update();\n> >  }\n> >  \n> > @@ -147,8 +153,22 @@ void ViewFinderQt::paintEvent(QPaintEvent *)\n> >  {\n> >         QPainter painter(this);\n> >  \n> > -       /* If we have an image, draw it. */\n> > +       painter.setBrush(palette().window());\n> > +\n> > +       /* If we have an image, draw it, with black letterbox rectangles. */\n> >         if (!image_.isNull()) {\n> > +               if (place_.width() < width()) {\n> > +                       QRect rect{ 0, 0, (width() - place_.width()) / 2, height() };\n> > +                       painter.drawRect(rect);\n> > +                       rect.moveLeft(place_.right());\n> > +                       painter.drawRect(rect);\n> > +               } else {\n> > +                       QRect rect{ 0, 0, width(), (height() - place_.height()) / 2 };\n> > +                       painter.drawRect(rect);\n> > +                       rect.moveTop(place_.bottom());\n> > +                       painter.drawRect(rect);\n> > +               }\n> \n> Seems easy enough.\n> \n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n> And tested on my X13s\n> \n> However, I can't currently test qcam -r gles it seems which is crashing\n> but that's on mainline too so not this series.\n\nIt doesn't crash for me, but it doesn't work either :-( The move to Qt6\napparently introduced an issue.\n\n> > +\n> >                 painter.drawImage(place_, image_, image_.rect());\n> >                 return;\n> >         }\n> > @@ -174,7 +194,6 @@ void ViewFinderQt::paintEvent(QPaintEvent *)\n> >         else\n> >                 point.setY((height() - pixmap_.height()) / 2);\n> >  \n> > -       painter.setBackgroundMode(Qt::OpaqueMode);\n> >         painter.drawPixmap(point, pixmap_);\n> >  }\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 86976C324C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  9 Sep 2024 16:03:37 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7FAE5634F7;\n\tMon,  9 Sep 2024 18:03:36 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 548F4634EB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  9 Sep 2024 18:03:35 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(213-229-8-243.static.upcbusiness.at [213.229.8.243])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id BF75F5A4;\n\tMon,  9 Sep 2024 18:02:18 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"oMfiew5K\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1725897738;\n\tbh=DEd/7XbdU1+VMxY2OGM9DiR+ktqfdWHPs/84SX6FLcY=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=oMfiew5KbmAKW/qqShcwKY3yBCagKlzTXATWfIMH7hNcZ2Qqbt4nXhhXOl2GUWYh5\n\tjsOFdSPSxtXSzlUajh176+mjbfOsb8ggpygpmVvUE/ZK6U0PbSBJUFof5KsCyTQfWb\n\tTifowJQWtZ+6ajYoQ1XyYxPNEBDRYJZHNP4+eG14=","Date":"Mon, 9 Sep 2024 19:03:31 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 1/2] qcam: viewfinder_qt: Draw the letterbox background\n\tblack","Message-ID":"<20240909160331.GA2144@pendragon.ideasonboard.com>","References":"<20240905162508.4169-1-laurent.pinchart@ideasonboard.com>\n\t<20240905162508.4169-2-laurent.pinchart@ideasonboard.com>\n\t<172588523464.2319503.6724857365209443266@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<172588523464.2319503.6724857365209443266@ping.linuxembedded.co.uk>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]