From 68b4b1aa97985d9bcb4f2b5504647e7f212a7497 Mon Sep 17 00:00:00 2001 From: Kazuhiko Shiozaki <kazuhiko@nexedi.com> Date: Fri, 11 Sep 2009 14:26:55 +0000 Subject: [PATCH] Use ImageMagick's 'convert' program instead of PIL to handle CMYK images well. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@28974 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/PortalTransforms/HISTORY.txt | 6 ++ .../libtransforms/imagemagick_transform.py | 47 ++++++++++ .../tests/testImageMagickPortalTransforms.py | 86 +++++++++++++++++++ .../transforms/image_to_bmp.py | 4 +- .../transforms/image_to_gif.py | 4 +- .../transforms/image_to_jpeg.py | 4 +- .../transforms/image_to_pcx.py | 4 +- .../transforms/image_to_png.py | 4 +- .../transforms/image_to_ppm.py | 4 +- .../transforms/image_to_tiff.py | 4 +- 10 files changed, 153 insertions(+), 14 deletions(-) create mode 100644 product/PortalTransforms/libtransforms/imagemagick_transform.py create mode 100644 product/PortalTransforms/tests/testImageMagickPortalTransforms.py diff --git a/product/PortalTransforms/HISTORY.txt b/product/PortalTransforms/HISTORY.txt index 83be6e5d3b8..2def77799d4 100644 --- a/product/PortalTransforms/HISTORY.txt +++ b/product/PortalTransforms/HISTORY.txt @@ -1,3 +1,9 @@ +1.4.2-nexedi +========================= + + * Use ImageMagick's 'convert' program instead of PIL to handle CMYK + images well. + 1.4.1-nexedi - 2009-03-03 ========================= diff --git a/product/PortalTransforms/libtransforms/imagemagick_transform.py b/product/PortalTransforms/libtransforms/imagemagick_transform.py new file mode 100644 index 00000000000..0f4a9fd0299 --- /dev/null +++ b/product/PortalTransforms/libtransforms/imagemagick_transform.py @@ -0,0 +1,47 @@ +from Products.PortalTransforms.interfaces import itransform +import subprocess + +class ImageMagickTransforms: + __implements__ = itransform + __name__ = "imagemagick_transforms" + def __init__(self, name=None): + if name is not None: + self.__name__ = name + + def name(self): + return self.__name__ + + def convert(self, orig, data, **kwargs): + parameter_list = ['convert'] + newwidth = kwargs.get('width','') + newheight = kwargs.get('height','') + if newwidth and newheight: + parameter_list.extend('-resize', '%sx%s!' % (newwidth, newheight)) + elif newwidth or newheight: + parameter_list.extend('-resize', '%sx%s' % (newwidth, newheight)) + parameter_list.append('-') + parameter_list.append('%s:-' % self.format) + process = subprocess.Popen(parameter_list, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True) + imgin, imgout, err = process.stdin, process.stdout, process.stderr + + def writeData(stream, data): + if isinstance(data, str): + stream.write(data) + else: + # Use PData structure to prevent + # consuming too much memory + while data is not None: + stream.write(data.data) + data = data.next + + writeData(imgin, orig) + imgin.close() + data.setData(imgout.read()) + return data + +def register(): + return ImageMagickTransforms() diff --git a/product/PortalTransforms/tests/testImageMagickPortalTransforms.py b/product/PortalTransforms/tests/testImageMagickPortalTransforms.py new file mode 100644 index 00000000000..4afcfcd159c --- /dev/null +++ b/product/PortalTransforms/tests/testImageMagickPortalTransforms.py @@ -0,0 +1,86 @@ +import os + +from Testing import ZopeTestCase +from Products.PortalTransforms.tests.utils import input_file_path, normalize_html,\ + matching_inputs +from Products.PortalTransforms.transforms.image_to_gif import image_to_gif +from Products.PortalTransforms.transforms.image_to_png import image_to_png +from Products.PortalTransforms.transforms.image_to_jpeg import image_to_jpeg +from Products.PortalTransforms.transforms.image_to_bmp import image_to_bmp +from Products.PortalTransforms.transforms.image_to_tiff import image_to_tiff +from Products.PortalTransforms.transforms.image_to_ppm import image_to_ppm +from Products.PortalTransforms.transforms.image_to_pcx import image_to_pcx +from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase + +# we have to set locale because lynx output is locale sensitive ! +os.environ['LC_ALL'] = 'C' + +class ImageMagickTransformsTest(ERP5TypeTestCase, ZopeTestCase.Functional): + def afterSetUp(self): + ERP5TypeTestCase.afterSetUp(self) + self.pt = self.portal.portal_transforms + + def test_image_to_bmp(self): + self.pt.registerTransform(image_to_bmp()) + imgFile = open(input_file_path('logo.jpg'), 'rb') + data = imgFile.read() + self.failUnlessEqual(self.portal.mimetypes_registry.classify(data),'image/jpeg') + data = self.pt.convertTo(target_mimetype='image/x-ms-bmp',orig=data) + self.failUnlessEqual(data.getMetadata()['mimetype'], 'image/x-ms-bmp') + + def test_image_to_gif(self): + self.pt.registerTransform(image_to_gif()) + imgFile = open(input_file_path('logo.png'), 'rb') + data = imgFile.read() + self.failUnlessEqual(self.portal.mimetypes_registry.classify(data),'image/png') + data = self.pt.convertTo(target_mimetype='image/gif',orig=data) + self.failUnlessEqual(data.getMetadata()['mimetype'], 'image/gif') + + def test_image_to_jpeg(self): + self.pt.registerTransform(image_to_jpeg()) + imgFile = open(input_file_path('logo.gif'), 'rb') + data = imgFile.read() + self.failUnlessEqual(self.portal.mimetypes_registry.classify(data),'image/gif') + data = self.pt.convertTo(target_mimetype='image/jpeg',orig=data) + self.failUnlessEqual(data.getMetadata()['mimetype'], 'image/jpeg') + + def test_image_to_png(self): + self.pt.registerTransform(image_to_png()) + imgFile = open(input_file_path('logo.jpg'), 'rb') + data = imgFile.read() + self.failUnlessEqual(self.portal.mimetypes_registry.classify(data),'image/jpeg') + data = self.pt.convertTo(target_mimetype='image/png',orig=data) + self.failUnlessEqual(data.getMetadata()['mimetype'], 'image/png') + + def test_image_to_pcx(self): + self.pt.registerTransform(image_to_pcx()) + imgFile = open(input_file_path('logo.gif'), 'rb') + data = imgFile.read() + self.failUnlessEqual(self.portal.mimetypes_registry.classify(data),'image/gif') + data = self.pt.convertTo(target_mimetype='image/pcx',orig=data) + self.failUnlessEqual(data.getMetadata()['mimetype'], 'image/pcx') + + def test_image_to_ppm(self): + self.pt.registerTransform(image_to_ppm()) + imgFile = open(input_file_path('logo.png'), 'rb') + data = imgFile.read() + self.failUnlessEqual(self.portal.mimetypes_registry.classify(data),'image/png') + data = self.pt.convertTo(target_mimetype='image/x-portable-pixmap',orig=data) + self.failUnlessEqual(data.getMetadata()['mimetype'], 'image/x-portable-pixmap') + + def test_image_to_tiff(self): + self.pt.registerTransform(image_to_tiff()) + imgFile = open(input_file_path('logo.jpg'), 'rb') + data = imgFile.read() + self.failUnlessEqual(self.portal.mimetypes_registry.classify(data),'image/jpeg') + data = self.pt.convertTo(target_mimetype='image/tiff',orig=data) + self.failUnlessEqual(data.getMetadata()['mimetype'], 'image/tiff') + + +# FIXME missing tests for image_to_html, st + +def test_suite(): + from unittest import TestSuite, makeSuite + suite = TestSuite() + suite.addTest(makeSuite(ImageMagickTransformsTest)) + return suite diff --git a/product/PortalTransforms/transforms/image_to_bmp.py b/product/PortalTransforms/transforms/image_to_bmp.py index ff812123a3b..ff726131941 100644 --- a/product/PortalTransforms/transforms/image_to_bmp.py +++ b/product/PortalTransforms/transforms/image_to_bmp.py @@ -1,6 +1,6 @@ -from Products.PortalTransforms.libtransforms.piltransform import PILTransforms +from Products.PortalTransforms.libtransforms.imagemagick_transform import ImageMagickTransforms -class image_to_bmp(PILTransforms): +class image_to_bmp(ImageMagickTransforms): __name__ = "image_to_bmp" inputs = ('image/*', ) output = 'image/x-ms-bmp' diff --git a/product/PortalTransforms/transforms/image_to_gif.py b/product/PortalTransforms/transforms/image_to_gif.py index 37526e528aa..89db9049e3b 100644 --- a/product/PortalTransforms/transforms/image_to_gif.py +++ b/product/PortalTransforms/transforms/image_to_gif.py @@ -1,6 +1,6 @@ -from Products.PortalTransforms.libtransforms.piltransform import PILTransforms +from Products.PortalTransforms.libtransforms.imagemagick_transform import ImageMagickTransforms -class image_to_gif(PILTransforms): +class image_to_gif(ImageMagickTransforms): __name__ = "image_to_gif" inputs = ('image/*', ) output = 'image/gif' diff --git a/product/PortalTransforms/transforms/image_to_jpeg.py b/product/PortalTransforms/transforms/image_to_jpeg.py index a507e506967..6dfa24ef909 100644 --- a/product/PortalTransforms/transforms/image_to_jpeg.py +++ b/product/PortalTransforms/transforms/image_to_jpeg.py @@ -1,6 +1,6 @@ -from Products.PortalTransforms.libtransforms.piltransform import PILTransforms +from Products.PortalTransforms.libtransforms.imagemagick_transform import ImageMagickTransforms -class image_to_jpeg(PILTransforms): +class image_to_jpeg(ImageMagickTransforms): __name__ = "image_to_jpeg" inputs = ('image/*', ) output = 'image/jpeg' diff --git a/product/PortalTransforms/transforms/image_to_pcx.py b/product/PortalTransforms/transforms/image_to_pcx.py index 35d10868382..df7282f0d04 100644 --- a/product/PortalTransforms/transforms/image_to_pcx.py +++ b/product/PortalTransforms/transforms/image_to_pcx.py @@ -1,6 +1,6 @@ -from Products.PortalTransforms.libtransforms.piltransform import PILTransforms +from Products.PortalTransforms.libtransforms.imagemagick_transform import ImageMagickTransforms -class image_to_pcx(PILTransforms): +class image_to_pcx(ImageMagickTransforms): __name__ = "image_to_pcx" inputs = ('image/*', ) output = 'image/pcx' diff --git a/product/PortalTransforms/transforms/image_to_png.py b/product/PortalTransforms/transforms/image_to_png.py index 22a710ea6ae..de03d408055 100644 --- a/product/PortalTransforms/transforms/image_to_png.py +++ b/product/PortalTransforms/transforms/image_to_png.py @@ -1,6 +1,6 @@ -from Products.PortalTransforms.libtransforms.piltransform import PILTransforms +from Products.PortalTransforms.libtransforms.imagemagick_transform import ImageMagickTransforms -class image_to_png(PILTransforms): +class image_to_png(ImageMagickTransforms): __name__ = "image_to_png" inputs = ('image/*', ) output = 'image/png' diff --git a/product/PortalTransforms/transforms/image_to_ppm.py b/product/PortalTransforms/transforms/image_to_ppm.py index bdb17ebd74d..f6c528d696a 100644 --- a/product/PortalTransforms/transforms/image_to_ppm.py +++ b/product/PortalTransforms/transforms/image_to_ppm.py @@ -1,6 +1,6 @@ -from Products.PortalTransforms.libtransforms.piltransform import PILTransforms +from Products.PortalTransforms.libtransforms.imagemagick_transform import ImageMagickTransforms -class image_to_ppm(PILTransforms): +class image_to_ppm(ImageMagickTransforms): __name__ = "image_to_ppm" inputs = ('image/*', ) output = 'image/x-portable-pixmap' diff --git a/product/PortalTransforms/transforms/image_to_tiff.py b/product/PortalTransforms/transforms/image_to_tiff.py index 4c15243edd3..29418cbbab7 100644 --- a/product/PortalTransforms/transforms/image_to_tiff.py +++ b/product/PortalTransforms/transforms/image_to_tiff.py @@ -1,6 +1,6 @@ -from Products.PortalTransforms.libtransforms.piltransform import PILTransforms +from Products.PortalTransforms.libtransforms.imagemagick_transform import ImageMagickTransforms -class image_to_tiff(PILTransforms): +class image_to_tiff(ImageMagickTransforms): __name__ = "image_to_tiff" inputs = ('image/*', ) output = 'image/tiff' -- 2.30.9