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