From 756be9b409f1f7a59f9d2ccc90fd083a164df5f7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 4 Dec 2013 14:50:45 +0530 Subject: [PATCH] Exporting of image data from the canvas --- src/calibre/gui2/dialogs/trim_image.py | 17 +++++++++----- src/calibre/gui2/tweak_book/editor/image.py | 25 ++++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/calibre/gui2/dialogs/trim_image.py b/src/calibre/gui2/dialogs/trim_image.py index 4b4ed1a636..5f4495ee42 100644 --- a/src/calibre/gui2/dialogs/trim_image.py +++ b/src/calibre/gui2/dialogs/trim_image.py @@ -6,7 +6,7 @@ from __future__ import (unicode_literals, division, absolute_import, __license__ = 'GPL v3' __copyright__ = '2013, Kovid Goyal ' -import sys +import sys, os from PyQt4.Qt import ( QDialog, QGridLayout, QToolBar, Qt, QLabel, QIcon, QDialogButtonBox, QSize, @@ -64,6 +64,7 @@ class TrimImage(QDialog): if geom is not None: self.restoreGeometry(geom) self.setWindowIcon(self.trim_action.icon()) + self.image_data = None def selection_changed(self, has_selection): self.trim_action.setEnabled(has_selection) @@ -77,6 +78,8 @@ class TrimImage(QDialog): gprefs.set('image-trim-dialog-geometry', bytearray(self.saveGeometry())) def accept(self): + if self.canvas.is_modified: + self.image_data = self.canvas.get_image_data() self.cleanup() QDialog.accept(self) @@ -86,9 +89,13 @@ class TrimImage(QDialog): if __name__ == '__main__': app = QApplication([]) - with open(sys.argv[-1], 'rb') as f: + fname = sys.argv[-1] + with open(fname, 'rb') as f: data = f.read() d = TrimImage(data) - d.exec_() - - + if d.exec_() == d.Accepted and d.image_data is not None: + b, ext = os.path.splitext(fname) + fname = b + '-trimmed' + ext + with open(fname, 'wb') as f: + f.write(d.image_data) + print ('Trimmed image written to', fname) diff --git a/src/calibre/gui2/tweak_book/editor/image.py b/src/calibre/gui2/tweak_book/editor/image.py index 6b21bae0c7..9425b033c9 100644 --- a/src/calibre/gui2/tweak_book/editor/image.py +++ b/src/calibre/gui2/tweak_book/editor/image.py @@ -10,11 +10,12 @@ import sys, string, weakref from functools import wraps from PyQt4.Qt import ( - QWidget, QImage, QPainter, QColor, QApplication, Qt, QPixmap, QRectF, - QPointF, QPen, pyqtSignal, QUndoCommand, QUndoStack, QIcon) + QWidget, QPainter, QColor, QApplication, Qt, QPixmap, QRectF, + QPointF, QPen, pyqtSignal, QUndoCommand, QUndoStack, QIcon, QImage) from calibre import fit_image -from calibre.gui2 import error_dialog +from calibre.gui2 import error_dialog, pixmap_to_data +from calibre.utils.magick.draw import identify_data def painter(func): @wraps(func) @@ -105,6 +106,10 @@ class Canvas(QWidget): def has_selection(self): return self.selection_state.current_mode == 'selected' + @property + def is_modified(self): + return self.current_image is not self.original_image + def __init__(self, parent=None): QWidget.__init__(self, parent) self.setMouseTracking(True) @@ -125,10 +130,15 @@ class Canvas(QWidget): a.setIcon(QIcon(I('edit-redo.png'))) def load_image(self, data): + try: + fmt = identify_data(data)[-1].encode('ascii') + except Exception: + fmt = b'' + self.original_image_format = fmt.decode('ascii').lower() self.selection_state.reset() self.original_image_data = data - self.current_image = i = self.original_image = QImage() - i.loadFromData(data) + self.current_image = i = self.original_image = ( + QImage.fromData(data, format=fmt) if fmt else QImage.fromData(data)) self.is_valid = not i.isNull() self.update() self.image_changed.emit(self.current_image) @@ -141,6 +151,11 @@ class Canvas(QWidget): self.update() self.image_changed.emit(self.current_image) + def get_image_data(self, quality=90): + if not self.is_modified: + return self.original_image_data + return pixmap_to_data(self.current_image, format=self.original_image_format or 'JPEG', quality=90) + def cleanup(self): self.undo_stack.clear() self.original_image_data = self.current_image = self.current_scaled_pixmap = None