summaryrefslogtreecommitdiffstats
path: root/lib/Python/Lib/PIL/ImageCms.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Python/Lib/PIL/ImageCms.py')
-rw-r--r--lib/Python/Lib/PIL/ImageCms.py972
1 files changed, 972 insertions, 0 deletions
diff --git a/lib/Python/Lib/PIL/ImageCms.py b/lib/Python/Lib/PIL/ImageCms.py
new file mode 100644
index 000000000..ed219f7ba
--- /dev/null
+++ b/lib/Python/Lib/PIL/ImageCms.py
@@ -0,0 +1,972 @@
+# 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
+# Copyright (c) 2013 by Eric Soroos
+
+# See the README file for information on usage and redistribution. See
+# below for the original description.
+
+from __future__ import print_function
+
+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:
+
+ 1.0.0 pil Oct 2013 Port to LCMS 2.
+
+ 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 = "1.0.0 pil"
+
+# --------------------------------------------------------------------.
+
+from PIL import Image
+try:
+ from PIL import _imagingcms
+except ImportError as ex:
+ # Allow error import for doc purposes, but error out when accessing
+ # anything in core.
+ from _util import deferred_error
+ _imagingcms = deferred_error(ex)
+from PIL._util import isStringType
+
+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
+ # Don't create prelinearization tables on precalculated transforms
+ # (internal use):
+ "NOPRELINEARIZATION": 16,
+ "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, int):
+ _MAX_FLAG = _MAX_FLAG | flag
+
+
+# --------------------------------------------------------------------.
+# Experimental PIL-level API
+# --------------------------------------------------------------------.
+
+##
+# Profile.
+
+class ImageCmsProfile:
+
+ def __init__(self, profile):
+ """
+ :param profile: Either a string representing a filename,
+ a file like object containing a profile or a
+ low-level profile object
+
+ """
+
+ if isStringType(profile):
+ self._set(core.profile_open(profile), profile)
+ elif hasattr(profile, "read"):
+ self._set(core.profile_frombytes(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 = None # profile.product_name
+ self.product_info = None # profile.product_info
+ else:
+ self.product_name = None
+ self.product_info = None
+
+ def tobytes(self):
+ """
+ Returns the profile in a format suitable for embedding in
+ saved images.
+
+ :returns: a bytes object containing the ICC profile.
+ """
+
+ return core.profile_tobytes(self.profile)
+
+
+class ImageCmsTransform(Image.ImagePointHandler):
+
+ # Transform. This can be used with the procedural API, or with the
+ # standard Image.point() method.
+ #
+ # Will return the output profile in the output.info['icc_profile'].
+
+ 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
+
+ self.output_profile = output
+
+ 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)
+ self.transform.apply(im.im.id, imOut.im.id)
+ imOut.info['icc_profile'] = self.output_profile.tobytes()
+ return imOut
+
+ def apply_in_place(self, im):
+ im.load()
+ if im.mode != self.output_mode:
+ raise ValueError("mode mismatch") # wrong output mode
+ self.transform.apply(im.im.id, im.im.id)
+ im.info['icc_profile'] = self.output_profile.tobytes()
+ return im
+
+
+def get_display_profile(handle=None):
+ """ (experimental) Fetches the profile for the current display device.
+ :returns: None if the profile is not known.
+ """
+
+ import sys
+ if sys.platform == "win32":
+ from PIL 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
+# --------------------------------------------------------------------.
+
+class PyCMSError(Exception):
+
+ """ (pyCMS) Exception class.
+ This is used for all errors in the pyCMS API. """
+ pass
+
+
+def profileToProfile(
+ im, inputProfile, outputProfile, renderingIntent=INTENT_PERCEPTUAL,
+ outputMode=None, inPlace=0, flags=0):
+ """
+ (pyCMS) Applies an ICC transformation to a given image, mapping from
+ inputProfile to outputProfile.
+
+ 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.
+
+ :param im: An open PIL image object (i.e. Image.new(...) or
+ Image.open(...), etc.)
+ :param inputProfile: String, as a valid filename path to the ICC input
+ profile you wish to use for this image, or a profile object
+ :param outputProfile: String, as a valid filename path to the ICC output
+ profile you wish to use for this image, or a profile object
+ :param 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.
+ :param 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)
+ :param inPlace: Boolean (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.
+ :param flags: Integer (0-...) specifying additional flags
+ :returns: Either None or a new PIL image object, depending on value of
+ inPlace
+ :exception PyCMSError:
+ """
+
+ if outputMode is None:
+ outputMode = im.mode
+
+ if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
+ raise PyCMSError("renderingIntent must be an integer between 0 and 3")
+
+ if not isinstance(flags, int) 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) as v:
+ raise PyCMSError(v)
+
+ return imOut
+
+
+def getOpenProfile(profileFilename):
+ """
+ (pyCMS) Opens an ICC profile file.
+
+ 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.
+
+ :param profileFilename: String, as a valid filename path to the ICC profile
+ you wish to open, or a file-like object.
+ :returns: A CmsProfile class object.
+ :exception PyCMSError:
+ """
+
+ try:
+ return ImageCmsProfile(profileFilename)
+ except (IOError, TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def buildTransform(
+ inputProfile, outputProfile, inMode, outMode,
+ renderingIntent=INTENT_PERCEPTUAL, flags=0):
+ """
+ (pyCMS) Builds an ICC transform mapping from the inputProfile to the
+ outputProfile. Use applyTransform to apply the transform to a given
+ image.
+
+ 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).
+
+ :param inputProfile: String, as a valid filename path to the ICC input
+ profile you wish to use for this transform, or a profile object
+ :param outputProfile: String, as a valid filename path to the ICC output
+ profile you wish to use for this transform, or a profile object
+ :param inMode: String, as a valid PIL mode that the appropriate profile
+ also supports (i.e. "RGB", "RGBA", "CMYK", etc.)
+ :param outMode: String, as a valid PIL mode that the appropriate profile
+ also supports (i.e. "RGB", "RGBA", "CMYK", etc.)
+ :param 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.
+ :param flags: Integer (0-...) specifying additional flags
+ :returns: A CmsTransform class object.
+ :exception PyCMSError:
+ """
+
+ if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
+ raise PyCMSError("renderingIntent must be an integer between 0 and 3")
+
+ if not isinstance(flags, int) 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) as v:
+ raise PyCMSError(v)
+
+
+def buildProofTransform(
+ inputProfile, outputProfile, proofProfile, inMode, outMode,
+ renderingIntent=INTENT_PERCEPTUAL,
+ proofRenderingIntent=INTENT_ABSOLUTE_COLORIMETRIC,
+ flags=FLAGS["SOFTPROOFING"]):
+ """
+ (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.
+
+ 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.
+
+ :param inputProfile: String, as a valid filename path to the ICC input
+ profile you wish to use for this transform, or a profile object
+ :param 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
+ :param proofProfile: String, as a valid filename path to the ICC proof
+ profile you wish to use for this transform, or a profile object
+ :param inMode: String, as a valid PIL mode that the appropriate profile
+ also supports (i.e. "RGB", "RGBA", "CMYK", etc.)
+ :param outMode: String, as a valid PIL mode that the appropriate profile
+ also supports (i.e. "RGB", "RGBA", "CMYK", etc.)
+ :param 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.
+ :param 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.
+ :param flags: Integer (0-...) specifying additional flags
+ :returns: A CmsTransform class object.
+ :exception PyCMSError:
+ """
+
+ if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
+ raise PyCMSError("renderingIntent must be an integer between 0 and 3")
+
+ if not isinstance(flags, int) 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) as v:
+ raise PyCMSError(v)
+
+buildTransformFromOpenProfiles = buildTransform
+buildProofTransformFromOpenProfiles = buildProofTransform
+
+
+def applyTransform(im, transform, inPlace=0):
+ """
+ (pyCMS) Applies a transform to a given image.
+
+ 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.
+
+ :param im: A PIL Image object, and im.mode must be the same as the inMode
+ supported by the transform.
+ :param transform: A valid CmsTransform class object
+ :param 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.
+ :returns: Either None, or a new PIL Image object, depending on the value of
+ inPlace. The profile will be returned in the image's info['icc_profile'].
+ :exception PyCMSError:
+ """
+
+ try:
+ if inPlace:
+ transform.apply_in_place(im)
+ imOut = None
+ else:
+ imOut = transform.apply(im)
+ except (TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+ return imOut
+
+
+def createProfile(colorSpace, colorTemp=-1):
+ """
+ (pyCMS) Creates a profile.
+
+ 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.
+
+ :param colorSpace: String, the color space of the profile you wish to
+ create.
+ Currently only "LAB", "XYZ", and "sRGB" are supported.
+ :param 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.
+ :returns: A CmsProfile class object
+ :exception PyCMSError:
+ """
+
+ if colorSpace not in ["LAB", "XYZ", "sRGB"]:
+ raise PyCMSError(
+ "Color space not supported for on-the-fly profile creation (%s)"
+ % colorSpace)
+
+ if colorSpace == "LAB":
+ try:
+ colorTemp = float(colorTemp)
+ except:
+ raise PyCMSError(
+ "Color temperature must be numeric, \"%s\" not valid"
+ % colorTemp)
+
+ try:
+ return core.createProfile(colorSpace, colorTemp)
+ except (TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def getProfileName(profile):
+ """
+
+ (pyCMS) Gets the internal product name for the given 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.
+
+ :param profile: EITHER a valid CmsProfile object, OR a string of the
+ filename of an ICC profile.
+ :returns: A string containing the internal name of the profile as stored
+ in an ICC tag.
+ :exception PyCMSError:
+ """
+
+ try:
+ # add an extra newline to preserve pyCMS compatibility
+ if not isinstance(profile, ImageCmsProfile):
+ profile = ImageCmsProfile(profile)
+ # do it in python, not c.
+ # // name was "%s - %s" (model, manufacturer) || Description ,
+ # // but if the Model and Manufacturer were the same or the model
+ # // was long, Just the model, in 1.x
+ model = profile.profile.product_model
+ manufacturer = profile.profile.product_manufacturer
+
+ if not (model or manufacturer):
+ return profile.profile.product_description + "\n"
+ if not manufacturer or len(model) > 30:
+ return model + "\n"
+ return "%s - %s\n" % (model, manufacturer)
+
+ except (AttributeError, IOError, TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def getProfileInfo(profile):
+ """
+ (pyCMS) Gets the internal product information for the given 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.
+
+ :param profile: EITHER a valid CmsProfile object, OR a string of the
+ filename of an ICC profile.
+ :returns: A string containing the internal profile information stored in
+ an ICC tag.
+ :exception PyCMSError:
+ """
+
+ try:
+ if not isinstance(profile, ImageCmsProfile):
+ profile = ImageCmsProfile(profile)
+ # add an extra newline to preserve pyCMS compatibility
+ # Python, not C. the white point bits weren't working well,
+ # so skipping.
+ # // info was description \r\n\r\n copyright \r\n\r\n K007 tag \r\n\r\n whitepoint
+ description = profile.profile.product_description
+ cpright = profile.profile.product_copyright
+ arr = []
+ for elt in (description, cpright):
+ if elt:
+ arr.append(elt)
+ return "\r\n\r\n".join(arr) + "\r\n\r\n"
+
+ except (AttributeError, IOError, TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def getProfileCopyright(profile):
+ """
+ (pyCMS) Gets the copyright for the given 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 copyright tag, a PyCMSError
+ is raised
+
+ Use this function to obtain the information stored in the profile's
+ copyright tag.
+
+ :param profile: EITHER a valid CmsProfile object, OR a string of the
+ filename of an ICC profile.
+ :returns: A string containing the internal profile information stored in
+ an ICC tag.
+ :exception PyCMSError:
+ """
+ try:
+ # add an extra newline to preserve pyCMS compatibility
+ if not isinstance(profile, ImageCmsProfile):
+ profile = ImageCmsProfile(profile)
+ return profile.profile.product_copyright + "\n"
+ except (AttributeError, IOError, TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def getProfileManufacturer(profile):
+ """
+ (pyCMS) Gets the manufacturer for the given 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 manufacturer tag, a
+ PyCMSError is raised
+
+ Use this function to obtain the information stored in the profile's
+ manufacturer tag.
+
+ :param profile: EITHER a valid CmsProfile object, OR a string of the
+ filename of an ICC profile.
+ :returns: A string containing the internal profile information stored in
+ an ICC tag.
+ :exception PyCMSError:
+ """
+ try:
+ # add an extra newline to preserve pyCMS compatibility
+ if not isinstance(profile, ImageCmsProfile):
+ profile = ImageCmsProfile(profile)
+ return profile.profile.product_manufacturer + "\n"
+ except (AttributeError, IOError, TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def getProfileModel(profile):
+ """
+ (pyCMS) Gets the model for the given 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 model tag, a PyCMSError
+ is raised
+
+ Use this function to obtain the information stored in the profile's
+ model tag.
+
+ :param profile: EITHER a valid CmsProfile object, OR a string of the
+ filename of an ICC profile.
+ :returns: A string containing the internal profile information stored in
+ an ICC tag.
+ :exception PyCMSError:
+ """
+
+ try:
+ # add an extra newline to preserve pyCMS compatibility
+ if not isinstance(profile, ImageCmsProfile):
+ profile = ImageCmsProfile(profile)
+ return profile.profile.product_model + "\n"
+ except (AttributeError, IOError, TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def getProfileDescription(profile):
+ """
+ (pyCMS) Gets the description for the given 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 description tag, a PyCMSError
+ is raised
+
+ Use this function to obtain the information stored in the profile's
+ description tag.
+
+ :param profile: EITHER a valid CmsProfile object, OR a string of the
+ filename of an ICC profile.
+ :returns: A string containing the internal profile information stored in an
+ ICC tag.
+ :exception PyCMSError:
+ """
+
+ try:
+ # add an extra newline to preserve pyCMS compatibility
+ if not isinstance(profile, ImageCmsProfile):
+ profile = ImageCmsProfile(profile)
+ return profile.profile.product_description + "\n"
+ except (AttributeError, IOError, TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def getDefaultIntent(profile):
+ """
+ (pyCMS) Gets the default intent name for the given 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.
+
+ :param profile: EITHER a valid CmsProfile object, OR a string of the
+ filename of an ICC 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.
+ :exception PyCMSError:
+ """
+
+ try:
+ if not isinstance(profile, ImageCmsProfile):
+ profile = ImageCmsProfile(profile)
+ return profile.profile.rendering_intent
+ except (AttributeError, IOError, TypeError, ValueError) as v:
+ raise PyCMSError(v)
+
+
+def isIntentSupported(profile, intent, direction):
+ """
+ (pyCMS) Checks if a given intent is supported.
+
+ 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.
+
+ :param profile: EITHER a valid CmsProfile object, OR a string of the
+ filename of an ICC profile.
+ :param 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.
+ :param 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)
+
+ :returns: 1 if the intent/direction are supported, -1 if they are not.
+ :exception PyCMSError:
+ """
+
+ 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) as v:
+ raise PyCMSError(v)
+
+
+def versions():
+ """
+ (pyCMS) Fetches 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
+
+ from PIL import ImageCms
+ print(__doc__)
+
+ for f in dir(ImageCms):
+ doc = None
+ try:
+ exec("doc = %s.__doc__" % (f))
+ if "pyCMS" in doc:
+ # so we don't get the __doc__ string for imported modules
+ print("=" * 80)
+ print("%s" % f)
+ print(doc)
+ except (AttributeError, TypeError):
+ pass
+
+# End of file