Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

handle jpg/jpeg in the qtconsole #1643

Merged
merged 5 commits into from

2 participants

@Carreau
Owner

This add jpg/jpeg display in QtConsole, after png has been tried, of course.

IPython/frontend/qt/console/rich_ipython_widget.py
@@ -69,24 +83,38 @@ def _context_menu_make(self, pos):
def _handle_pyout(self, msg):
""" Overridden to handle rich data types, like SVG.
"""
+ def pre_image_append():
@minrk Owner
minrk added a note

This function shouldn't be defined anew every time this is called. Just make it a method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
IPython/frontend/qt/console/rich_ipython_widget.py
@@ -36,6 +44,12 @@ def __init__(self, *args, **kw):
# Dictionary for resolving document resource names to SVG data.
self._name_to_svg_map = {}
+ # Do we support jpg ?
+ # it seems that sometime jpg support is a plugin of QT, so try to assume
+ # it is not always supported.
+ self._supported_format = map(str, QtGui.QImageReader.supportedImageFormats())
+ self._jpg_supported = 'jpeg' in self._supported_format
@minrk Owner
minrk added a note

There should be no attributes that are not always defined. Make sure this is defined in the class at the top level (_jpg_supported = Bool(False))

@Carreau Owner
Carreau added a note

Well, it's true that I can put it at class top level, but I don't see why 'jpeg' in _supported_format can be not defined. and Bool traits would be overkill no ?

@minrk Owner
minrk added a note
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@minrk
Owner

What happens to jpegs during export?

@Carreau
Owner

jpeg are converted to png at export time. I thought it was overkill to try to keep the original file format, as well as proposing a full jpeg export. ( who likes jpeg for graphs anyway ? )
Moreover rich_text.py and HtmlExporter are, I think, written to work only with only one function to convert from the <image> tag of the qtconsole to file.

IPython/frontend/qt/console/rich_ipython_widget.py
@@ -65,6 +81,15 @@ def _context_menu_make(self, pos):
#---------------------------------------------------------------------------
# 'BaseFrontendMixin' abstract interface
#---------------------------------------------------------------------------
+ def _pre_image_append(self, msg, prompt_number):
+ """ Append the Out[] prompt and mke the output nicer
@minrk Owner
minrk added a note

mke/make

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@minrk
Owner

one last spelling error, and I think it's ready for merge.

Carreau added some commits
@Carreau Carreau handle jpg/jpeg in the qtconsole.
This try to handle both image/jpeg image/jpg mimetype that arrives in
the qtconsole, when QImage support It,
note that image/jpg should never append, but is still supported.

It does not allows the export as html/jpeg. The jpeg will be converted
to png at save time.
c722f75
@Carreau Carreau pylinting 51ddac4
@Carreau Carreau more robust code
_pre_image_append as method
_jpg_supported as Bool Trait
193559c
@Carreau Carreau strip copyright 9e8cfdd
@Carreau Carreau do not handle image/jpg 9d7b5df
@Carreau
Owner

Thanks, as I rebased on master to avoid recursive merge, I squashed the fix in the commit that introduced the docstring :-)
Should I merge ?

@minrk
Owner

Sure, go for it.

@Carreau Carreau merged commit f387e4a into ipython:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 25, 2012
  1. @Carreau

    handle jpg/jpeg in the qtconsole.

    Carreau authored
    This try to handle both image/jpeg image/jpg mimetype that arrives in
    the qtconsole, when QImage support It,
    note that image/jpg should never append, but is still supported.
    
    It does not allows the export as html/jpeg. The jpeg will be converted
    to png at save time.
  2. @Carreau

    pylinting

    Carreau authored
  3. @Carreau

    more robust code

    Carreau authored
    _pre_image_append as method
    _jpg_supported as Bool Trait
  4. @Carreau

    strip copyright

    Carreau authored
  5. @Carreau

    do not handle image/jpg

    Carreau authored
This page is out of date. Refresh to see the latest.
Showing with 58 additions and 19 deletions.
  1. +58 −19 IPython/frontend/qt/console/rich_ipython_widget.py
View
77 IPython/frontend/qt/console/rich_ipython_widget.py
@@ -1,3 +1,11 @@
+#-----------------------------------------------------------------------------
+# Copyright (c) 2010, IPython Development Team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file COPYING.txt, distributed with this software.
+#-----------------------------------------------------------------------------
+
# Standard libary imports.
from base64 import decodestring
import os
@@ -7,6 +15,7 @@
from IPython.external.qt import QtCore, QtGui
# Local imports
+from IPython.utils.traitlets import Bool
from IPython.frontend.qt.svg import save_svg, svg_to_clipboard, svg_to_image
from ipython_widget import IPythonWidget
@@ -19,7 +28,7 @@ class RichIPythonWidget(IPythonWidget):
# RichIPythonWidget protected class variables.
_payload_source_plot = 'IPython.zmq.pylab.backend_payload.add_plot_payload'
-
+ _jpg_supported = Bool(False)
#---------------------------------------------------------------------------
# 'object' interface
#---------------------------------------------------------------------------
@@ -36,6 +45,13 @@ def __init__(self, *args, **kw):
# Dictionary for resolving document resource names to SVG data.
self._name_to_svg_map = {}
+ # Do we support jpg ?
+ # it seems that sometime jpg support is a plugin of QT, so try to assume
+ # it is not always supported.
+ _supported_format = map(str, QtGui.QImageReader.supportedImageFormats())
+ self._jpg_supported = 'jpeg' in _supported_format
+
+
#---------------------------------------------------------------------------
# 'ConsoleWidget' protected interface
#---------------------------------------------------------------------------
@@ -65,6 +81,15 @@ def _context_menu_make(self, pos):
#---------------------------------------------------------------------------
# 'BaseFrontendMixin' abstract interface
#---------------------------------------------------------------------------
+ def _pre_image_append(self, msg, prompt_number):
+ """ Append the Out[] prompt and make the output nicer
+
+ Shared code for some the following if statement
+ """
+ self.log.debug("pyout: %s", msg.get('content', ''))
+ self._append_plain_text(self.output_sep, True)
+ self._append_html(self._make_out_prompt(prompt_number), True)
+ self._append_plain_text('\n', True)
def _handle_pyout(self, msg):
""" Overridden to handle rich data types, like SVG.
@@ -74,19 +99,17 @@ def _handle_pyout(self, msg):
prompt_number = content['execution_count']
data = content['data']
if data.has_key('image/svg+xml'):
- self.log.debug("pyout: %s", msg.get('content', ''))
- self._append_plain_text(self.output_sep, True)
- self._append_html(self._make_out_prompt(prompt_number), True)
+ self._pre_image_append(msg, prompt_number)
self._append_svg(data['image/svg+xml'], True)
self._append_html(self.output_sep2, True)
elif data.has_key('image/png'):
- self.log.debug("pyout: %s", msg.get('content', ''))
- self._append_plain_text(self.output_sep, True)
- self._append_html(self._make_out_prompt(prompt_number), True)
- # This helps the output to look nice.
- self._append_plain_text('\n', True)
+ self._pre_image_append(msg, prompt_number)
self._append_png(decodestring(data['image/png'].encode('ascii')), True)
self._append_html(self.output_sep2, True)
+ elif data.has_key('image/jpeg') and self._jpg_supported:
+ self._pre_image_append(msg, prompt_number)
+ self._append_jpg(decodestring(data['image/jpeg'].encode('ascii')), True)
+ self._append_html(self.output_sep2, True)
else:
# Default back to the plain text representation.
return super(RichIPythonWidget, self)._handle_pyout(msg)
@@ -110,6 +133,10 @@ def _handle_display_data(self, msg):
# in a JSON structure so we decode it.
png = decodestring(data['image/png'].encode('ascii'))
self._append_png(png, True)
+ elif data.has_key('image/jpeg') and self._jpg_supported:
+ self.log.debug("display: %s", msg.get('content', ''))
+ jpg = decodestring(data['image/jpeg'].encode('ascii'))
+ self._append_jpg(jpg, True)
else:
# Default back to the plain text representation.
return super(RichIPythonWidget, self)._handle_display_data(msg)
@@ -118,6 +145,10 @@ def _handle_display_data(self, msg):
# 'RichIPythonWidget' protected interface
#---------------------------------------------------------------------------
+ def _append_jpg(self, jpg, before_prompt=False):
+ """ Append raw JPG data to the widget."""
+ self._append_custom(self._insert_jpg, jpg, before_prompt)
+
def _append_png(self, png, before_prompt=False):
""" Append raw PNG data to the widget.
"""
@@ -168,10 +199,10 @@ def _get_image_tag(self, match, path = None, format = "png"):
written (e.g., for linked images). If None, all images are to be
included inline.
- format : "png"|"svg", optional [default "png"]
+ format : "png"|"svg"|"jpg", optional [default "png"]
Format for returned or referenced images.
"""
- if format == "png":
+ if format in ("png","jpg"):
try:
image = self._get_image(match.group("name"))
except KeyError:
@@ -181,20 +212,20 @@ def _get_image_tag(self, match, path = None, format = "png"):
if not os.path.exists(path):
os.mkdir(path)
relpath = os.path.basename(path)
- if image.save("%s/qt_img%s.png" % (path,match.group("name")),
+ if image.save("%s/qt_img%s.%s" % (path, match.group("name"), format),
"PNG"):
- return '<img src="%s/qt_img%s.png">' % (relpath,
- match.group("name"))
+ return '<img src="%s/qt_img%s.%s">' % (relpath,
+ match.group("name"),format)
else:
return "<b>Couldn't save image!</b>"
else:
ba = QtCore.QByteArray()
buffer_ = QtCore.QBuffer(ba)
buffer_.open(QtCore.QIODevice.WriteOnly)
- image.save(buffer_, "PNG")
+ image.save(buffer_, format.upper())
buffer_.close()
- return '<img src="data:image/png;base64,\n%s\n" />' % (
- re.sub(r'(.{60})',r'\1\n',str(ba.toBase64())))
+ return '<img src="data:image/%s;base64,\n%s\n" />' % (
+ format,re.sub(r'(.{60})',r'\1\n',str(ba.toBase64())))
elif format == "svg":
try:
@@ -215,14 +246,22 @@ def _get_image_tag(self, match, path = None, format = "png"):
else:
return '<b>Unrecognized image format</b>'
+ def _insert_jpg(self, cursor, jpg):
+ """ Insert raw PNG data into the widget."""
+ self._insert_img(cursor, jpg, 'jpg')
+
def _insert_png(self, cursor, png):
""" Insert raw PNG data into the widget.
"""
+ self._insert_img(cursor, png, 'png')
+
+ def _insert_img(self, cursor, img, fmt):
+ """ insert a raw image, jpg or png """
try:
image = QtGui.QImage()
- image.loadFromData(png, 'PNG')
+ image.loadFromData(img, fmt.upper())
except ValueError:
- self._insert_plain_text(cursor, 'Received invalid PNG data.')
+ self._insert_plain_text(cursor, 'Received invalid %s data.'%fmt)
else:
format = self._add_image(image)
cursor.insertBlock()
Something went wrong with that request. Please try again.