# 
 | 
# 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 
 |