From 996baaad14b3b652e264aaed21aa76c8d36c2496 Mon Sep 17 00:00:00 2001 From: Vassilii Khachaturov Date: Sat, 14 Dec 2013 23:12:18 +0200 Subject: [PATCH] 7288/7290: image_dpi and cropping fixes for ODFdoc Port my fixes based on the patch from Matthias Basler from gramps34 [2eca30] 7290: use simpler math in image_dpi [2f5e22] 7290: align warning with the image_dpi fix logic [36f84e] 7290: image_dpi default calc based on gtk.gdk [161ce3] 7290: ImgManip.image_dpi shouldn't return None [460e63] 7288/7290 refactor out crop_percentage_to_pixel [a8a38f] 7288/7290 refactor out crop_percentage_to_subpixel [0d61bb] 7288/7290: refactor fix from matthiasbasler [088146] rm relict RCS kwd [76df5d] 7288/7290: image cropping fixes in ODFDoc Using legacy gtk interface in image.py at the moment, need to port to the new style. Tested with python2. --- gramps/gen/utils/image.py | 67 ++++++++++++++++++++------------- gramps/plugins/docgen/odfdoc.py | 40 ++++++++++---------- 2 files changed, 62 insertions(+), 45 deletions(-) diff --git a/gramps/gen/utils/image.py b/gramps/gen/utils/image.py index 85cf4b12b..4f3e2af01 100644 --- a/gramps/gen/utils/image.py +++ b/gramps/gen/utils/image.py @@ -47,6 +47,20 @@ import tempfile #------------------------------------------------------------------------- from .file import get_unicode_path_from_env_var +def crop_percentage_to_subpixel(width, height, crop): + """ + Convert from Gramps cropping coordinates [0, 100] to + pixels, given image width and height. No rounding to pixel resolution. + """ + return ( + crop[0]/100.0*width, + crop[1]/100.0*height, + crop[2]/100.0*width, + crop[3]/100.0*height ) + +def crop_percentage_to_pixel(width, height, crop): + return map (int, crop_percentage_to_subpixel(width, height, crop)) + #------------------------------------------------------------------------- # # resize_to_jpeg @@ -73,12 +87,9 @@ def resize_to_jpeg(source, destination, width, height, crop=None): img = GdkPixbuf.Pixbuf.new_from_file(source) if crop: - # Gramps cropping coorinates are [0, 100], so we need to convert to pixels - start_x = int((crop[0]/100.0)*img.get_width()) - start_y = int((crop[1]/100.0)*img.get_height()) - end_x = int((crop[2]/100.0)*img.get_width()) - end_y = int((crop[3]/100.0)*img.get_height()) - + (start_x, start_y, end_x, end_y + ) = crop_percentage_to_pixel( + img.get_width(), img.get_height(), crop) if sys.version_info[0] < 3: img = img.new_subpixbuf(start_x, start_y, end_x-start_x, end_y-start_y) else: @@ -96,35 +107,44 @@ def resize_to_jpeg(source, destination, width, height, crop=None): # image_dpi # #------------------------------------------------------------------------- +MM_PER_INCH = 25.4 def image_dpi(source): """ - Return the dpi found in the image header. None is returned if no dpi attribute - is available. + Return the dpi found in the image header. Use a sensible + default of the screen DPI or 96.0 dpi if N/A. :param source: source image file, in any format that PIL recognizes :type source: unicode :rtype: int - :returns: the DPI setting in the image header + :returns: (x_dpi, y_dpi) """ try: import PIL.Image except ImportError: import logging logging.warning(_("WARNING: PIL module not loaded. " - "Image cropping in report files will not be available.")) - - dpi = None + "Image cropping in report files will be impaired.")) else: try: img = PIL.Image.open(source) except IOError: - dpi = None + pass else: try: dpi = img.info["dpi"] + return dpi except (AttributeError, KeyError): - dpi = None - + pass + try: + import gtk + dpi = ( + gtk.gdk.screen_width() * MM_PER_INCH / gtk.gdk.screen_width_mm(), + gtk.gdk.screen_height() * MM_PER_INCH / gtk.gdk.screen_height_mm() + ) + except: + dpi = (96.0,96.0) #LibOO 3.6 assumes this if image contains no DPI info + # This isn't safe even within a single platform (Windows), but we + # can't do better if all of the above failed. See bug# 7290. return dpi #------------------------------------------------------------------------- @@ -207,12 +227,9 @@ def resize_to_buffer(source, size, crop=None): img = GdkPixbuf.Pixbuf.new_from_file(source) if crop: - # Gramps cropping coorinates are [0, 100], so we need to convert to pixels - start_x = int((crop[0]/100.0)*img.get_width()) - start_y = int((crop[1]/100.0)*img.get_height()) - end_x = int((crop[2]/100.0)*img.get_width()) - end_y = int((crop[3]/100.0)*img.get_height()) - + (start_x, start_y, end_x, end_y + ) = crop_percentage_to_pixel( + img.get_width(), img.get_height(), crop) if sys.version_info[0] < 3: img = img.new_subpixbuf(start_x, start_y, end_x-start_x, end_y-start_y) else: @@ -250,11 +267,9 @@ def resize_to_jpeg_buffer(source, size, crop=None): img = GdkPixbuf.Pixbuf.new_from_file(source) if crop: - # Gramps cropping coorinates are [0, 100], so we need to convert to pixels - start_x = int((crop[0]/100.0)*img.get_width()) - start_y = int((crop[1]/100.0)*img.get_height()) - end_x = int((crop[2]/100.0)*img.get_width()) - end_y = int((crop[3]/100.0)*img.get_height()) + (start_x, start_y, end_x, end_y + ) = crop_percentage_to_pixel( + img.get_width(), img.get_height(), crop) if sys.version_info[0] < 3: img = img.new_subpixbuf(start_x, start_y, end_x-start_x, end_y-start_y) diff --git a/gramps/plugins/docgen/odfdoc.py b/gramps/plugins/docgen/odfdoc.py index b65ee1ab4..aa7b092b7 100644 --- a/gramps/plugins/docgen/odfdoc.py +++ b/gramps/plugins/docgen/odfdoc.py @@ -24,8 +24,6 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id$ - """ ODFDoc : used to generate Open Office Document """ @@ -93,7 +91,8 @@ from gramps.plugins.lib.libodfbackend import OdfBackend from gramps.gen.const import PROGRAM_NAME from gramps.version import VERSION from gramps.gen.plug.report import utils as ReportUtils -from gramps.gen.utils.image import image_size, image_dpi, image_actual_size +from gramps.gen.utils.image import (image_size, image_dpi, image_actual_size, + crop_percentage_to_subpixel) from gramps.gen.errors import ReportError #------------------------------------------------------------------------- @@ -1035,27 +1034,30 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): pos = pos.title() if pos in ['left', 'right', 'single'] else 'Row' if crop: + (start_x, start_y, end_x, end_y + ) = crop_percentage_to_subpixel(x, y, crop) + + # Need to keep the ratio intact, otherwise scaled images look stretched + # if the dimensions aren't close in size + (act_width, act_height) = image_actual_size( + x_cm, y_cm, int(end_x-start_x), int(end_y-start_y) + ) + dpi = image_dpi(file_name) - if dpi: - (act_width, act_height) = image_actual_size( - x_cm, y_cm, crop[2] - crop[0], crop[3] - crop[1] - ) + # ODF wants crop measurements in inch and as margins from each side + left = start_x/dpi[0] + right = (x - end_x)/dpi[0] + top = start_y/dpi[1] + bottom = (y - end_y)/dpi[1] + crop = (top, right, bottom, left) - left = ((crop[0]/100.0)*x)/dpi[0] - right = (x - ((crop[2]/100.0)*x))/dpi[0] - top = ((crop[1]/100.0)*y)/dpi[1] - bottom = (y - ((crop[3]/100.0)*y))/dpi[1] + self.StyleList_photos.append( + [pos, crop] + ) - crop = (top, right, bottom, left) + pos += "_" + str(crop) - self.StyleList_photos.append( - [pos, crop] - ) - - pos += "_" + str(crop) - else: - (act_width, act_height) = image_actual_size(x_cm, y_cm, x, y) else: (act_width, act_height) = image_actual_size(x_cm, y_cm, x, y)