[{"id":23236,"web_url":"https://patchwork.libcamera.org/comment/23236/","msgid":"<YpSQg9gHbA3a02eo@pendragon.ideasonboard.com>","date":"2022-05-30T09:38:11","subject":"Re: [libcamera-devel] [PATCH v3 20/30] py: cam: Drop PIL dependency","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Tomi,\n\nThank you for the patch.\n\nOn Fri, May 27, 2022 at 05:44:37PM +0300, Tomi Valkeinen wrote:\n> We can use Qt directly to accomplish the same as we do with PIL.\n> \n> A minor downside is that loading MJPEG frame with Qt produces a \"Corrupt\n> JPEG data\" warning. The resulting picture looks fine, though. So add a\n> message handler to ignore that warning.\n\nWhat's the exact message being printed ?\n\n> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n> ---\n>  src/py/cam/cam_qt.py | 30 ++++++++++++++++++++++--------\n>  1 file changed, 22 insertions(+), 8 deletions(-)\n> \n> diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py\n> index af4b0f86..b6412bdf 100644\n> --- a/src/py/cam/cam_qt.py\n> +++ b/src/py/cam/cam_qt.py\n> @@ -2,17 +2,32 @@\n>  # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n>  \n>  from helpers import mfb_to_rgb\n> -from io import BytesIO\n> -from PIL import Image\n> -from PIL.ImageQt import ImageQt\n>  from PyQt5 import QtCore, QtGui, QtWidgets\n>  import libcamera as libcam\n>  import libcamera.utils\n>  import sys\n>  \n> +\n> +# Loading MJPEG to a QPixmap produces corrupt JPEG data warnings. Ignore these.\n> +def qt_message_handler(msg_type, msg_log_context, msg_string):\n> +    if msg_string.startswith(\"Corrupt JPEG data\"):\n> +        return\n> +\n> +    # For some reason qInstallMessageHandler returns None, so we won't\n> +    # call the old handler\n\nHave you seen that happening ? If that's the case, do we really need to\ncall print(), or is it a sign that there should be no logging ?\n\n> +    if old_msg_handler is not None:\n> +        old_msg_handler(msg_type, msg_log_context, msg_string)\n> +    else:\n> +        print(msg_string)\n> +\n> +\n> +old_msg_handler = QtCore.qInstallMessageHandler(qt_message_handler)\n\nQuite a bit of a hack, but I don't really see another viable option.\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> +\n> +\n>  def rgb_to_pix(rgb):\n> -    img = Image.frombuffer('RGB', (rgb.shape[1], rgb.shape[0]), rgb)\n> -    qim = ImageQt(img).copy()\n> +    w = rgb.shape[1]\n> +    h = rgb.shape[0]\n> +    qim = QtGui.QImage(rgb, w, h, QtGui.QImage.Format.Format_RGB888)\n>      pix = QtGui.QPixmap.fromImage(qim)\n>      return pix\n>  \n> @@ -135,9 +150,8 @@ class MainWindow(QtWidgets.QWidget):\n>              cfg = stream.configuration\n>  \n>              if cfg.pixel_format == libcam.formats.MJPEG:\n> -                img = Image.open(BytesIO(mfb.planes[0]))\n> -                qim = ImageQt(img).copy()\n> -                pix = QtGui.QPixmap.fromImage(qim)\n> +                pix = QtGui.QPixmap(cfg.size.width, cfg.size.height)\n> +                pix.loadFromData(mfb.planes[0])\n>              else:\n>                  rgb = mfb_to_rgb(mfb, cfg)\n>                  if rgb is None:","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 D27E9BD161\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 30 May 2022 09:38:16 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 26DEC65633;\n\tMon, 30 May 2022 11:38:16 +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 C47F06040B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 30 May 2022 11:38:14 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(lmontsouris-659-1-41-236.w92-154.abo.wanadoo.fr [92.154.76.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 14A1D104;\n\tMon, 30 May 2022 11:38:14 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1653903496;\n\tbh=64ZdAb8EnLkvK6DXqT1ZcSH21QaCO0dtATPrSyHNIBw=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=gFtS2qtextAZr9kLWq5VDxoXstXR5skzhytjwjggnbGA+Q8xQ5pMAfM0c1nyPVkXA\n\t568MTgHq55vQDuLPwKqtgkFM7/Ms4YF0lEo6ltHhk3kgxohWgRIayDav8lgeAO3Bm+\n\t+FxGVQKM6hiMgUviRtMjkMSvn1WVzUL9aycLLcy9SLlFAR+Ih/ubMl6V72tCsoLG8n\n\tzk0YrfZQcC3TGQAhiVcyII24ycfSM7Kwnslo6Na2ssP3JYsUQprcWxndRDPdUhgjrS\n\tilQoRIIJvbVgtcM+D8DEYEguldNWPaXac3bg57PlLKebE4tbS5pzF2P8cE3L4lIa1d\n\thXRnoCUc8LNNg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1653903494;\n\tbh=64ZdAb8EnLkvK6DXqT1ZcSH21QaCO0dtATPrSyHNIBw=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=CACb66q/kCQnbXf73Gh1ineTaDkitXZou2ktKnSd1rxAZIF+ws5nwqa9CvpqSFhKP\n\tEeYGNsWOnW63YtCxd/yhdKgNY9/YhVnPvtdXOm7xQ0lzwnExOTIU15JTFCIMQNLuw4\n\tEjB4dxz4gIgVCT2tSHCagxWVUIHZOxaLpU6yaAvY="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"CACb66q/\"; dkim-atps=neutral","Date":"Mon, 30 May 2022 12:38:11 +0300","To":"Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>","Message-ID":"<YpSQg9gHbA3a02eo@pendragon.ideasonboard.com>","References":"<20220527144447.94891-1-tomi.valkeinen@ideasonboard.com>\n\t<20220527144447.94891-21-tomi.valkeinen@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220527144447.94891-21-tomi.valkeinen@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v3 20/30] py: cam: Drop PIL dependency","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>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":23238,"web_url":"https://patchwork.libcamera.org/comment/23238/","msgid":"<64c4fd7e-2395-d347-d4f4-1a901ce25bae@ideasonboard.com>","date":"2022-05-30T09:45:11","subject":"Re: [libcamera-devel] [PATCH v3 20/30] py: cam: Drop PIL dependency","submitter":{"id":109,"url":"https://patchwork.libcamera.org/api/people/109/","name":"Tomi Valkeinen","email":"tomi.valkeinen@ideasonboard.com"},"content":"On 30/05/2022 12:38, Laurent Pinchart wrote:\n> Hi Tomi,\n> \n> Thank you for the patch.\n> \n> On Fri, May 27, 2022 at 05:44:37PM +0300, Tomi Valkeinen wrote:\n>> We can use Qt directly to accomplish the same as we do with PIL.\n>>\n>> A minor downside is that loading MJPEG frame with Qt produces a \"Corrupt\n>> JPEG data\" warning. The resulting picture looks fine, though. So add a\n>> message handler to ignore that warning.\n> \n> What's the exact message being printed ?\n\nIt varies a bit, but I get a single print like these per frame:\n\nCorrupt JPEG data: 12 extraneous bytes before marker 0xd5\nCorrupt JPEG data: 2 extraneous bytes before marker 0xd4\nCorrupt JPEG data: 3 extraneous bytes before marker 0xd3\nCorrupt JPEG data: 1 extraneous bytes before marker 0xd5\nCorrupt JPEG data: 1 extraneous bytes before marker 0xd2\n\nPossibly MJPEG contains something extra and the jpeg decorer Qt uses \ndoesn't cope with it? It's possible that PIL encounters the same issue \nbut is just silent about it.\n\n>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n>> ---\n>>   src/py/cam/cam_qt.py | 30 ++++++++++++++++++++++--------\n>>   1 file changed, 22 insertions(+), 8 deletions(-)\n>>\n>> diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py\n>> index af4b0f86..b6412bdf 100644\n>> --- a/src/py/cam/cam_qt.py\n>> +++ b/src/py/cam/cam_qt.py\n>> @@ -2,17 +2,32 @@\n>>   # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>\n>>   \n>>   from helpers import mfb_to_rgb\n>> -from io import BytesIO\n>> -from PIL import Image\n>> -from PIL.ImageQt import ImageQt\n>>   from PyQt5 import QtCore, QtGui, QtWidgets\n>>   import libcamera as libcam\n>>   import libcamera.utils\n>>   import sys\n>>   \n>> +\n>> +# Loading MJPEG to a QPixmap produces corrupt JPEG data warnings. Ignore these.\n>> +def qt_message_handler(msg_type, msg_log_context, msg_string):\n>> +    if msg_string.startswith(\"Corrupt JPEG data\"):\n>> +        return\n>> +\n>> +    # For some reason qInstallMessageHandler returns None, so we won't\n>> +    # call the old handler\n> \n> Have you seen that happening ? If that's the case, do we really need to\n> call print(), or is it a sign that there should be no logging ?\n\nYes, on my machine qInstallMessageHandler returns None. I don't know \nwhy. Afaics it's a bug somewhere in Qt, but I didn't spend much time \ndebugging this.\n\n  Tomi","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 BBBECBD160\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 30 May 2022 09:45:15 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 20FE565633;\n\tMon, 30 May 2022 11:45:15 +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 A9AFD6040B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 30 May 2022 11:45:14 +0200 (CEST)","from [192.168.1.111] (91-156-85-209.elisa-laajakaista.fi\n\t[91.156.85.209])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C5B966BD;\n\tMon, 30 May 2022 11:45:13 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1653903915;\n\tbh=XLUdeoQYJoy56iuKfM6p39E+RHVXT9OiwQdyt3habeQ=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=hjm02aHF1730XYsxB5rMrRce92OVZg1lr5DjjGOPvfhayrY3IXmRhHH5h92isDJ+7\n\tjnqSFrykbyZv8wODYi2WbF+KZECRlDqA/wnxl+FMwnlgJ3mcQyzfZt+Njv9IU8l0tD\n\tt06YTgNA8C88iUwy+Tw4gggp3sOUM9Qqsq5K7BXRQLPbfsvchywjQslo0QSTnAam2/\n\teo0Y/7LoEF9VWWYTsemK9gNZR7M2g2CeVaRzfPs6lkpxRys2WdX+qYKHJy9Z0m62hz\n\tHYZlmYIytK3tClyLlkz40ai4vRzti6jAMas3nGjXAONvsYT/CG+4p76aQ7/O4bT8Gi\n\tlpZYtzz96aA5A==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1653903914;\n\tbh=XLUdeoQYJoy56iuKfM6p39E+RHVXT9OiwQdyt3habeQ=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=gxOl4Ro8Q42PsvZ8YCaSsqGIAiEPnjVrtoHTRd4qPpjMUeKxIrULBc6smrV8wjGHb\n\tOc4raqQA3H1iwsRZDfivqVgghPQKW7ZhfCcs8pdWPuHfjvG+yuhqkI7Xh1RkM49fE9\n\tWyIrMhjhP49YUZVM7OfyoPJOiFZZSL7ezTmES/8w="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"gxOl4Ro8\"; dkim-atps=neutral","Message-ID":"<64c4fd7e-2395-d347-d4f4-1a901ce25bae@ideasonboard.com>","Date":"Mon, 30 May 2022 12:45:11 +0300","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101\n\tThunderbird/91.9.1","Content-Language":"en-US","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","References":"<20220527144447.94891-1-tomi.valkeinen@ideasonboard.com>\n\t<20220527144447.94891-21-tomi.valkeinen@ideasonboard.com>\n\t<YpSQg9gHbA3a02eo@pendragon.ideasonboard.com>","In-Reply-To":"<YpSQg9gHbA3a02eo@pendragon.ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH v3 20/30] py: cam: Drop PIL dependency","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>","From":"Tomi Valkeinen via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]