Skip to content
This repository

handle jpg/jpeg in the qtconsole #1643

Merged
merged 5 commits into from almost 2 years ago

2 participants

Matthias Bussonnier Min RK
Matthias Bussonnier
Collaborator

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):
69 83
     def _handle_pyout(self, msg):
70 84
         """ Overridden to handle rich data types, like SVG.
71 85
         """
  86
+        def pre_image_append():
1
Min RK Owner
minrk added a note April 22, 2012

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):
36 44
         # Dictionary for resolving document resource names to SVG data.
37 45
         self._name_to_svg_map = {}
38 46
 
  47
+        # Do we support jpg ?
  48
+        # it seems that sometime jpg support is a plugin of QT, so try to assume
  49
+        # it is not always supported.
  50
+        self._supported_format = map(str, QtGui.QImageReader.supportedImageFormats())
  51
+        self._jpg_supported = 'jpeg' in self._supported_format
3
Min RK Owner
minrk added a note April 22, 2012

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))

Matthias Bussonnier Collaborator
Carreau added a note April 23, 2012

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 ?

Min RK Owner
minrk added a note April 23, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Min RK
Owner
minrk commented April 22, 2012

What happens to jpegs during export?

Matthias Bussonnier
Collaborator

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):
65 81
     #---------------------------------------------------------------------------
66 82
     # 'BaseFrontendMixin' abstract interface
67 83
     #---------------------------------------------------------------------------
  84
+    def _pre_image_append(self, msg, prompt_number):
  85
+        """ Append the Out[] prompt  and mke the output nicer
1
Min RK Owner
minrk added a note April 25, 2012

mke/make

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Min RK
Owner
minrk commented April 25, 2012

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

added some commits April 22, 2012
Matthias Bussonnier 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
Matthias Bussonnier pylinting 51ddac4
Matthias Bussonnier more robust code
_pre_image_append as method
_jpg_supported as Bool Trait
193559c
Matthias Bussonnier strip copyright 9e8cfdd
Matthias Bussonnier do not handle image/jpg 9d7b5df
Matthias Bussonnier
Collaborator

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

Min RK
Owner
minrk commented April 25, 2012

Sure, go for it.

Matthias Bussonnier Carreau merged commit f387e4a into from April 25, 2012
Matthias Bussonnier Carreau closed this April 25, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 5 unique commits by 1 author.

Apr 25, 2012
Matthias Bussonnier 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
Matthias Bussonnier pylinting 51ddac4
Matthias Bussonnier more robust code
_pre_image_append as method
_jpg_supported as Bool Trait
193559c
Matthias Bussonnier strip copyright 9e8cfdd
Matthias Bussonnier do not handle image/jpg 9d7b5df
This page is out of date. Refresh to see the latest.
77  IPython/frontend/qt/console/rich_ipython_widget.py
... ...
@@ -1,3 +1,11 @@
  1
+#-----------------------------------------------------------------------------
  2
+# Copyright (c) 2010, IPython Development Team.
  3
+#
  4
+# Distributed under the terms of the Modified BSD License.
  5
+#
  6
+# The full license is in the file COPYING.txt, distributed with this software.
  7
+#-----------------------------------------------------------------------------
  8
+
1 9
 # Standard libary imports.
2 10
 from base64 import decodestring
3 11
 import os
@@ -7,6 +15,7 @@
7 15
 from IPython.external.qt import QtCore, QtGui
8 16
 
9 17
 # Local imports
  18
+from IPython.utils.traitlets import Bool
10 19
 from IPython.frontend.qt.svg import save_svg, svg_to_clipboard, svg_to_image
11 20
 from ipython_widget import IPythonWidget
12 21
 
@@ -19,7 +28,7 @@ class RichIPythonWidget(IPythonWidget):
19 28
 
20 29
     # RichIPythonWidget protected class variables.
21 30
     _payload_source_plot = 'IPython.zmq.pylab.backend_payload.add_plot_payload'
22  
-
  31
+    _jpg_supported = Bool(False)
23 32
     #---------------------------------------------------------------------------
24 33
     # 'object' interface
25 34
     #---------------------------------------------------------------------------
@@ -36,6 +45,13 @@ def __init__(self, *args, **kw):
36 45
         # Dictionary for resolving document resource names to SVG data.
37 46
         self._name_to_svg_map = {}
38 47
 
  48
+        # Do we support jpg ?
  49
+        # it seems that sometime jpg support is a plugin of QT, so try to assume
  50
+        # it is not always supported.
  51
+        _supported_format = map(str, QtGui.QImageReader.supportedImageFormats())
  52
+        self._jpg_supported = 'jpeg' in _supported_format
  53
+
  54
+
39 55
     #---------------------------------------------------------------------------
40 56
     # 'ConsoleWidget' protected interface
41 57
     #---------------------------------------------------------------------------
@@ -65,6 +81,15 @@ def _context_menu_make(self, pos):
65 81
     #---------------------------------------------------------------------------
66 82
     # 'BaseFrontendMixin' abstract interface
67 83
     #---------------------------------------------------------------------------
  84
+    def _pre_image_append(self, msg, prompt_number):
  85
+        """ Append the Out[] prompt  and make the output nicer
  86
+
  87
+        Shared code for some the following if statement
  88
+        """
  89
+        self.log.debug("pyout: %s", msg.get('content', ''))
  90
+        self._append_plain_text(self.output_sep, True)
  91
+        self._append_html(self._make_out_prompt(prompt_number), True)
  92
+        self._append_plain_text('\n', True)
68 93
 
69 94
     def _handle_pyout(self, msg):
70 95
         """ Overridden to handle rich data types, like SVG.
@@ -74,19 +99,17 @@ def _handle_pyout(self, msg):
74 99
             prompt_number = content['execution_count']
75 100
             data = content['data']
76 101
             if data.has_key('image/svg+xml'):
77  
-                self.log.debug("pyout: %s", msg.get('content', ''))
78  
-                self._append_plain_text(self.output_sep, True)
79  
-                self._append_html(self._make_out_prompt(prompt_number), True)
  102
+                self._pre_image_append(msg, prompt_number)
80 103
                 self._append_svg(data['image/svg+xml'], True)
81 104
                 self._append_html(self.output_sep2, True)
82 105
             elif data.has_key('image/png'):
83  
-                self.log.debug("pyout: %s", msg.get('content', ''))
84  
-                self._append_plain_text(self.output_sep, True)
85  
-                self._append_html(self._make_out_prompt(prompt_number), True)
86  
-                # This helps the output to look nice.
87  
-                self._append_plain_text('\n', True)
  106
+                self._pre_image_append(msg, prompt_number)
88 107
                 self._append_png(decodestring(data['image/png'].encode('ascii')), True)
89 108
                 self._append_html(self.output_sep2, True)
  109
+            elif data.has_key('image/jpeg') and self._jpg_supported:
  110
+                self._pre_image_append(msg, prompt_number)
  111
+                self._append_jpg(decodestring(data['image/jpeg'].encode('ascii')), True)
  112
+                self._append_html(self.output_sep2, True)
90 113
             else:
91 114
                 # Default back to the plain text representation.
92 115
                 return super(RichIPythonWidget, self)._handle_pyout(msg)
@@ -110,6 +133,10 @@ def _handle_display_data(self, msg):
110 133
                 # in a JSON structure so we decode it.
111 134
                 png = decodestring(data['image/png'].encode('ascii'))
112 135
                 self._append_png(png, True)
  136
+            elif data.has_key('image/jpeg') and self._jpg_supported:
  137
+                self.log.debug("display: %s", msg.get('content', ''))
  138
+                jpg = decodestring(data['image/jpeg'].encode('ascii'))
  139
+                self._append_jpg(jpg, True)
113 140
             else:
114 141
                 # Default back to the plain text representation.
115 142
                 return super(RichIPythonWidget, self)._handle_display_data(msg)
@@ -118,6 +145,10 @@ def _handle_display_data(self, msg):
118 145
     # 'RichIPythonWidget' protected interface
119 146
     #---------------------------------------------------------------------------
120 147
 
  148
+    def _append_jpg(self, jpg, before_prompt=False):
  149
+        """ Append raw JPG data to the widget."""
  150
+        self._append_custom(self._insert_jpg, jpg, before_prompt)
  151
+
121 152
     def _append_png(self, png, before_prompt=False):
122 153
         """ Append raw PNG data to the widget.
123 154
         """
@@ -168,10 +199,10 @@ def _get_image_tag(self, match, path = None, format = "png"):
168 199
             written (e.g., for linked images).  If None, all images are to be
169 200
             included inline.
170 201
 
171  
-        format : "png"|"svg", optional [default "png"]
  202
+        format : "png"|"svg"|"jpg", optional [default "png"]
172 203
             Format for returned or referenced images.
173 204
         """
174  
-        if format == "png":
  205
+        if format in ("png","jpg"):
175 206
             try:
176 207
                 image = self._get_image(match.group("name"))
177 208
             except KeyError:
@@ -181,20 +212,20 @@ def _get_image_tag(self, match, path = None, format = "png"):
181 212
                 if not os.path.exists(path):
182 213
                     os.mkdir(path)
183 214
                 relpath = os.path.basename(path)
184  
-                if image.save("%s/qt_img%s.png" % (path,match.group("name")),
  215
+                if image.save("%s/qt_img%s.%s" % (path, match.group("name"), format),
185 216
                               "PNG"):
186  
-                    return '<img src="%s/qt_img%s.png">' % (relpath,
187  
-                                                            match.group("name"))
  217
+                    return '<img src="%s/qt_img%s.%s">' % (relpath,
  218
+                                                            match.group("name"),format)
188 219
                 else:
189 220
                     return "<b>Couldn't save image!</b>"
190 221
             else:
191 222
                 ba = QtCore.QByteArray()
192 223
                 buffer_ = QtCore.QBuffer(ba)
193 224
                 buffer_.open(QtCore.QIODevice.WriteOnly)
194  
-                image.save(buffer_, "PNG")
  225
+                image.save(buffer_, format.upper())
195 226
                 buffer_.close()
196  
-                return '<img src="data:image/png;base64,\n%s\n" />' % (
197  
-                    re.sub(r'(.{60})',r'\1\n',str(ba.toBase64())))
  227
+                return '<img src="data:image/%s;base64,\n%s\n" />' % (
  228
+                    format,re.sub(r'(.{60})',r'\1\n',str(ba.toBase64())))
198 229
 
199 230
         elif format == "svg":
200 231
             try:
@@ -215,14 +246,22 @@ def _get_image_tag(self, match, path = None, format = "png"):
215 246
         else:
216 247
             return '<b>Unrecognized image format</b>'
217 248
 
  249
+    def _insert_jpg(self, cursor, jpg):
  250
+        """ Insert raw PNG data into the widget."""
  251
+        self._insert_img(cursor, jpg, 'jpg')
  252
+
218 253
     def _insert_png(self, cursor, png):
219 254
         """ Insert raw PNG data into the widget.
220 255
         """
  256
+        self._insert_img(cursor, png, 'png')
  257
+
  258
+    def _insert_img(self, cursor, img, fmt):
  259
+        """ insert a raw image, jpg or png """
221 260
         try:
222 261
             image = QtGui.QImage()
223  
-            image.loadFromData(png, 'PNG')
  262
+            image.loadFromData(img, fmt.upper())
224 263
         except ValueError:
225  
-            self._insert_plain_text(cursor, 'Received invalid PNG data.')
  264
+            self._insert_plain_text(cursor, 'Received invalid %s data.'%fmt)
226 265
         else:
227 266
             format = self._add_image(image)
228 267
             cursor.insertBlock()
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.