Message ID | 20220527144447.94891-21-tomi.valkeinen@ideasonboard.com |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi Tomi, Thank you for the patch. On Fri, May 27, 2022 at 05:44:37PM +0300, Tomi Valkeinen wrote: > We can use Qt directly to accomplish the same as we do with PIL. > > A minor downside is that loading MJPEG frame with Qt produces a "Corrupt > JPEG data" warning. The resulting picture looks fine, though. So add a > message handler to ignore that warning. What's the exact message being printed ? > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > --- > src/py/cam/cam_qt.py | 30 ++++++++++++++++++++++-------- > 1 file changed, 22 insertions(+), 8 deletions(-) > > diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py > index af4b0f86..b6412bdf 100644 > --- a/src/py/cam/cam_qt.py > +++ b/src/py/cam/cam_qt.py > @@ -2,17 +2,32 @@ > # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > > from helpers import mfb_to_rgb > -from io import BytesIO > -from PIL import Image > -from PIL.ImageQt import ImageQt > from PyQt5 import QtCore, QtGui, QtWidgets > import libcamera as libcam > import libcamera.utils > import sys > > + > +# Loading MJPEG to a QPixmap produces corrupt JPEG data warnings. Ignore these. > +def qt_message_handler(msg_type, msg_log_context, msg_string): > + if msg_string.startswith("Corrupt JPEG data"): > + return > + > + # For some reason qInstallMessageHandler returns None, so we won't > + # call the old handler Have you seen that happening ? If that's the case, do we really need to call print(), or is it a sign that there should be no logging ? > + if old_msg_handler is not None: > + old_msg_handler(msg_type, msg_log_context, msg_string) > + else: > + print(msg_string) > + > + > +old_msg_handler = QtCore.qInstallMessageHandler(qt_message_handler) Quite a bit of a hack, but I don't really see another viable option. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > + > + > def rgb_to_pix(rgb): > - img = Image.frombuffer('RGB', (rgb.shape[1], rgb.shape[0]), rgb) > - qim = ImageQt(img).copy() > + w = rgb.shape[1] > + h = rgb.shape[0] > + qim = QtGui.QImage(rgb, w, h, QtGui.QImage.Format.Format_RGB888) > pix = QtGui.QPixmap.fromImage(qim) > return pix > > @@ -135,9 +150,8 @@ class MainWindow(QtWidgets.QWidget): > cfg = stream.configuration > > if cfg.pixel_format == libcam.formats.MJPEG: > - img = Image.open(BytesIO(mfb.planes[0])) > - qim = ImageQt(img).copy() > - pix = QtGui.QPixmap.fromImage(qim) > + pix = QtGui.QPixmap(cfg.size.width, cfg.size.height) > + pix.loadFromData(mfb.planes[0]) > else: > rgb = mfb_to_rgb(mfb, cfg) > if rgb is None:
On 30/05/2022 12:38, Laurent Pinchart wrote: > Hi Tomi, > > Thank you for the patch. > > On Fri, May 27, 2022 at 05:44:37PM +0300, Tomi Valkeinen wrote: >> We can use Qt directly to accomplish the same as we do with PIL. >> >> A minor downside is that loading MJPEG frame with Qt produces a "Corrupt >> JPEG data" warning. The resulting picture looks fine, though. So add a >> message handler to ignore that warning. > > What's the exact message being printed ? It varies a bit, but I get a single print like these per frame: Corrupt JPEG data: 12 extraneous bytes before marker 0xd5 Corrupt JPEG data: 2 extraneous bytes before marker 0xd4 Corrupt JPEG data: 3 extraneous bytes before marker 0xd3 Corrupt JPEG data: 1 extraneous bytes before marker 0xd5 Corrupt JPEG data: 1 extraneous bytes before marker 0xd2 Possibly MJPEG contains something extra and the jpeg decorer Qt uses doesn't cope with it? It's possible that PIL encounters the same issue but is just silent about it. >> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> >> --- >> src/py/cam/cam_qt.py | 30 ++++++++++++++++++++++-------- >> 1 file changed, 22 insertions(+), 8 deletions(-) >> >> diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py >> index af4b0f86..b6412bdf 100644 >> --- a/src/py/cam/cam_qt.py >> +++ b/src/py/cam/cam_qt.py >> @@ -2,17 +2,32 @@ >> # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> >> >> from helpers import mfb_to_rgb >> -from io import BytesIO >> -from PIL import Image >> -from PIL.ImageQt import ImageQt >> from PyQt5 import QtCore, QtGui, QtWidgets >> import libcamera as libcam >> import libcamera.utils >> import sys >> >> + >> +# Loading MJPEG to a QPixmap produces corrupt JPEG data warnings. Ignore these. >> +def qt_message_handler(msg_type, msg_log_context, msg_string): >> + if msg_string.startswith("Corrupt JPEG data"): >> + return >> + >> + # For some reason qInstallMessageHandler returns None, so we won't >> + # call the old handler > > Have you seen that happening ? If that's the case, do we really need to > call print(), or is it a sign that there should be no logging ? Yes, on my machine qInstallMessageHandler returns None. I don't know why. Afaics it's a bug somewhere in Qt, but I didn't spend much time debugging this. Tomi
diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py index af4b0f86..b6412bdf 100644 --- a/src/py/cam/cam_qt.py +++ b/src/py/cam/cam_qt.py @@ -2,17 +2,32 @@ # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> from helpers import mfb_to_rgb -from io import BytesIO -from PIL import Image -from PIL.ImageQt import ImageQt from PyQt5 import QtCore, QtGui, QtWidgets import libcamera as libcam import libcamera.utils import sys + +# Loading MJPEG to a QPixmap produces corrupt JPEG data warnings. Ignore these. +def qt_message_handler(msg_type, msg_log_context, msg_string): + if msg_string.startswith("Corrupt JPEG data"): + return + + # For some reason qInstallMessageHandler returns None, so we won't + # call the old handler + if old_msg_handler is not None: + old_msg_handler(msg_type, msg_log_context, msg_string) + else: + print(msg_string) + + +old_msg_handler = QtCore.qInstallMessageHandler(qt_message_handler) + + def rgb_to_pix(rgb): - img = Image.frombuffer('RGB', (rgb.shape[1], rgb.shape[0]), rgb) - qim = ImageQt(img).copy() + w = rgb.shape[1] + h = rgb.shape[0] + qim = QtGui.QImage(rgb, w, h, QtGui.QImage.Format.Format_RGB888) pix = QtGui.QPixmap.fromImage(qim) return pix @@ -135,9 +150,8 @@ class MainWindow(QtWidgets.QWidget): cfg = stream.configuration if cfg.pixel_format == libcam.formats.MJPEG: - img = Image.open(BytesIO(mfb.planes[0])) - qim = ImageQt(img).copy() - pix = QtGui.QPixmap.fromImage(qim) + pix = QtGui.QPixmap(cfg.size.width, cfg.size.height) + pix.loadFromData(mfb.planes[0]) else: rgb = mfb_to_rgb(mfb, cfg) if rgb is None:
We can use Qt directly to accomplish the same as we do with PIL. A minor downside is that loading MJPEG frame with Qt produces a "Corrupt JPEG data" warning. The resulting picture looks fine, though. So add a message handler to ignore that warning. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> --- src/py/cam/cam_qt.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-)