[Products.Silva][Sylvain Viollon] Fix various image issues.
[email protected] Tue, 17 Sep 2013 11:48:03 +0200
| Newsgroups | gmane.comp.web.zope.silva.cvs |
|---|---|
| Message-ID | <[email protected]> |
author: Sylvain Viollon
date: Tue Sep 17 11:48:00 2013 +0200
revision: 11859:d88cd4ce0728 in Products.Silva
branch: 2.4
details: https://hg.infrae.com/Products.Silva?cmd=changeset;node=d88cd4ce0728
modified: Products/Silva/Image/content.py Products/Silva/Image/smi.py Products/Silva/Image/smi_templates/infoportlet.cpt Products/Silva/tests/test_image.py Products/Silva/tests/test_image_utils.py
added:
removed:
log: Fix various image issues.
diffstat:
Products/Silva/Image/content.py | 83 ++++++++++-----------
Products/Silva/Image/smi.py | 31 +++----
Products/Silva/Image/smi_templates/infoportlet.cpt | 37 +++++---
Products/Silva/tests/test_image.py | 20 +++-
Products/Silva/tests/test_image_utils.py | 7 +
5 files changed, 97 insertions(+), 81 deletions(-)
diffs (335 lines):
diff -r 25cf922b3707 -r d88cd4ce0728 Products/Silva/Image/content.py
--- a/Products/Silva/Image/content.py Mon Sep 02 14:52:31 2013 +0200
+++ b/Products/Silva/Image/content.py Tue Sep 17 11:48:00 2013 +0200
@@ -96,8 +96,6 @@
class ImageFile(object):
def __init__(self, image):
- if image is None:
- raise ValueError("Missing image.")
self._fd = image.get_file_fd()
self._changed = False
try:
@@ -274,28 +272,31 @@
Automaticaly updates cached web presentation image.
"""
- update_cache = False
+ update = False
if self.hires_image is None:
- update_cache = True
+ update = True
self.hires_image = self.image
self.image = None
- if web_format != 'unknown':
- if self.web_format != web_format and \
- web_format in self.web_formats:
+
+ # Set web format.
+ if web_format not in ('unknown', '') and self.web_format != web_format:
+ if web_format in self.web_formats:
self.web_format = web_format
- update_cache = True
+ update = True
+ else:
+ raise ValueError('Unknown image format %s' % web_format)
# check if web_scale can be parsed:
self.get_canonical_web_scale(web_scale)
if self.web_scale != web_scale:
- update_cache = True
self.web_scale = web_scale
+ update = True
# check if web_crop can be parsed:
self.get_crop_box(web_crop)
if self.web_crop != web_crop:
- update_cache = True
# if web_crop is None it should be replaced by an empty string
self.web_crop = web_crop and web_crop or ''
- if self.hires_image is not None and update_cache:
+ update = True
+ if update and self.hires_image is not None:
self._create_derived_images()
security.declareProtected(
@@ -320,26 +321,25 @@
def get_image(self, hires=True, webformat=False):
"""Return image data.
"""
- image = None
if hires:
- # You want hires
- image = self.hires_image
- if webformat and image is not None:
- # Hires in webformat
- with ImageFile(image) as working:
- data = working.save(self.web_format)
- if data is not None:
- return data.getvalue()
- else:
- # Resized version
+ if self.hires_image is not None:
+ if webformat:
+ # Create web format of original image.
+ with ImageFile(self.hires_image) as working:
+ data = working.save(self.web_format)
+ if data is not None:
+ return data.getvalue()
+ # Original format of the original image is the orginal.
+ return self.hires_image.get_file()
+ return None
+ if self.image is not None:
if webformat:
- image = self.image
- else:
- raise ValueError(
- _(u"Low resolution image in original format is "
- u"not supported"))
- if image is not None:
- return image.get_file()
+ # Webformat of the cropped/resized image is already computed.
+ return self.image.get_file()
+ # Original format of the cropped/resize image is not possible.
+ raise ValueError(
+ _(u"Low resolution image in original format is "
+ u"not supported"))
return None
security.declareProtected(SilvaPermissions.View, 'get_canonical_web_scale')
@@ -584,11 +584,6 @@
self._image_factory('image', image_io, content_type)
else:
self.image = self.hires_image
- except ValueError as error:
- logger.error("Web presentation creation failed for %s with %s" %
- ('/'.join(self.getPhysicalPath()), str(error)))
- self.image = self.hires_image
- return
except IOError as error:
logger.error("Web presentation creation failed for %s with %s" %
('/'.join(self.getPhysicalPath()), str(error)))
@@ -596,6 +591,11 @@
self.image = self.hires_image
return
raise ValueError(str(error))
+ except ValueError as error:
+ logger.error("Web presentation creation failed for %s with %s" %
+ ('/'.join(self.getPhysicalPath()), str(error)))
+ self.image = self.hires_image
+ return
def _create_thumbnail(self):
try:
@@ -605,14 +605,14 @@
if thumb:
content_type = self._web2ct[self.web_format]
self._image_factory('thumbnail_image', thumb, content_type)
- except IOError, e:
+ except IOError as error:
logger.info("Thumbnail creation failed for %s with %s" %
- ('/'.join(self.getPhysicalPath()), str(e)))
- if str(e.args[0]) == "cannot read interlaced PNG files":
+ ('/'.join(self.getPhysicalPath()), str(error)))
+ if str(error.args[0]) == "cannot read interlaced PNG files":
self.thumbnail_image = None
return
else:
- raise ValueError(str(e))
+ raise ValueError(str(error))
except ValueError, e:
logger.info("Thumbnail creation failed for %s with %s" %
('/'.join(self.getPhysicalPath()), str(e)))
@@ -621,18 +621,13 @@
return
def _image_factory(self, identifier, stream, content_type=None):
- service_files = getUtility(IFilesService)
- new_image = service_files.new_file(identifier)
+ new_image = getUtility(IFilesService).new_file(identifier)
setattr(self, identifier, new_image)
new_image = getattr(self, identifier)
new_image.set_file(stream, content_type)
getUtility(IMimeTypeClassifier).guess_filename(new_image, self.getId())
return new_image
- def _image_is_hires(self):
- return (self.image is not None and
- self.image.aq_base is self.hires_image.aq_base)
-
InitializeClass(Image)
diff -r 25cf922b3707 -r d88cd4ce0728 Products/Silva/Image/smi.py
--- a/Products/Silva/Image/smi.py Mon Sep 02 14:52:31 2013 +0200
+++ b/Products/Silva/Image/smi.py Tue Sep 17 11:48:00 2013 +0200
@@ -133,30 +133,27 @@
grok.order(10)
def update(self):
- self.format = self.context.web_format.lower()
+ self.thumbnail = None
self.dimensions = None
- try:
- dimensions = self.context.get_dimensions()
+ self.original_available = False
+ self.original_dimensions = None
+ self.web_format = self.context.web_format.lower()
+ dimensions = self.context.get_dimensions(hires=False)
+ if dimensions != (0, 0):
self.dimensions = dict(zip(['width', 'height'], dimensions))
- except ValueError:
- dimensions = None
- self.scaling = None
+
if self.context.hires_image is not None:
- try:
- scaled_dimensions = self.context.get_canonical_web_scale()
- if scaled_dimensions != dimensions:
- self.scaling = dict(
- zip(['width', 'height'], scaled_dimensions))
- except ValueError:
- scaled_dimensions = None
- self.thumbnail = None
+ self.original_available = True
+ original_dimensions = self.context.get_dimensions(hires=True)
+ if original_dimensions not in (dimensions, (0, 0)):
+ self.original_dimensions = dict(
+ zip(['width', 'height'], original_dimensions))
+
if self.context.thumbnail_image:
self.thumbnail = self.context.tag(request=self.request,
preview=True,
thumbnail=True)
- self.original = self.context.url(request=self.request,
- preview=True,
- hires=True)
+
self.orientation = self.context.get_orientation()
self.orientation_cls = unicode(self.orientation)
diff -r 25cf922b3707 -r d88cd4ce0728 Products/Silva/Image/smi_templates/infoportlet.cpt
--- a/Products/Silva/Image/smi_templates/infoportlet.cpt Mon Sep 02 14:52:31 2013 +0200
+++ b/Products/Silva/Image/smi_templates/infoportlet.cpt Tue Sep 17 11:48:00 2013 +0200
@@ -2,7 +2,7 @@
i18n:domain="silva">
<h4 i18n:translate="">Format</h4>
<p i18n:translate="">
- <span i18n:name="format" tal:replace="viewlet.format" /> image
+ <span i18n:name="format" tal:replace="viewlet.web_format" /> image
</p>
<h4 i18n:translate="">Dimensions</h4>
@@ -10,11 +10,9 @@
i18n:translate="">
unknown
</p>
- <p tal:condition="viewlet.dimensions">
- <!-- Template is not properly indented to prevent a spaces before 'x' and '.' -->
- <tal:original i18n:translate="">
- <span tal:replace="viewlet.dimensions.width" i18n:name="width"/>x<span tal:replace="viewlet.dimensions.height" i18n="height" /> pixels</tal:original><tal:scaled tal:condition="viewlet.scaling" i18n:translate="">
- scaled to <span tal:replace="viewlet.scaling.width" i18n:name="width"/>x<span tal:replace="viewlet.scaling.height" i18n="height" /> pixels</tal:scaled>
+ <!-- Template is not properly indented to prevent a spaces before 'x'-->
+ <p tal:condition="viewlet.dimensions" i18n:translate="">
+ <span tal:replace="viewlet.dimensions.width" i18n:name="width"/>x<span tal:replace="viewlet.dimensions.height" i18n="height" /> pixels
</p>
<tal:thumbnail tal:condition="viewlet.thumbnail">
@@ -24,15 +22,24 @@
</p>
</tal:thumbnail>
- <h4 i18n:translate="">Original</h4>
- <div class="external-controls">
- <a title="View the original image"
- class="open-screen form-button ui-state-default" rel="preview/hires"
- i18n:attributes="title">
- <ins class="ui-icon ui-icon-search"></ins>
- <tal:msg i18n:translate="">View unscaled image</tal:msg>
- </a>
- </div>
+ <tal:original tal:condition="viewlet.original_available">
+ <h4 i18n:translate="">Original</h4>
+ <!-- Template is not properly indented to prevent a spaces before 'x'-->
+ <p tal:condition="viewlet.original_dimensions" i18n:translate="">
+ Original dimensions are <span tal:replace="viewlet.original_dimensions.width" i18n:name="width"/>x<span tal:replace="viewlet.original_dimensions.height" i18n="height" /> pixels.
+ </p>
+ <p tal:condition="not: viewlet.original_dimensions" i18n:translate="">
+ Original image is not resized or cropped.
+ </p>
+ <div class="external-controls">
+ <a title="View the original image"
+ class="open-screen form-button ui-state-default" rel="preview/hires"
+ i18n:attributes="title">
+ <ins class="ui-icon ui-icon-search"></ins>
+ <tal:msg i18n:translate="">View unscaled image</tal:msg>
+ </a>
+ </div>
+ </tal:original>
<h4 i18n:translate="">Orientation</h4>
<p>
diff -r 25cf922b3707 -r d88cd4ce0728 Products/Silva/tests/test_image.py
--- a/Products/Silva/tests/test_image.py Mon Sep 02 14:52:31 2013 +0200
+++ b/Products/Silva/tests/test_image.py Tue Sep 17 11:48:00 2013 +0200
@@ -58,7 +58,7 @@
def test_image(self):
"""Test image content.
"""
- image = self.root.test_image
+ image = self.root._getOb('test_image')
self.assertTrue(verifyObject(interfaces.IAsset, image))
self.assertTrue(verifyObject(interfaces.IImage, image))
self.assertNotEqual(image.get_modification_datetime(), None)
@@ -71,14 +71,13 @@
self.assertEquals(image.get_mime_type(), 'image/tiff')
# Image methods
+ self.assertTrue(image.tag() is not None)
self.assertEquals(image.get_format(), 'TIFF')
self.assertEquals(image.get_web_format(), 'JPEG')
self.assertEquals(image.get_dimensions(), (960, 1280))
self.assertEquals(str(image.get_orientation()), "portrait")
+
image.set_web_presentation_properties('JPEG', '100x100', '')
- with self.assertRaises(ValueError):
- image.get_image(hires=False, webformat=False)
- self.assertTrue(image.tag() is not None)
self.assertEquals(image.get_web_format(), 'JPEG')
data = io.BytesIO(image.get_image(hires=False, webformat=True))
@@ -94,7 +93,18 @@
self.assertEquals((960, 1280), pil_image.size)
self.assertEquals('JPEG', pil_image.format)
- def test_upload_image_with_existing_id(self):
+ with self.assertRaises(ValueError) as error:
+ image.get_image(hires=False, webformat=False)
+ self.assertEquals(
+ str(error.exception),
+ 'Low resolution image in original format is not supported')
+
+ def test_set_web_presentation_properties(self):
+ """Test set web presentation.
+ """
+ image = self.root._getOb('test_image')
+
+ def test_add_image_with_existing_id(self):
with Transaction():
with self.layer.open_fixture('photo.tif') as image:
factory = self.root.manage_addProduct['Silva']
diff -r 25cf922b3707 -r d88cd4ce0728 Products/Silva/tests/test_image_utils.py
--- a/Products/Silva/tests/test_image_utils.py Mon Sep 02 14:52:31 2013 +0200
+++ b/Products/Silva/tests/test_image_utils.py Tue Sep 17 11:48:00 2013 +0200
@@ -15,6 +15,13 @@
class ImageUtilsTestCase(unittest.TestCase):
+ def test_size(self):
+ """Test Size.
+ """
+ size = Size(10, 10)
+ self.assertEqual(size, (10, 10)) # You can compare it to a tuple.
+ self.assertNotEqual(size, (15, 10))
+
def test_percentresizespec(self):
"""Test PercentResizeSpec used to express a resize specification.
"""