| # | 
| # The Python Imaging Library. | 
| # $Id$ | 
| # | 
| # optional color managment support, based on Kevin Cazabon's PyCMS | 
| # library. | 
| # | 
| # History: | 
| # 2009-03-08 fl   Added to PIL. | 
| # | 
| # Copyright (C) 2002-2003 Kevin Cazabon | 
| # Copyright (c) 2009 by Fredrik Lundh | 
| # | 
| # See the README file for information on usage and redistribution.  See | 
| # below for the original description. | 
| # | 
|   | 
| DESCRIPTION = """ | 
| pyCMS | 
|   | 
|     a Python / PIL interface to the littleCMS ICC Color Management System | 
|     Copyright (C) 2002-2003 Kevin Cazabon | 
|     kevin@cazabon.com | 
|     http://www.cazabon.com | 
|   | 
|     pyCMS home page:  http://www.cazabon.com/pyCMS | 
|     littleCMS home page:  http://www.littlecms.com | 
|     (littleCMS is Copyright (C) 1998-2001 Marti Maria) | 
|   | 
|     Originally released under LGPL.  Graciously donated to PIL in | 
|     March 2009, for distribution under the standard PIL license | 
|   | 
|     The pyCMS.py module provides a "clean" interface between Python/PIL and | 
|     pyCMSdll, taking care of some of the more complex handling of the direct | 
|     pyCMSdll functions, as well as error-checking and making sure that all | 
|     relevant data is kept together. | 
|   | 
|     While it is possible to call pyCMSdll functions directly, it's not highly | 
|     recommended. | 
|   | 
|     Version History: | 
|   | 
|         0.1.0 pil mod   March 10, 2009 | 
|   | 
|                         Renamed display profile to proof profile. The proof | 
|                         profile is the profile of the device that is being | 
|                         simulated, not the profile of the device which is | 
|                         actually used to display/print the final simulation | 
|                         (that'd be the output profile) - also see LCMSAPI.txt | 
|                         input colorspace -> using 'renderingIntent' -> proof | 
|                         colorspace -> using 'proofRenderingIntent' -> output | 
|                         colorspace | 
|   | 
|                         Added LCMS FLAGS support. | 
|                         Added FLAGS["SOFTPROOFING"] as default flag for | 
|                         buildProofTransform (otherwise the proof profile/intent | 
|                         would be ignored). | 
|   | 
|         0.1.0 pil       March 2009 - added to PIL, as PIL.ImageCms | 
|   | 
|         0.0.2 alpha     Jan 6, 2002 | 
|   | 
|                         Added try/except statements arount type() checks of | 
|                         potential CObjects... Python won't let you use type() | 
|                         on them, and raises a TypeError (stupid, if you ask me!) | 
|   | 
|                         Added buildProofTransformFromOpenProfiles() function. | 
|                         Additional fixes in DLL, see DLL code for details. | 
|   | 
|         0.0.1 alpha     first public release, Dec. 26, 2002 | 
|   | 
|     Known to-do list with current version (of Python interface, not pyCMSdll): | 
|   | 
|         none | 
|   | 
| """ | 
|   | 
| VERSION = "0.1.0 pil" | 
|   | 
| # --------------------------------------------------------------------. | 
|   | 
| import Image | 
| import _imagingcms | 
|   | 
| core = _imagingcms | 
|   | 
| # | 
| # intent/direction values | 
|   | 
| INTENT_PERCEPTUAL = 0 | 
| INTENT_RELATIVE_COLORIMETRIC = 1 | 
| INTENT_SATURATION = 2 | 
| INTENT_ABSOLUTE_COLORIMETRIC = 3 | 
|   | 
| DIRECTION_INPUT = 0 | 
| DIRECTION_OUTPUT = 1 | 
| DIRECTION_PROOF = 2 | 
|   | 
| # | 
| # flags | 
|   | 
| FLAGS = { | 
|     "MATRIXINPUT": 1, | 
|     "MATRIXOUTPUT": 2, | 
|     "MATRIXONLY": (1|2), | 
|     "NOWHITEONWHITEFIXUP": 4, # Don't hot fix scum dot | 
|     "NOPRELINEARIZATION": 16, # Don't create prelinearization tables on precalculated transforms (internal use) | 
|     "GUESSDEVICECLASS": 32, # Guess device class (for transform2devicelink) | 
|     "NOTCACHE": 64, # Inhibit 1-pixel cache | 
|     "NOTPRECALC": 256, | 
|     "NULLTRANSFORM": 512, # Don't transform anyway | 
|     "HIGHRESPRECALC": 1024, # Use more memory to give better accurancy | 
|     "LOWRESPRECALC": 2048, # Use less memory to minimize resouces | 
|     "WHITEBLACKCOMPENSATION": 8192, | 
|     "BLACKPOINTCOMPENSATION": 8192, | 
|     "GAMUTCHECK": 4096, # Out of Gamut alarm | 
|     "SOFTPROOFING": 16384, # Do softproofing | 
|     "PRESERVEBLACK": 32768, # Black preservation | 
|     "NODEFAULTRESOURCEDEF": 16777216, # CRD special | 
|     "GRIDPOINTS": lambda n: ((n) & 0xFF) << 16 # Gridpoints | 
| } | 
|   | 
| _MAX_FLAG = 0 | 
| for flag in FLAGS.values(): | 
|     if isinstance(flag, type(0)): | 
|         _MAX_FLAG = _MAX_FLAG | flag | 
|   | 
| # --------------------------------------------------------------------. | 
| # Experimental PIL-level API | 
| # --------------------------------------------------------------------. | 
|   | 
| ## | 
| # Profile. | 
|   | 
| class ImageCmsProfile: | 
|   | 
|     def __init__(self, profile): | 
|         # accepts a string (filename), a file-like object, or a low-level | 
|         # profile object | 
|         if Image.isStringType(profile): | 
|             self._set(core.profile_open(profile), profile) | 
|         elif hasattr(profile, "read"): | 
|             self._set(core.profile_fromstring(profile.read())) | 
|         else: | 
|             self._set(profile) # assume it's already a profile | 
|   | 
|     def _set(self, profile, filename=None): | 
|         self.profile = profile | 
|         self.filename = filename | 
|         if profile: | 
|             self.product_name = profile.product_name | 
|             self.product_info = profile.product_info | 
|         else: | 
|             self.product_name = None | 
|             self.product_info = None | 
|   | 
| ## | 
| # Transform.  This can be used with the procedural API, or with the | 
| # standard {@link Image.point} method. | 
|   | 
| class ImageCmsTransform(Image.ImagePointHandler): | 
|   | 
|     def __init__(self, input, output, input_mode, output_mode, | 
|                  intent=INTENT_PERCEPTUAL, | 
|                  proof=None, proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0): | 
|         if proof is None: | 
|             self.transform = core.buildTransform( | 
|                 input.profile, output.profile, | 
|                 input_mode, output_mode, | 
|                 intent, | 
|                 flags | 
|                 ) | 
|         else: | 
|             self.transform = core.buildProofTransform( | 
|                 input.profile, output.profile, proof.profile, | 
|                 input_mode, output_mode, | 
|                 intent, proof_intent, | 
|                 flags | 
|                 ) | 
|         # Note: inputMode and outputMode are for pyCMS compatibility only | 
|         self.input_mode = self.inputMode = input_mode | 
|         self.output_mode = self.outputMode = output_mode | 
|   | 
|     def point(self, im): | 
|         return self.apply(im) | 
|   | 
|     def apply(self, im, imOut=None): | 
|         im.load() | 
|         if imOut is None: | 
|             imOut = Image.new(self.output_mode, im.size, None) | 
|         result = self.transform.apply(im.im.id, imOut.im.id) | 
|         return imOut | 
|   | 
|     def apply_in_place(self, im): | 
|         im.load() | 
|         if im.mode != self.output_mode: | 
|             raise ValueError("mode mismatch") # wrong output mode | 
|         result = self.transform.apply(im.im.id, im.im.id) | 
|         return im | 
|   | 
| ## | 
| # (experimental) Fetches the profile for the current display device. | 
| # Returns None if the profile is not known. | 
|   | 
| def get_display_profile(handle=None): | 
|     import sys | 
|     if sys.platform == "win32": | 
|         import ImageWin | 
|         if isinstance(handle, ImageWin.HDC): | 
|             profile = core.get_display_profile_win32(handle, 1) | 
|         else: | 
|             profile = core.get_display_profile_win32(handle or 0) | 
|     else: | 
|         try: | 
|             get = _imagingcms.get_display_profile | 
|         except AttributeError: | 
|             return None | 
|         else: | 
|             profile = get() | 
|     return ImageCmsProfile(profile) | 
|   | 
| # --------------------------------------------------------------------. | 
| # pyCMS compatible layer | 
| # --------------------------------------------------------------------. | 
|   | 
| ## | 
| # (pyCMS) Exception class.  This is used for all errors in the pyCMS API. | 
|   | 
| class PyCMSError(Exception): | 
|     pass | 
|   | 
| ## | 
| # (pyCMS) Applies an ICC transformation to a given image, mapping from | 
| # inputProfile to outputProfile. | 
|   | 
| def profileToProfile(im, inputProfile, outputProfile, renderingIntent=INTENT_PERCEPTUAL, outputMode=None, inPlace=0, flags=0): | 
|     """ | 
|     ImageCms.profileToProfile(im, inputProfile, outputProfile, | 
|         [renderingIntent], [outputMode], [inPlace]) | 
|   | 
|     Returns either None or a new PIL image object, depending on value of | 
|     inPlace (see below). | 
|   | 
|     im = an open PIL image object (i.e. Image.new(...) or | 
|         Image.open(...), etc.) | 
|     inputProfile = string, as a valid filename path to the ICC input | 
|         profile you wish to use for this image, or a profile object | 
|     outputProfile = string, as a valid filename path to the ICC output | 
|         profile you wish to use for this image, or a profile object | 
|     renderingIntent = integer (0-3) specifying the rendering intent you | 
|         wish to use for the transform | 
|         INTENT_PERCEPTUAL =           0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) | 
|         INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) | 
|         INTENT_SATURATION =           2 (ImageCms.INTENT_SATURATION) | 
|         INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) | 
|   | 
|         see the pyCMS documentation for details on rendering intents and | 
|         what they do. | 
|     outputMode = a valid PIL mode for the output image (i.e. "RGB", "CMYK", | 
|         etc.).  Note: if rendering the image "inPlace", outputMode MUST be | 
|         the same mode as the input, or omitted completely.  If omitted, the | 
|         outputMode will be the same as the mode of the input image (im.mode) | 
|     inPlace = BOOL (1 = TRUE, None or 0 = FALSE).  If TRUE, the original | 
|         image is modified in-place, and None is returned.  If FALSE | 
|         (default), a new Image object is returned with the transform | 
|         applied. | 
|     flags = integer (0-...) specifying additional flags | 
|   | 
|     If the input or output profiles specified are not valid filenames, a | 
|     PyCMSError will be raised.  If inPlace == TRUE and outputMode != im.mode, | 
|     a PyCMSError will be raised.  If an error occurs during application of | 
|     the profiles, a PyCMSError will be raised.  If outputMode is not a mode | 
|     supported by the outputProfile (or by pyCMS), a PyCMSError will be | 
|     raised. | 
|   | 
|     This function applies an ICC transformation to im from inputProfile's | 
|     color space to outputProfile's color space using the specified rendering | 
|     intent to decide how to handle out-of-gamut colors. | 
|   | 
|     OutputMode can be used to specify that a color mode conversion is to | 
|     be done using these profiles, but the specified profiles must be able | 
|     to handle that mode.  I.e., if converting im from RGB to CMYK using | 
|     profiles, the input profile must handle RGB data, and the output | 
|     profile must handle CMYK data. | 
|   | 
|     """ | 
|   | 
|     if outputMode is None: | 
|         outputMode = im.mode | 
|   | 
|     if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3): | 
|         raise PyCMSError("renderingIntent must be an integer between 0 and 3") | 
|   | 
|     if type(flags) != type(1) or not (0 <= flags <= _MAX_FLAG): | 
|         raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG) | 
|   | 
|     try: | 
|         if not isinstance(inputProfile, ImageCmsProfile): | 
|             inputProfile = ImageCmsProfile(inputProfile) | 
|         if not isinstance(outputProfile, ImageCmsProfile): | 
|             outputProfile = ImageCmsProfile(outputProfile) | 
|         transform = ImageCmsTransform( | 
|             inputProfile, outputProfile, im.mode, outputMode, renderingIntent, flags=flags | 
|             ) | 
|         if inPlace: | 
|             transform.apply_in_place(im) | 
|             imOut = None | 
|         else: | 
|             imOut = transform.apply(im) | 
|     except (IOError, TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
|     return imOut | 
|   | 
| ## | 
| # (pyCMS) Opens an ICC profile file. | 
|   | 
| def getOpenProfile(profileFilename): | 
|     """ | 
|     ImageCms.getOpenProfile(profileFilename) | 
|   | 
|     Returns a CmsProfile class object. | 
|   | 
|     profileFilename = string, as a valid filename path to the ICC profile | 
|         you wish to open, or a file-like object. | 
|   | 
|     The PyCMSProfile object can be passed back into pyCMS for use in creating | 
|     transforms and such (as in ImageCms.buildTransformFromOpenProfiles()). | 
|   | 
|     If profileFilename is not a vaild filename for an ICC profile, a | 
|     PyCMSError will be raised. | 
|   | 
|     """ | 
|   | 
|     try: | 
|         return ImageCmsProfile(profileFilename) | 
|     except (IOError, TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
| ## | 
| # (pyCMS) Builds an ICC transform mapping from the inputProfile to the | 
| # outputProfile.  Use applyTransform to apply the transform to a given | 
| # image. | 
|   | 
| def buildTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent=INTENT_PERCEPTUAL, flags=0): | 
|     """ | 
|     ImageCms.buildTransform(inputProfile, outputProfile, inMode, outMode, | 
|         [renderingIntent]) | 
|   | 
|     Returns a CmsTransform class object. | 
|   | 
|     inputProfile = string, as a valid filename path to the ICC input | 
|         profile you wish to use for this transform, or a profile object | 
|     outputProfile = string, as a valid filename path to the ICC output | 
|         profile you wish to use for this transform, or a profile object | 
|     inMode = string, as a valid PIL mode that the appropriate profile also | 
|         supports (i.e. "RGB", "RGBA", "CMYK", etc.) | 
|     outMode = string, as a valid PIL mode that the appropriate profile also | 
|         supports (i.e. "RGB", "RGBA", "CMYK", etc.) | 
|     renderingIntent = integer (0-3) specifying the rendering intent you | 
|         wish to use for the transform | 
|         INTENT_PERCEPTUAL =           0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) | 
|         INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) | 
|         INTENT_SATURATION =           2 (ImageCms.INTENT_SATURATION) | 
|         INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) | 
|         see the pyCMS documentation for details on rendering intents and | 
|         what they do. | 
|     flags = integer (0-...) specifying additional flags | 
|   | 
|     If the input or output profiles specified are not valid filenames, a | 
|     PyCMSError will be raised.  If an error occurs during creation of the | 
|     transform, a PyCMSError will be raised. | 
|   | 
|     If inMode or outMode are not a mode supported by the outputProfile (or | 
|     by pyCMS), a PyCMSError will be raised. | 
|   | 
|     This function builds and returns an ICC transform from the inputProfile | 
|     to the outputProfile using the renderingIntent to determine what to do | 
|     with out-of-gamut colors.  It will ONLY work for converting images that | 
|     are in inMode to images that are in outMode color format (PIL mode, | 
|     i.e. "RGB", "RGBA", "CMYK", etc.). | 
|   | 
|     Building the transform is a fair part of the overhead in | 
|     ImageCms.profileToProfile(), so if you're planning on converting multiple | 
|     images using the same input/output settings, this can save you time. | 
|     Once you have a transform object, it can be used with | 
|     ImageCms.applyProfile() to convert images without the need to re-compute | 
|     the lookup table for the transform. | 
|   | 
|     The reason pyCMS returns a class object rather than a handle directly | 
|     to the transform is that it needs to keep track of the PIL input/output | 
|     modes that the transform is meant for.  These attributes are stored in | 
|     the "inMode" and "outMode" attributes of the object (which can be | 
|     manually overridden if you really want to, but I don't know of any | 
|     time that would be of use, or would even work). | 
|   | 
|     """ | 
|   | 
|     if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3): | 
|         raise PyCMSError("renderingIntent must be an integer between 0 and 3") | 
|   | 
|     if type(flags) != type(1) or not (0 <= flags <= _MAX_FLAG): | 
|         raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG) | 
|   | 
|     try: | 
|         if not isinstance(inputProfile, ImageCmsProfile): | 
|             inputProfile = ImageCmsProfile(inputProfile) | 
|         if not isinstance(outputProfile, ImageCmsProfile): | 
|             outputProfile = ImageCmsProfile(outputProfile) | 
|         return ImageCmsTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent, flags=flags) | 
|     except (IOError, TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
| ## | 
| # (pyCMS) Builds an ICC transform mapping from the inputProfile to the | 
| # outputProfile, but tries to simulate the result that would be | 
| # obtained on the proofProfile device. | 
|   | 
| def buildProofTransform(inputProfile, outputProfile, proofProfile, inMode, outMode, renderingIntent=INTENT_PERCEPTUAL, proofRenderingIntent=INTENT_ABSOLUTE_COLORIMETRIC, flags=FLAGS["SOFTPROOFING"]): | 
|     """ | 
|     ImageCms.buildProofTransform(inputProfile, outputProfile, proofProfile, | 
|         inMode, outMode, [renderingIntent], [proofRenderingIntent]) | 
|   | 
|     Returns a CmsTransform class object. | 
|   | 
|     inputProfile = string, as a valid filename path to the ICC input | 
|         profile you wish to use for this transform, or a profile object | 
|     outputProfile = string, as a valid filename path to the ICC output | 
|         (monitor, usually) profile you wish to use for this transform, | 
|         or a profile object | 
|     proofProfile = string, as a valid filename path to the ICC proof | 
|         profile you wish to use for this transform, or a profile object | 
|     inMode = string, as a valid PIL mode that the appropriate profile also | 
|         supports (i.e. "RGB", "RGBA", "CMYK", etc.) | 
|     outMode = string, as a valid PIL mode that the appropriate profile also | 
|         supports (i.e. "RGB", "RGBA", "CMYK", etc.) | 
|     renderingIntent = integer (0-3) specifying the rendering intent you | 
|         wish to use for the input->proof (simulated) transform | 
|         INTENT_PERCEPTUAL =           0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) | 
|         INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) | 
|         INTENT_SATURATION =           2 (ImageCms.INTENT_SATURATION) | 
|         INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) | 
|         see the pyCMS documentation for details on rendering intents and | 
|         what they do. | 
|     proofRenderingIntent = integer (0-3) specifying the rendering intent | 
|         you wish to use for proof->output transform | 
|         INTENT_PERCEPTUAL =           0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) | 
|         INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) | 
|         INTENT_SATURATION =           2 (ImageCms.INTENT_SATURATION) | 
|         INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) | 
|         see the pyCMS documentation for details on rendering intents and | 
|         what they do. | 
|     flags = integer (0-...) specifying additional flags | 
|   | 
|     If the input, output, or proof profiles specified are not valid | 
|     filenames, a PyCMSError will be raised. | 
|   | 
|     If an error occurs during creation of the transform, a PyCMSError will | 
|     be raised. | 
|   | 
|     If inMode or outMode are not a mode supported by the outputProfile | 
|     (or by pyCMS), a PyCMSError will be raised. | 
|   | 
|     This function builds and returns an ICC transform from the inputProfile | 
|     to the outputProfile, but tries to simulate the result that would be | 
|     obtained on the proofProfile device using renderingIntent and | 
|     proofRenderingIntent to determine what to do with out-of-gamut | 
|     colors.  This is known as "soft-proofing".  It will ONLY work for | 
|     converting images that are in inMode to images that are in outMode | 
|     color format (PIL mode, i.e. "RGB", "RGBA", "CMYK", etc.). | 
|   | 
|     Usage of the resulting transform object is exactly the same as with | 
|     ImageCms.buildTransform(). | 
|   | 
|     Proof profiling is generally used when using an output device to get a | 
|     good idea of what the final printed/displayed image would look like on | 
|     the proofProfile device when it's quicker and easier to use the | 
|     output device for judging color.  Generally, this means that the | 
|     output device is a monitor, or a dye-sub printer (etc.), and the simulated | 
|     device is something more expensive, complicated, or time consuming | 
|     (making it difficult to make a real print for color judgement purposes). | 
|   | 
|     Soft-proofing basically functions by adjusting the colors on the | 
|     output device to match the colors of the device being simulated. However, | 
|     when the simulated device has a much wider gamut than the output | 
|     device, you may obtain marginal results. | 
|   | 
|     """ | 
|   | 
|     if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3): | 
|         raise PyCMSError("renderingIntent must be an integer between 0 and 3") | 
|   | 
|     if type(flags) != type(1) or not (0 <= flags <= _MAX_FLAG): | 
|         raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG) | 
|   | 
|     try: | 
|         if not isinstance(inputProfile, ImageCmsProfile): | 
|             inputProfile = ImageCmsProfile(inputProfile) | 
|         if not isinstance(outputProfile, ImageCmsProfile): | 
|             outputProfile = ImageCmsProfile(outputProfile) | 
|         if not isinstance(proofProfile, ImageCmsProfile): | 
|             proofProfile = ImageCmsProfile(proofProfile) | 
|         return ImageCmsTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent, proofProfile, proofRenderingIntent, flags) | 
|     except (IOError, TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
| buildTransformFromOpenProfiles = buildTransform | 
| buildProofTransformFromOpenProfiles = buildProofTransform | 
|   | 
| ## | 
| # (pyCMS) Applies a transform to a given image. | 
|   | 
| def applyTransform(im, transform, inPlace=0): | 
|     """ | 
|     ImageCms.applyTransform(im, transform, [inPlace]) | 
|   | 
|     Returns either None, or a new PIL Image object, depending on the value | 
|         of inPlace (see below) | 
|   | 
|     im = a PIL Image object, and im.mode must be the same as the inMode | 
|         supported by the transform. | 
|     transform = a valid CmsTransform class object | 
|     inPlace = BOOL (1 == TRUE, 0 or None == FALSE).  If TRUE, im is | 
|         modified in place and None is returned, if FALSE, a new Image | 
|         object with the transform applied is returned (and im is not | 
|         changed).  The default is FALSE. | 
|   | 
|     If im.mode != transform.inMode, a PyCMSError is raised. | 
|   | 
|     If inPlace == TRUE and transform.inMode != transform.outMode, a | 
|     PyCMSError is raised. | 
|   | 
|     If im.mode, transfer.inMode, or transfer.outMode is not supported by | 
|     pyCMSdll or the profiles you used for the transform, a PyCMSError is | 
|     raised. | 
|   | 
|     If an error occurs while the transform is being applied, a PyCMSError | 
|     is raised. | 
|   | 
|     This function applies a pre-calculated transform (from | 
|     ImageCms.buildTransform() or ImageCms.buildTransformFromOpenProfiles()) to an | 
|     image.  The transform can be used for multiple images, saving | 
|     considerable calcuation time if doing the same conversion multiple times. | 
|   | 
|     If you want to modify im in-place instead of receiving a new image as | 
|     the return value, set inPlace to TRUE.  This can only be done if | 
|     transform.inMode and transform.outMode are the same, because we can't | 
|     change the mode in-place (the buffer sizes for some modes are | 
|     different).  The  default behavior is to return a new Image object of | 
|     the same dimensions in mode transform.outMode. | 
|   | 
|     """ | 
|   | 
|     try: | 
|         if inPlace: | 
|             transform.apply_in_place(im) | 
|             imOut = None | 
|         else: | 
|             imOut = transform.apply(im) | 
|     except (TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
|     return imOut | 
|   | 
| ## | 
| # (pyCMS) Creates a profile. | 
|   | 
| def createProfile(colorSpace, colorTemp=-1): | 
|     """ | 
|     ImageCms.createProfile(colorSpace, [colorTemp]) | 
|   | 
|     Returns a CmsProfile class object | 
|   | 
|     colorSpace = string, the color space of the profile you wish to create. | 
|         Currently only "LAB", "XYZ", and "sRGB" are supported. | 
|     colorTemp = positive integer for the white point for the profile, in | 
|         degrees Kelvin (i.e. 5000, 6500, 9600, etc.).  The default is for | 
|         D50 illuminant if omitted (5000k).  colorTemp is ONLY applied to | 
|         LAB profiles, and is ignored for XYZ and sRGB. | 
|   | 
|     If colorSpace not in ["LAB", "XYZ", "sRGB"], a PyCMSError is raised | 
|   | 
|     If using LAB and colorTemp != a positive integer, a PyCMSError is raised. | 
|   | 
|     If an error occurs while creating the profile, a PyCMSError is raised. | 
|   | 
|     Use this function to create common profiles on-the-fly instead of | 
|     having to supply a profile on disk and knowing the path to it.  It | 
|     returns a normal CmsProfile object that can be passed to | 
|     ImageCms.buildTransformFromOpenProfiles() to create a transform to apply | 
|     to images. | 
|   | 
|     """ | 
|     if colorSpace not in ["LAB", "XYZ", "sRGB"]: | 
|         raise PyCMSError("Color space not supported for on-the-fly profile creation (%s)" % colorSpace) | 
|   | 
|     if colorSpace == "LAB": | 
|         if type(colorTemp) == type(5000.0): | 
|             colorTemp = int(colorTemp + 0.5) | 
|         if type (colorTemp) != type (5000): | 
|             raise PyCMSError("Color temperature must be a positive integer, \"%s\" not valid" % colorTemp) | 
|   | 
|     try: | 
|         return core.createProfile(colorSpace, colorTemp) | 
|     except (TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
| ## | 
| # (pyCMS) Gets the internal product name for the given profile. | 
|   | 
| def getProfileName(profile): | 
|     """ | 
|     ImageCms.getProfileName(profile) | 
|   | 
|     Returns a string containing the internal name of the profile as stored | 
|         in an ICC tag. | 
|   | 
|     profile = EITHER a valid CmsProfile object, OR a string of the | 
|         filename of an ICC profile. | 
|   | 
|     If profile isn't a valid CmsProfile object or filename to a profile, | 
|     a PyCMSError is raised If an error occurs while trying to obtain the | 
|     name tag, a PyCMSError is raised. | 
|   | 
|     Use this function to obtain the INTERNAL name of the profile (stored | 
|     in an ICC tag in the profile itself), usually the one used when the | 
|     profile was originally created.  Sometimes this tag also contains | 
|     additional information supplied by the creator. | 
|   | 
|     """ | 
|     try: | 
|         # add an extra newline to preserve pyCMS compatibility | 
|         if not isinstance(profile, ImageCmsProfile): | 
|             profile = ImageCmsProfile(profile) | 
|         return profile.profile.product_name + "\n" | 
|     except (AttributeError, IOError, TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
| ## | 
| # (pyCMS) Gets the internal product information for the given profile. | 
|   | 
| def getProfileInfo(profile): | 
|     """ | 
|     ImageCms.getProfileInfo(profile) | 
|   | 
|     Returns a string containing the internal profile information stored in | 
|         an ICC tag. | 
|   | 
|     profile = EITHER a valid CmsProfile object, OR a string of the | 
|         filename of an ICC profile. | 
|   | 
|     If profile isn't a valid CmsProfile object or filename to a profile, | 
|     a PyCMSError is raised. | 
|   | 
|     If an error occurs while trying to obtain the info tag, a PyCMSError | 
|     is raised | 
|   | 
|     Use this function to obtain the information stored in the profile's | 
|     info tag.  This often contains details about the profile, and how it | 
|     was created, as supplied by the creator. | 
|   | 
|     """ | 
|     try: | 
|         if not isinstance(profile, ImageCmsProfile): | 
|             profile = ImageCmsProfile(profile) | 
|         # add an extra newline to preserve pyCMS compatibility | 
|         return profile.product_info + "\n" | 
|     except (AttributeError, IOError, TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
| ## | 
| # (pyCMS) Gets the default intent name for the given profile. | 
|   | 
| def getDefaultIntent(profile): | 
|     """ | 
|     ImageCms.getDefaultIntent(profile) | 
|   | 
|     Returns integer 0-3 specifying the default rendering intent for this | 
|         profile. | 
|         INTENT_PERCEPTUAL =           0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) | 
|         INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) | 
|         INTENT_SATURATION =           2 (ImageCms.INTENT_SATURATION) | 
|         INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) | 
|         see the pyCMS documentation for details on rendering intents and | 
|         what they do. | 
|   | 
|     profile = EITHER a valid CmsProfile object, OR a string of the | 
|         filename of an ICC profile. | 
|   | 
|     If profile isn't a valid CmsProfile object or filename to a profile, | 
|     a PyCMSError is raised. | 
|   | 
|     If an error occurs while trying to obtain the default intent, a | 
|     PyCMSError is raised. | 
|   | 
|     Use this function to determine the default (and usually best optomized) | 
|     rendering intent for this profile.  Most profiles support multiple | 
|     rendering intents, but are intended mostly for one type of conversion. | 
|     If you wish to use a different intent than returned, use | 
|     ImageCms.isIntentSupported() to verify it will work first. | 
|     """ | 
|     try: | 
|         if not isinstance(profile, ImageCmsProfile): | 
|             profile = ImageCmsProfile(profile) | 
|         return profile.profile.rendering_intent | 
|     except (AttributeError, IOError, TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
| ## | 
| # (pyCMS) Checks if a given intent is supported. | 
|   | 
| def isIntentSupported(profile, intent, direction): | 
|     """ | 
|     ImageCms.isIntentSupported(profile, intent, direction) | 
|   | 
|     Returns 1 if the intent/direction are supported, -1 if they are not. | 
|   | 
|     profile = EITHER a valid CmsProfile object, OR a string of the | 
|         filename of an ICC profile. | 
|     intent = integer (0-3) specifying the rendering intent you wish to use | 
|         with this profile | 
|         INTENT_PERCEPTUAL =           0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) | 
|         INTENT_RELATIVE_COLORIMETRIC =1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) | 
|         INTENT_SATURATION =           2 (ImageCms.INTENT_SATURATION) | 
|         INTENT_ABSOLUTE_COLORIMETRIC =3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) | 
|         see the pyCMS documentation for details on rendering intents and | 
|         what they do. | 
|     direction = integer specifing if the profile is to be used for input, | 
|         output, or proof | 
|         INPUT =               0 (or use ImageCms.DIRECTION_INPUT) | 
|         OUTPUT =              1 (or use ImageCms.DIRECTION_OUTPUT) | 
|         PROOF =               2 (or use ImageCms.DIRECTION_PROOF) | 
|   | 
|     Use this function to verify that you can use your desired | 
|     renderingIntent with profile, and that profile can be used for the | 
|     input/output/proof profile as you desire. | 
|   | 
|     Some profiles are created specifically for one "direction", can cannot | 
|     be used for others.  Some profiles can only be used for certain | 
|     rendering intents... so it's best to either verify this before trying | 
|     to create a transform with them (using this function), or catch the | 
|     potential PyCMSError that will occur if they don't support the modes | 
|     you select. | 
|   | 
|     """ | 
|     try: | 
|         if not isinstance(profile, ImageCmsProfile): | 
|             profile = ImageCmsProfile(profile) | 
|         # FIXME: I get different results for the same data w. different | 
|         # compilers.  Bug in LittleCMS or in the binding? | 
|         if profile.profile.is_intent_supported(intent, direction): | 
|             return 1 | 
|         else: | 
|             return -1 | 
|     except (AttributeError, IOError, TypeError, ValueError), v: | 
|         raise PyCMSError(v) | 
|   | 
| ## | 
| # (pyCMS) Fetches versions. | 
|   | 
| def versions(): | 
|     import sys | 
|     return ( | 
|         VERSION, core.littlecms_version, sys.version.split()[0], Image.VERSION | 
|         ) | 
|   | 
| # -------------------------------------------------------------------- | 
|   | 
| if __name__ == "__main__": | 
|     # create a cheap manual from the __doc__ strings for the functions above | 
|   | 
|     import ImageCms | 
|     import string | 
|     print __doc__ | 
|   | 
|     for f in dir(pyCMS): | 
|         print "="*80 | 
|         print "%s" %f | 
|   | 
|         try: | 
|             exec ("doc = ImageCms.%s.__doc__" %(f)) | 
|             if string.find(doc, "pyCMS") >= 0: | 
|                 # so we don't get the __doc__ string for imported modules | 
|                 print doc | 
|         except AttributeError: | 
|             pass |