Index: setup.py
===================================================================
--- setup.py (.../trunk/sK1) (revision 560)
+++ setup.py (.../branches/hackontest/sK1) (revision 560)
@@ -188,6 +188,14 @@
libraries=['freetype'],
extra_compile_args=["-Wall"])
+ pycms_src=src_path+'extentions/pycms/'
+ pycms_module = Extension('sk1.app.modules.pyCMSdll',
+ define_macros = [('MAJOR_VERSION', '0'),
+ ('MINOR_VERSION', '1')],
+ sources = [pycms_src+'pyCMSdll.c'],
+ libraries=['lcms'],
+ extra_compile_args=["-Wall"])
+
pax_src=src_path+'extentions/pax/'
pax_include_dirs=['/usr/include/cairo']
pax_include_dirs.extend(tcl_include_dirs)
@@ -294,7 +302,7 @@
ext_modules = [filter_module, type1mod_module, skread_module,
pstokenize_module, skmod_module, paxtkinter_module,
- pax_module, tkpng_module, ft2_module])
+ pax_module, tkpng_module, ft2_module, pycms_module])
Index: src/app/plugins/Filters/sk1saver.py
===================================================================
--- src/app/plugins/Filters/sk1saver.py (.../trunk/sK1) (revision 560)
+++ src/app/plugins/Filters/sk1saver.py (.../branches/hackontest/sK1) (revision 560)
@@ -537,7 +537,7 @@
from streamfilter import Base64Encode
write('bm(%d)\n' % id(image))
file = Base64Encode(self.file)
- image.image.save(file, 'PPM')
+ image.orig_image.save(file, 'IM')
file.close()
write('-\n')
else:
Index: src/app/managers/colormanager.py
===================================================================
--- src/app/managers/colormanager.py (.../trunk/sK1) (revision 560)
+++ src/app/managers/colormanager.py (.../branches/hackontest/sK1) (revision 560)
@@ -19,6 +19,8 @@
import sys
print "Cannot find Python binding for LittleCMS!"
sys.exit(1)
+
+import pyCMS
class ColorManager:
rgb_monitor=None
@@ -30,6 +32,7 @@
hCMYK=None
hMONITOR=None
colors_pool=[]
+ image_pool=[]
def __init__(self):
self.refresh_profiles()
@@ -37,13 +40,23 @@
def add_to_pool(self,color):
self.colors_pool.append(color)
+ def add_to_image_pool(self,image):
+ self.image_pool.append(image)
+
def remove_from_pool(self,color):
self.colors_pool.remove(color)
+ def remove_from_image_pool(self,image):
+ self.image_pool.remove(image)
+
def update(self):
for color in self.colors_pool:
color.update()
+
+ for image in self.image_pool:
+ image.update()
+
def refresh_profiles(self):
if app.config.preferences.user_rgb_profile and os.path.isfile(app.config.preferences.user_rgb_profile):
rgb_file=app.config.user_rgb_profile
@@ -160,7 +173,15 @@
cmsCloseProfile(self.hRGB)
cmsCloseProfile(self.hMONITOR)
+ def ImageRGBtoCMYK(self, image):
+ rgb_profile=os.path.join(app.config.sk_icc,app.config.preferences.default_rgb_profile)
+ cmyk_profile=os.path.join(app.config.sk_icc,app.config.preferences.default_cmyk_profile)
+ return pyCMS.profileToProfile(image, rgb_profile, cmyk_profile, outputMode = "CMYK")
+ def ImageCMYKtoRGB(self, image):
+ rgb_profile=os.path.join(app.config.sk_icc,app.config.preferences.default_rgb_profile)
+ cmyk_profile=os.path.join(app.config.sk_icc,app.config.preferences.default_cmyk_profile)
+ return pyCMS.profileToProfile(image, cmyk_profile, rgb_profile, outputMode = "RGB")
@@ -169,5 +190,4 @@
-
\ No newline at end of file
Index: src/app/managers/pyCMS.py
===================================================================
--- src/app/managers/pyCMS.py (.../trunk/sK1) (revision 0)
+++ src/app/managers/pyCMS.py (.../branches/hackontest/sK1) (revision 560)
@@ -0,0 +1,825 @@
+"""
+pyCMS
+
+ a Python / PIL interface to the littleCMS ICC Color Management System
+ Copyright (C) 2002-2003 Kevin Cazabon
+
[email protected]
+
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)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ 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.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
+#######################################################################
+VERSION = "0.0.2 alpha"
+
+
+#######################################################################
+# imports
+#######################################################################
+import pyCMSdll
+import os
+import Image
+
+#######################################################################
+# constants
+#######################################################################
+TRUE = 1
+FALSE = None
+
+INTENT_PERCEPTUAL = 0
+INTENT_RELATIVE_COLORIMETRIC = 1
+INTENT_SATURATION = 2
+INTENT_ABSOLUTE_COLORIMETRIC = 3
+
+DIRECTION_INPUT = 0
+DIRECTION_OUTPUT = 1
+DIRECTION_PROOF = 2
+
+#######################################################################
+# classes
+#######################################################################
+# classes are used for PyCMSTransform and PyCMSProfile so that data
+# such as input and output mode can follow the object after creation,
+# and be easily retrieved when needed.
+
+class PyCMSError(Exception):
+ pass
+
+class PyCMSTransform:
+ def __init__(self, transform = None, inputMode = None, outputMode = None):
+ self.transform = transform
+ self.inputMode = inputMode
+ self.outputMode = outputMode
+
+class PyCMSProfile:
+ def __init__(self, profile = None):
+ self.profile = profile
+
+
+#######################################################################
+# functions
+#######################################################################
+def versions ():
+ """
+ pyCMS.versions()
+
+ Returns a tuple of (pyCMSVersion, littleCMSVersion, pythonVersion,
+ PILVersion).
+
+ However, don't trust these values 100%, because they're currently
+ configured manually in pyCMSdll.c before building the DLL.
+ """
+
+ return pyCMSdll.versions()
+
+def about ():
+ """
+ pyCMS.about()
+
+ Returns a string containing information about pyCMSdll.dll, including
+ copyright and license information.
+ """
+
+ return pyCMSdll.about()
+
+def copyright ():
+ """
+ pyCMS.copyright()
+
+ Returns a string containing information about pyCMSdll.dll, including
+ copyright and license information.
+ """
+
+ return pyCMSdll.copyright()
+
+def profileToProfile (im, inputProfile, outputProfile, renderingIntent = INTENT_PERCEPTUAL, outputMode = None, inPlace = FALSE):
+ """
+ pyCMS.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
+ outputProfile = string, as a valid filename path to the ICC output
+ profile you wish to use for this image
+ renderingIntent = integer (0-3) specifying the rendering intent you
+ wish to use for the transform
+ INTENT_PERCEPTUAL = 0 (DEFAULT) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.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.
+
+ 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 not os.path.isfile(inputProfile):
+ raise PyCMSError, "Invalid input profile path provided: %s" %inputProfile
+ if not os.path.isfile(outputProfile):
+ raise PyCMSError, "Invalid output profile path provided: %s" %outputProfile
+
+ if outputMode == 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 inPlace == TRUE and im.mode != outputMode:
+ raise PyCMSError, "Cannot transform image in place, im.mode and output mode are different (%s vs. %s)" %(im.mode, outputMode)
+
+ if inPlace == TRUE:
+ imOut = im
+ else:
+ imOut = Image.new(outputMode, im.size)
+
+ im.load() #make sure it's loaded, or it may not have a .im attribute!
+
+ result = pyCMSdll.profileToProfile(im.im.id, imOut.im.id, inputProfile, outputProfile, renderingIntent)
+
+ if result == 0:
+ if inPlace == TRUE:
+ return None
+ else:
+ return imOut
+
+ elif result == -1:
+ raise PyCMSError, "Error occurred in pyCMSdll.profileToProfile()"
+
+ else:
+ raise PyCMSError, result
+
+def getOpenProfile (profileFilename):
+ """
+ pyCMS.getOpenProfile(profileFilename)
+
+ Returns a PyCMSProfile class object.
+
+ profileFilename = string, as a valid filename path to the ICC profile
+ you wish to open
+
+ The PyCMSProfile object can be passed back into pyCMS for use in creating
+ transforms and such (as in pyCMS.buildTransformFromOpenProfiles()).
+
+ If profileFilename is not a vaild filename for an ICC profile, a
+ PyCMSError will be raised.
+
+ """
+ if not os.path.isfile(profileFilename):
+ raise PyCMSError, "Invalid profile path provided: %s" %profileFilename
+
+ result = pyCMSdll.getOpenProfile (profileFilename)
+
+ try:
+ if type(result) == type("string"):
+ raise PyCMSError, result
+ except TypeError:
+ pass
+
+ return PyCMSProfile(result)
+
+def buildTransform (inputProfile, outputProfile, inMode, outMode, renderingIntent = INTENT_PERCEPTUAL):
+ """
+ pyCMS.buildTransform(inputProfile, outputProfile, inMode, outMode,
+ [renderingIntent])
+
+ Returns a PyCMSTransform class object.
+
+ inputProfile = string, as a valid filename path to the ICC input
+ profile you wish to use for this transform
+ outputProfile = string, as a valid filename path to the ICC output
+ profile you wish to use for this transform
+ 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) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.INTENT_ABSOLUTE_COLORIMETRIC)
+ see the pyCMS documentation for details on rendering intents and
+ what they do.
+
+ 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
+ pyCMS.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
+ pyCMS.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 not os.path.isfile(inputProfile):
+ raise PyCMSError, "Invalid input profile path provided: %s" %inputProfile
+ if not os.path.isfile(outputProfile):
+ raise PyCMSError, "Invalid output profile path provided: %s" %outputProfile
+
+ if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3):
+ raise PyCMSError, "renderingIntent must be an integer between 0 and 3"
+
+ result = pyCMSdll.buildTransform (inputProfile, outputProfile, inMode, outMode, renderingIntent)
+
+ try:
+ if type(result) == type("string"):
+ raise PyCMSError, result
+ except TypeError:
+ pass
+
+ return PyCMSTransform(result, inMode, outMode)
+
+def buildProofTransform (inputProfile, outputProfile, displayProfile, inMode, outMode, renderingIntent = INTENT_PERCEPTUAL, displayRenderingIntent = INTENT_PERCEPTUAL):
+ """
+ pyCMS.buildProofTransform(inputProfile, outputProfile, displayProfile,
+ inMode, outMode, [renderingIntent], [displayRenderingIntent])
+
+ Returns a PyCMSTransform class object.
+
+ inputProfile = string, as a valid filename path to the ICC input
+ profile you wish to use for this transform
+ outputProfile = string, as a valid filename path to the ICC output
+ profile you wish to use for this transform
+ displayProfile = string, as a valid filename path to the ICC display
+ (monitor, usually) profile you wish to use for this transform
+ 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->output (simulated) transform
+ INTENT_PERCEPTUAL = 0 (DEFAULT) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.INTENT_ABSOLUTE_COLORIMETRIC)
+ see the pyCMS documentation for details on rendering intents and
+ what they do.
+ displayRenderingIntent = integer (0-3) specifying the rendering intent
+ you wish to use for (input/output simulation)->display transform
+ INTENT_PERCEPTUAL = 0 (DEFAULT) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.INTENT_ABSOLUTE_COLORIMETRIC)
+ see the pyCMS documentation for details on rendering intents and
+ what they do.
+
+ If the input, output, or display 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 displayProfile, but tries to simulate the result that would be
+ obtained on the outputProfile device using renderingIntent and
+ displayRenderingIntent 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
+ pyCMS.buildTransform().
+
+ Proof profiling is generally used when using a "proof" device to get a
+ good idea of what the final printed/displayed image would look like on
+ the outputProfile device when it's quicker and easier to use the
+ display device for judging color. Generally, this means that
+ displayDevice is a monitor, or a dye-sub printer (etc.), and the output
+ 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 limiting the color gamut on the
+ display device to the gamut availabile on the output device. However,
+ when the final output device has a much wider gamut than the display
+ device, you may obtain marginal results.
+
+ """
+ if not os.path.isfile(inputProfile):
+ raise PyCMSError, "Invalid input profile path provided: %s" %inputProfile
+ if not os.path.isfile(outputProfile):
+ raise PyCMSError, "Invalid output profile path provided: %s" %outputProfile
+ if not os.path.isfile(displayProfile):
+ raise PyCMSError, "Invalid display profile path provided: %s" %displayProfile
+
+ if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3):
+ raise PyCMSError, "renderingIntent must be an integer between 0 and 3"
+
+ result = pyCMSdll.buildProofTransform (inputProfile, outputProfile, displayProfile, inMode, outMode, renderingIntent, displayRenderingIntent)
+
+ try:
+ if type(result) == type("string"):
+ raise PyCMSError, result
+ except TypeError:
+ pass
+
+ return PyCMSTransform(result, inMode, outMode)
+
+def buildTransformFromOpenProfiles (inputProfile, outputProfile, inMode, outMode, renderingIntent = INTENT_PERCEPTUAL):
+ """
+ pyCMS.buildTransformFromOpenProfiles(inputProfile, outputProfile,
+ inMode, outMode, [renderingIntent])
+
+ Returns a PyCMSTransform class object
+
+ inputProfile = a valid PyCMSProfile class object
+ outputProfile = a valid PyCMSProfile class 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) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.INTENT_ABSOLUTE_COLORIMETRIC)
+ see the pyCMS documentation for details on rendering intents and
+ what they do.
+
+ This function operates exactly the same as pyCMS.buildTransform()
+ except that the inputProfile and outputProfile arguments must be valid
+ PyCMSProfile objects rather than filenames. Use this function to
+ create pre-calculated transforms from open PyCMSProfiles (such as
+ profiles created on-the-fly using pyCMS.createProfile(), or [in the
+ future] profiles extracted from image files.
+
+ """
+
+ if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3):
+ raise PyCMSError, "renderingIntent must be an integer between 0 and 3"
+
+ result = pyCMSdll.buildTransformFromOpenProfiles (inputProfile.profile, outputProfile.profile, inMode, outMode, renderingIntent)
+
+ try:
+ if type(result) == type("string"):
+ raise PyCMSError, result
+ except TypeError:
+ pass
+
+ return PyCMSTransform(result, inMode, outMode)
+
+def buildProofTransformFromOpenProfiles (inputProfile, outputProfile, displayProfile, inMode, outMode, renderingIntent = INTENT_PERCEPTUAL, displayRenderingIntent = INTENT_PERCEPTUAL):
+ """
+ pyCMS.buildProofTransformFromOpenProfiles(inputProfile, outputProfile,
+ displayProfile, inMode, outMode, [renderingIntent],
+ [displayRenderingIntent])
+
+ Returns a PyCMSTransform class object
+
+ inputProfile = a valid PyCMSProfile class object
+ outputProfile = a valid PyCMSProfile class object
+ displayProfile = a valid PyCMSProfile class 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) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.INTENT_ABSOLUTE_COLORIMETRIC)
+ see the pyCMS documentation for details on rendering intents and
+ what they do.
+ displayRenderingIntent = integer (0-3) specifying the rendering intent you
+ wish to use for the transform
+ INTENT_PERCEPTUAL = 0 (DEFAULT) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.INTENT_ABSOLUTE_COLORIMETRIC)
+ see the pyCMS documentation for details on rendering intents and
+ what they do.
+ This function operates exactly the same as pyCMS.buildProofTransform()
+ except that the profile arguments must be valid
+ PyCMSProfile objects rather than filenames. Use this function to
+ create pre-calculated proof transforms from open PyCMSProfiles (such as
+ profiles created on-the-fly using pyCMS.createProfile(), or [in the
+ future] profiles extracted from image files.
+
+ """
+
+ if type(renderingIntent) != type(1) or not (0 <= renderingIntent <=3) or type(displayRenderingIntent) != type(1) or not (0 <= displayRenderingIntent <=3):
+ raise PyCMSError, "renderingIntent must be an integer between 0 and 3"
+
+ result = pyCMSdll.buildProofTransformFromOpenProfiles (inputProfile.profile, outputProfile.profile, displayProfile.profile, inMode, outMode, renderingIntent, displayRenderingIntent)
+
+ try:
+ if type(result) == type("string"):
+ raise PyCMSError, result
+
+ except TypeError:
+ pass
+
+ return PyCMSTransform(result, inMode, outMode)
+
+def applyTransform (im, transform, inPlace = FALSE):
+ """
+ pyCMS.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 PyCMSTransform 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
+ pyCMS.buildTransform() or pyCMS.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.
+
+ """
+ if im.mode != transform.inputMode:
+ raise PyCMSError, "Image mode does not match profile input mode (%s vs %s)" %(im.mode, transform.inMode)
+
+ if inPlace == TRUE:
+ if transform.inputMode != transform.outputMode:
+ raise PyCMSError, "Cannot transform image in place, input mode and output mode are different (%s vs. %s)" %(transform.inMode, transform.outMode)
+ imOut = im
+ else:
+ imOut = Image.new(transform.outputMode, im.size)
+
+ im.load() #make sure it's loaded, or it may not have an .im attribute!
+
+ result = pyCMSdll.applyTransform (im.im.id, imOut.im.id, transform.transform)
+
+ if result == 0:
+ if inPlace == TRUE:
+ return None
+ else:
+ return imOut
+
+ elif result == -1:
+ raise PyCMSError, "Error occurred in pyCMSdll.applyTransform()"
+
+ else:
+ raise PyCMSError, result
+
+def createProfile (colorSpace, colorTemp = -1):
+ """
+ pyCMS.createProfile(colorSpace, [colorTemp])
+
+ Returns a PyCMSProfile 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 PyCMSProfile object that can be passed to
+ pyCMS.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
+
+ result = pyCMSdll.createProfile (colorSpace, colorTemp)
+
+ try:
+ if type(result) == type("string"):
+ raise PyCMSError, result
+
+ else:
+ return PyCMSProfile(result)
+ except TypeError:
+ # you can't use type() on a PyCObject... argh!
+ return PyCMSProfile(result)
+
+def getProfileName (profile):
+ """
+ pyCMS.getProfileName(profile)
+
+ Returns a string containing the internal name of the profile as stored
+ in an ICC tag.
+
+ profile = EITHER a valid PyCMSProfile object, OR a string of the
+ filename of an ICC profile.
+
+ If profile isn't a valid PyCMSProfile 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:
+ if type(profile) != type("string"):
+ profile = profile.profile
+ elif (not os.path.isfile(profile)):
+ raise PyCMSError, "Invalid profile path provided: %s" %profile
+
+ except TypeError:
+ # you can't use type() on a PyCObject... argh!
+ profile = profile.profile
+
+ result = pyCMSdll.getProfileName(profile)
+
+ if len(result) > 7 and result[:7] == "ERROR: ":
+ raise PyCMSError, result
+
+ else:
+ return result
+
+def getProfileInfo (profile):
+ """
+ pyCMS.getProfileInfo(profile)
+
+ Returns a string containing the internal profile information stored in
+ an ICC tag.
+
+ profile = EITHER a valid PyCMSProfile object, OR a string of the
+ filename of an ICC profile.
+
+ If profile isn't a valid PyCMSProfile 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 type(profile) != type("string"):
+ profile = profile.profile
+ elif (not os.path.isfile(profile)):
+ raise PyCMSError, "Invalid profile path provided: %s" %profile
+
+ except TypeError:
+ # you can't use type() on a PyCObject... argh!
+ profile = profile.profile
+
+ result = pyCMSdll.getProfileInfo(profile)
+
+ if len(result) > 7 and result[:7] == "ERROR: ":
+ raise PyCMSError, result
+
+ else:
+ return result
+
+def getDefaultIntent (profile):
+ """
+ pyCMS.getDefaultIntent(profile)
+
+ Returns integer 0-3 specifying the default rendering intent for this
+ profile.
+ INTENT_PERCEPTUAL = 0 (DEFAULT) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.INTENT_ABSOLUTE_COLORIMETRIC)
+ see the pyCMS documentation for details on rendering intents and
+ what they do.
+
+ profile = EITHER a valid PyCMSProfile object, OR a string of the
+ filename of an ICC profile.
+
+ If profile isn't a valid PyCMSProfile 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
+ pyCMS.isIntentSupported() to verify it will work first.
+ """
+ try:
+ if type(profile) != type("string"):
+ profile = profile.profile
+ elif (not os.path.isfile(profile)):
+ raise PyCMSError, "Invalid profile path provided: %s" %profile
+
+ except TypeError:
+ # you can't use type() on a PyCObject... argh!
+ profile = profile.profile
+
+ result = pyCMSdll.getDefaultIntent(profile)
+
+ try:
+ if type(result) == type("string"):
+ raise PyCMSError, result
+ else:
+ return result
+
+ except TypeError:
+ # you can't use type() on a PyCObject... argh!
+ return result
+
+def isIntentSupported (profile, intent, direction):
+ """
+ pyCMS.isIntentSupported(profile, intent, direction)
+
+ Returns 1 if the intent/direction are supported, -1 if they are not.
+
+ profile = EITHER a valid PyCMSProfile 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) (pyCMS.INTENT_PERCEPTUAL)
+ INTENT_RELATIVE_COLORIMETRIC =1 (pyCMS.INTENT_RELATIVE_COLORIMETRIC)
+ INTENT_SATURATION = 2 (pyCMS.INTENT_SATURATION)
+ INTENT_ABSOLUTE_COLORIMETRIC =3 (pyCMS.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 display/proof
+ INPUT = 0 (or use pyCMS.DIRECTION_INPUT)
+ OUTPUT = 1 (or use pyCMS.DIRECTION_OUTPUT)
+ PROOF (or display) = 2 (or use pyCMS.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/display 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 type(profile) != type("string"):
+ profile = profile.profile
+ elif (not os.path.isfile(profile)):
+ raise PyCMSError, "Invalid profile path provided: %s" %profile
+
+ except TypeError:
+ # you can't use type() on a PyCObject... argh!
+ profile = profile.profile
+
+ result = pyCMSdll.isIntentSupported(profile, intent, direction)
+
+ try:
+ if type(result) == type("string"):
+ raise PyCMSError, result
+
+ else:
+ return result
+
+ except TypeError:
+ # you can't use type() on a PyCObject... argh!
+ return result
+
+if __name__ == "__main__":
+ # create a cheap manual from the __doc__ strings for the functions above
+
+ import pyCMS
+ import string
+ print __doc__
+
+ for f in dir(pyCMS):
+ print "="*80
+ print "%s" %f
+
+ try:
+ exec ("doc = pyCMS.%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
+
\ No newline at end of file
Index: src/app/Graphics/document.py
===================================================================
--- src/app/Graphics/document.py (.../trunk/sK1) (revision 560)
+++ src/app/Graphics/document.py (.../branches/hackontest/sK1) (revision 560)
@@ -1973,18 +1973,19 @@
return self.selection.GetObjectMethod(aclass, method)
def CurrentObjectCompatible(self, aclass):
- obj = self.CurrentObject()
+ obj = self.CurrentObject()
if obj is not None:
if aclass.is_Editor:
- return isinstance(obj, aclass.EditedClass)
+ return obj.__class__.__name__== aclass.EditedClass.__name__
else:
- return isinstance(obj, aclass)
+ return obj.__class__.__name__== aclass.__name__
return 0
# XXX the following methods for blend groups, path text, clones and
# bezier objects should perhaps be implemented in their respective
# modules (and then somehow grafted onto the document class?)
+
def CanBlend(self):
info = self.selection.GetInfo()
if len(info) == 2:
@@ -2210,8 +2211,79 @@
self.abort_transaction()
finally:
self.end_transaction()
+ #
+ # IMAGES MANAGMENT
+ #
+
+############
+ def CanBeRGB(self):
+ from image import RGB_IMAGE, RGBA_IMAGE
+ obj = self.CurrentObject()
+ if obj:
+ if obj.is_Image:
+ if obj.data.image_mode==RGB_IMAGE or obj.data.image_mode==RGBA_IMAGE:
+ return 0
+ else:
+ return 1
+ return 0
+ def CanBeCMYK(self):
+ from image import CMYK_IMAGE
+ obj = self.CurrentObject()
+ if obj:
+ if obj.is_Image and not obj.data.image_mode==CMYK_IMAGE:
+ return 1
+ return 0
+ def CanBeGrayscale(self):
+ from image import GRAYSCALE_IMAGE
+ obj = self.CurrentObject()
+ if obj:
+ if obj.is_Image and not obj.data.image_mode==GRAYSCALE_IMAGE:
+ return 1
+ return 0
+
+ def CanBeBW(self):
+ from image import BW_IMAGE
+ obj = self.CurrentObject()
+ if obj:
+ if obj.is_Image and not obj.data.image_mode==BW_IMAGE:
+ return 1
+ return 0
+
+ def ConvertImage(self, mode):
+ obj = self.CurrentObject()
+ self.CallObjectMethod(obj.__class__, _("Convert Image"), 'Convert', mode)
+# obj.Convert(mode)
+ self.SelectNone()
+ self.SelectObject(obj)
+
+ def CanEmbed(self):
+ obj = self.CurrentObject()
+ if obj:
+ if obj.is_Image and obj.CanEmbed():
+ return obj.CanEmbed()
+ return 0
+
+ def Embed(self):
+ obj = self.CurrentObject()
+ obj.Embed()
+ self.SelectNone()
+ self.SelectObject(obj)
+
+ def CanInvert(self):
+ obj = self.CurrentObject()
+ if obj:
+ if obj.is_Image and obj.IsEmbedded():
+ return 1
+ return 0
+
+ def Invert(self):
+ obj = self.CurrentObject()
+ self.CallObjectMethod(obj.__class__, _("Invert Image"), 'InvertImage')
+ app.mw.canvas.ForceRedraw()
+
+
#
# PAGES MANAGMENT
#
Index: src/app/Graphics/color.py
===================================================================
--- src/app/Graphics/color.py (.../trunk/sK1) (revision 560)
+++ src/app/Graphics/color.py (.../branches/hackontest/sK1) (revision 560)
@@ -98,7 +98,6 @@
def __del__(self):
if colormanager is not None:
colormanager.remove_from_pool(self)
- print "REMOVED"
def getScreenColor(self):
pass
Index: src/app/Graphics/image.py
===================================================================
--- src/app/Graphics/image.py (.../trunk/sK1) (revision 560)
+++ src/app/Graphics/image.py (.../branches/hackontest/sK1) (revision 560)
@@ -21,41 +21,85 @@
# memory.
#
-import os
+import os, app
from types import StringType
import PIL.Image, PIL.ImageChops
-from app import _, RegisterCommands
+from app import _, RegisterCommands, colormanager
from app.UI.command import AddCmd
from external import ExternalData, get_cached, ExternalGraphics
+RGB_IMAGE=_('RGB')
+RGBA_IMAGE=_('RGBA')
+GRAYSCALE_IMAGE=_('Greyscale')
+CMYK_IMAGE=_('CMYK')
+BW_IMAGE=_('Monochrome')
+UNSUPPORTED=_('UNSUPPORTED')
+
class ImageData(ExternalData):
attributes = {'mode':0, 'size':0, 'im':0, 'info':0}
+ cached =0
+
+ def __init__(self, image, filename = '', cache = 1):
+ self.orig_image=image.copy()
- def __init__(self, image, filename = '', cache = 1):
- # convert image to mode 'L' or 'RGB' if necessary
- if image.mode not in ('RGB', 'RGBA', 'L'):
- if image.mode == '1':
- mode = 'L'
- else:
- mode = 'RGB'
- image = image.convert(mode)
+ if image.mode=='1':
+ self.image_mode=BW_IMAGE
+ elif image.mode=='L':
+ self.image_mode=GRAYSCALE_IMAGE
+ elif image.mode=='RGB':
+ self.image_mode=RGB_IMAGE
+ elif image.mode=='RGBA':
+ self.image_mode=RGBA_IMAGE
+ elif image.mode=='CMYK':
+ self.image_mode=CMYK_IMAGE
+ colormanager.add_to_image_pool(self)
+ self.cached=1
else:
+ self.image_mode=UNSUPPORTED
+
+ if image.mode not in ('RGB', 'RGBA'):
+ if image.mode=='CMYK':
+ if app.config.preferences.use_cms:
+ self.image=colormanager.ImageCMYKtoRGB(image)
+ else:
+ self.image = image.convert('RGB')
+ else:
+ self.image = image.convert('RGB')
+ else:
image.load()
- self.image = image
+ self.image = image
+
+ if self.image_mode==UNSUPPORTED:
+ self.orig_image=self.image.copy()
+ self.image_mode=RGB_IMAGE
+
ExternalData.__init__(self, filename, cache)
+
+ def __del__(self):
+ if self.cached and colormanager is not None:
+ colormanager.remove_from_image_pool(self)
def __getattr__(self, attr):
if self.attributes.has_key(attr):
return getattr(self.image, attr)
raise AttributeError, attr
+
+ def update(self):
+ if app.config.preferences.use_cms:
+ if self.image_mode==CMYK_IMAGE:
+ self.image=colormanager.ImageCMYKtoRGB(self.orig_image)
+ else:
+ self.image = self.orig_image.convert('RGB')
+ else:
+ self.image = self.orig_image.convert('RGB')
def AsEmbedded(self):
if self.filename:
- return ImageData(self.image)
+ return ImageData(self.orig_image)
else:
return self
@@ -66,16 +110,23 @@
return self.size
def Image(self):
- return self.image
+ print 'Image provided'
+ return self.orig_image
def Convert(self, mode):
- if mode != self.image.mode:
- return ImageData(self.image.convert(mode))
+ if mode != self.orig_image.mode:
+ if app.config.preferences.use_cms:
+ if mode=='RGB'and self.orig_image.mode=='CMYK':
+ return ImageData(colormanager.ImageCMYKtoRGB(self.orig_image))
+ if mode=='CMYK'and self.orig_image.mode=='RGB':
+ return ImageData(colormanager.ImageRGBtoCMYK(self.orig_image))
+ else:
+ return ImageData(self.orig_image.convert(mode))
else:
return self
def Invert(self):
- return ImageData(PIL.ImageChops.invert(self.image))
+ return ImageData(PIL.ImageChops.invert(self.orig_image))
@@ -96,30 +147,25 @@
commands = ExternalGraphics.commands[:]
- def __init__(self, image = None, imagefile = '', trafo = None,
- duplicate = None):
+ def __init__(self, image = None, imagefile = '', trafo = None, duplicate = None):
if duplicate is None:
if not image:
if not imagefile:
raise ValueError, 'Image must be instantiated with'\
' either image or imagefile'
image = load_image(imagefile)
- ExternalGraphics.__init__(self, image, trafo,
- duplicate = duplicate)
+ ExternalGraphics.__init__(self, image, trafo, duplicate = duplicate)
+ self.Embed()
def DrawShape(self, device, rect = None, clip = 0):
device.DrawImage(self.data, self.trafo, clip)
def Info(self):
+ mode=self.data.image_mode
width, height = self.data.Size()
x, y = self.trafo.offset()
- if self.IsEmbedded():
- return _("Embedded Image %(width)d x %(height)d "
- "at (%(x)d, %(y)d)") % locals()
- else:
- filename = os.path.basename(self.data.Filename())
- return _("Linked Image `%(filename)s' %(width)d x %(height)d "
- "at (%(x)d, %(y)d)") % locals()
+ return _("Embedded %(mode)s image %(width)d x %(height)d "
+ "at (%(x)d, %(y)d)") % locals()
def SaveToFile(self, file):
file.Image(self.data, self.trafo)
@@ -132,20 +178,28 @@
def Embed(self):
return self.SetData(self.data.AsEmbedded())
- AddCmd(commands, 'EmbedImage', _("Embed Image"), Embed,
- sensitive_cb = 'CanEmbed')
+
+ def InvertImage(self):
+ return self.SetData(self.data.Invert())
+
+ def Convert(self, image_mode):
+ undo = (self.SetData, self.data)
+ if image_mode==RGB_IMAGE:
+ self.SetData(self.data.Convert('RGB'))
+ if image_mode==RGBA_IMAGE:
+ self.SetData(self.data.Convert('RGB'))
+ if image_mode==GRAYSCALE_IMAGE:
+ self.SetData(self.data.Convert('L'))
+ if image_mode==CMYK_IMAGE:
+ self.SetData(self.data.Convert('CMYK'))
+ if image_mode==BW_IMAGE:
+ self.SetData(self.data.Convert('1'))
+ return undo
def CallImageFunction(self, function, args = ()):
if type(args) != type(()):
args = (args,)
data = apply(getattr(self.data, function), args)
return self.SetData(data)
- AddCmd(commands, 'GrayscaleImage', _("Grayscale Image"),
- CallImageFunction, args = ('Convert', 'L'))
- AddCmd(commands, 'InvertImage', _("Invert Image"), CallImageFunction,
- args = 'Invert')
- context_commands = ('EmbedImage', 'GrayscaleImage', 'InvertImage')
-RegisterCommands(Image)
-
Index: src/app/UI/pluginpanels/find_replace_plugin.py
===================================================================
--- src/app/UI/pluginpanels/find_replace_plugin.py (.../trunk/sK1) (revision 0)
+++ src/app/UI/pluginpanels/find_replace_plugin.py (.../branches/hackontest/sK1) (revision 560)
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2008 by Darya Shumilina
+#
+# This library is covered by GNU Library General Public License.
+# For more info see COPYRIGHTS file in sK1 root directory.
+
+import re
+
+from ppanel import PluginPanel
+
+from app import _
+import app
+from app.Graphics import document, text
+
+from Ttk import LabelFrame, TFrame, TLabel, TCheckbutton, TButton
+from app.UI.ttk_ext import TEntryExt
+from Tkinter import RIGHT, BOTTOM, BOTH, TOP, X, E, W, Y, LEFT, StringVar, BooleanVar, DISABLED, NORMAL
+
+from app.UI.lengthvar import create_length_entry
+
+class FindReplacePanel(PluginPanel):
+ name='Find and Replace'
+ title = _("Find and Replace")
+
+ def init(self, master):
+ PluginPanel.init(self, master)
+ top = self.panel
+
+ top = TFrame(top, borderwidth=2, style='FlatFrame')
+ top.pack(side = TOP, expand = 1, fill = X)
+
+ button_frame = TFrame(top, borderwidth=2, style='FlatFrame')
+ button_frame.pack(side = BOTTOM, fill = BOTH, expand = 1)
+
+ button=TButton(button_frame,text=_('Apply'), command=self.replace)
+ button.pack(side = TOP)
+
+ #----------------------------------------------------------
+ main_frame = TFrame(top, style='FlatFrame', borderwidth=3)
+ main_frame.pack(side = TOP, fill=X)
+
+ self.find_var = StringVar(top);
+ self.find_var.set('')
+ findField = TEntryExt(main_frame, textvariable=self.find_var)
+ findField.pack(side = RIGHT)
+
+ label = TLabel(main_frame, style='FlatLabel', text = _("Find: "))
+ label.pack(side = RIGHT, anchor = E)
+ #---------------------------------------------------------
+ main_frame = TFrame(top, style='FlatFrame', borderwidth=3)
+ main_frame.pack(side = TOP, fill=X)
+
+
+ self.replace_var = StringVar(top);
+ self.replace_var.set('')
+ replaceField = TEntryExt(main_frame, textvariable=self.replace_var)
+ replaceField.pack(side = RIGHT)
+
+ label = TLabel(main_frame, style='FlatLabel', text = _("Replace to: "))
+ label.pack(side = RIGHT, anchor = E)
+
+ main_frame = TFrame(top, style='FlatFrame', borderwidth=3)
+ main_frame.pack(side = TOP)
+ #---------------------------------------------------------
+ parametersFrameLabel=LabelFrame(top, text=' Parameters ', borderwidth=2, relief='groove', pady=4, padx=4)
+
+ parametersFrameLabel.pack(side = TOP, fill=X, pady=4, padx=2)
+
+ parametersFrame = TFrame(parametersFrameLabel, style='FlatFrame')
+
+ self.var_case_sensitive = BooleanVar(top)
+ self.case_sensitive_check = TCheckbutton(parametersFrame, text = _("Case sensitive"), variable = self.var_case_sensitive)
+ self.case_sensitive_check.pack(side = TOP, anchor=W, padx=5)
+
+ self.var_whole_word = BooleanVar(top)
+ self.whole_word_check = TCheckbutton(parametersFrame, text = _("Whole word"), variable = self.var_whole_word)
+ self.whole_word_check.pack(side = TOP, anchor=W, padx=5)
+
+ self.var_regexp = BooleanVar(top)
+ self.regexpCheck = TCheckbutton(parametersFrame, text = _("RegExp search"), variable = self.var_regexp, command=self.disable_enable_action)
+ self.regexpCheck.pack(side = TOP, anchor=W, padx=5)
+
+ parametersFrame.pack(side=TOP, fill=X, pady=2)
+################################################################
+ def replace_text(self,objects, toReplace, replaceTo):
+ for object in objects:
+ if object.is_Text:
+
+ if self.var_regexp.get():
+ p=re.compile(toReplace)
+ text=p.sub(replaceTo, object.text)
+ app.mw.document.SelectObject(object)
+ app.mw.document.CallObjectMethod(object.__class__,_('Text Replace'),'SetText',text)
+ continue
+
+ if self.var_whole_word.get():
+ if not self.var_case_sensitive.get():
+ if object.text.lower()==toReplace.lower():
+ text=replaceTo
+ app.mw.document.SelectObject(object)
+ app.mw.document.CallObjectMethod(object.__class__,_('Text Replace'),'SetText',text)
+ else:
+ if object.text==toReplace:
+ text=replaceTo
+ app.mw.document.SelectObject(object)
+ app.mw.document.CallObjectMethod(object.__class__,_('Text Replace'),'SetText',text)
+
+ else:
+ if object.text.lower().find(toReplace.lower(), 0, len(object.text)) != -1:
+ if not self.var_case_sensitive.get():
+ text=object.text.lower().replace(toReplace.lower(), replaceTo)
+ else:
+ text=object.text.replace(toReplace, replaceTo)
+ app.mw.document.SelectObject(object)
+ app.mw.document.CallObjectMethod(object.__class__,_('Text Replace'),'SetText',text)
+
+ if object.is_Group:
+ self.replace_text(object.objects)
+################################################################
+ def replace(self):
+ textObjects=[]
+ textToReplace=self.find_var.get().decode('utf-8')
+ replaceTo=self.replace_var.get().decode('utf-8')
+
+ for layer in app.mw.document.layers:
+ self.replace_text(layer.objects, textToReplace, replaceTo)
+ app.mw.canvas.ForceRedraw()
+################################################################
+ def disable_enable_action(self):
+ if self.case_sensitive_check['state'] != DISABLED and self.whole_word_check['state'] != DISABLED:
+ self.case_sensitive_check['state'] = DISABLED
+ self.whole_word_check['state'] = DISABLED
+ else:
+ self.case_sensitive_check['state'] = NORMAL
+ self.whole_word_check['state'] = NORMAL
+################################################################
+ def whole_word_action(self):
+ pass
+################################################################
+
+instance=FindReplacePanel()
+app.extentions_plugins.append(instance)
Index: src/app/UI/pluginpanels/__init__.py
===================================================================
--- src/app/UI/pluginpanels/__init__.py (.../trunk/sK1) (revision 560)
+++ src/app/UI/pluginpanels/__init__.py (.../branches/hackontest/sK1) (revision 560)
@@ -1,3 +1,4 @@
import align_plugin
import grid_plugin, guidelines_plugin
-import resize_plugin, move_plugin, rotate_plugin
\ No newline at end of file
+import resize_plugin, move_plugin, rotate_plugin
+import find_replace_plugin
\ No newline at end of file
Index: src/app/UI/pluginpanels/ppanel.py
===================================================================
--- src/app/UI/pluginpanels/ppanel.py (.../trunk/sK1) (revision 560)
+++ src/app/UI/pluginpanels/ppanel.py (.../branches/hackontest/sK1) (revision 560)
@@ -87,26 +87,11 @@
return self.document.HasSelection()
def subscribe_receivers(self):
- for info in self.receivers:
- apply(self.document.Subscribe,
- (info[0], getattr(self, info[1])) + info[2:])
+ pass
def unsubscribe_receivers(self):
- for info in self.receivers:
- apply(self.document.Unsubscribe,
- (info[0], getattr(self, info[1])) + info[2:])
-
+ pass
- def subscribe_receivers(self):
- for info in self.receivers:
- apply(self.document.Subscribe,
- (info[0], getattr(self, info[1])) + info[2:])
-
- def unsubscribe_receivers(self):
- for info in self.receivers:
- apply(self.document.Unsubscribe,
- (info[0], getattr(self, info[1])) + info[2:])
-
def SetDocument(self, doc):
if self.document:
self.unsubscribe_receivers()
Index: src/app/UI/canvas.py
===================================================================
--- src/app/UI/canvas.py (.../trunk/sK1) (revision 560)
+++ src/app/UI/canvas.py (.../branches/hackontest/sK1) (revision 560)
@@ -304,8 +304,8 @@
if self.context_menu_items[-1] != None:
# insert a separator if necessary
self.context_menu_items.append(None)
- self.context_menu_items = self.context_menu_items \
- + list(aclass.context_commands)
+# self.context_menu_items = self.context_menu_items \
+# + list(aclass.context_commands)
self.commands = cmds
self.object_keymap = None
@@ -720,7 +720,6 @@
x, y, button, state)
if self.context_commands is None:
self.build_context_commands()
-
items = []
last = None
for cmd in self.context_commands:
Index: src/app/UI/command.py
===================================================================
--- src/app/UI/command.py (.../trunk/sK1) (revision 560)
+++ src/app/UI/command.py (.../branches/hackontest/sK1) (revision 560)
@@ -72,7 +72,6 @@
return changed
def get_sensitive(self):
- #print 'get_sensitive', self
if self.sensitive_cb:
method = self.get_method(self.sensitive_cb)
if method:
Index: src/app/UI/context/image_panel.py
===================================================================
--- src/app/UI/context/image_panel.py (.../trunk/sK1) (revision 0)
+++ src/app/UI/context/image_panel.py (.../branches/hackontest/sK1) (revision 560)
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2008 by Igor E. Novikov
+#
+# This library is covered by GNU Library General Public License.
+# For more info see COPYRIGHTS file in sK1 root directory.
+
+
+from app.UI.tkext import ToolbarButton
+from app.conf.const import CHANGED
+from Tkinter import LEFT, DoubleVar, StringVar, RIGHT
+from subpanel import CtxSubPanel
+from app import _, config, PolyBezier, CreatePath, Point
+import tooltips
+from app.UI.lengthvar import LengthVar
+from app.conf.const import SELECTION
+
+class ImagePanel(CtxSubPanel):
+
+ name='ImagePanel'
+
+ def __init__(self, parent):
+ CtxSubPanel.__init__(self, parent)
+ self.builded=0
+ self.doc.Subscribe(SELECTION, self.update)
+
+ def build_dlg(self):
+ if not self.builded:
+ cmds = self.mw.commands
+
+ b = ToolbarButton(self.panel, command=cmds.Convert_to_CMYK, style='Toolbutton', image='context_image_cmyk')
+ tooltips.AddDescription(b, _('Convert to CMYK'))
+ b.pack(side = LEFT)
+
+ b = ToolbarButton(self.panel, command=cmds.Convert_to_RGB, style='Toolbutton', image='context_image_rgb')
+ tooltips.AddDescription(b, _('Convert to RGB'))
+ b.pack(side = LEFT)
+
+ b = ToolbarButton(self.panel, command=cmds.Convert_to_Grayscale, style='Toolbutton', image='context_image_gray')
+ tooltips.AddDescription(b, _('Convert to Grayscale'))
+ b.pack(side = LEFT)
+
+ b = ToolbarButton(self.panel, command=cmds.Convert_to_BW, style='Toolbutton', image='context_image_bw')
+ tooltips.AddDescription(b, _('Convert to B&W'))
+ b.pack(side = LEFT)
+
+ self.builded=1
+
+ def update(self,*arg):
+ if not self.mw.canvas is None:
+ self.build_dlg()
+
+
Index: src/app/UI/context/ctxPanel.py
===================================================================
--- src/app/UI/context/ctxPanel.py (.../trunk/sK1) (revision 560)
+++ src/app/UI/context/ctxPanel.py (.../branches/hackontest/sK1) (revision 560)
@@ -16,6 +16,7 @@
from unit_panel import UnitPanel
from jump_panel import JumpPanel
from page_panel import PagePanel
+from image_panel import ImagePanel
from group_panel import GroupPanel, CombinePanel, ToCurvePanel
from text_prop_panel import TextPropPanel
from textalign_panel import TextAlignPanel
@@ -40,6 +41,7 @@
forSimpleText=['TextPropPanel','FontPanel','TextAlignPanel','ToCurvePanel']
forGroup=['ResizePanel','UnitPanel','FlipPanel', 'RotatePanel', 'GroupPanel', 'CombinePanel', 'ToCurvePanel']
forNodes=['ResizePanel','UnitPanel', 'CombinePanel','NodeEditPanel']
+forImage=['ResizePanel','UnitPanel','FlipPanel', 'RotatePanel', 'ImagePanel']
class ContexPanel(Publisher):
@@ -100,6 +102,8 @@
self.changeContent(forGroup)
elif obj_type==SIMPLE_TEXT:
self.changeContent(forSimpleText)
+ elif obj_type==IMAGE:
+ self.changeContent(forImage)
else:
self.changeContent(forObject)
else:
@@ -109,6 +113,8 @@
self.changeContent(forSimpleText)
elif obj_type==BEZIER:
self.changeContent(forNodes)
+ elif obj_type==IMAGE:
+ self.changeContent(forImage)
else:
self.changeContent(forObject)
else:
@@ -134,4 +140,4 @@
PanelList=[PagePanel, ResizePanel, GuidesPanel, RotatePanel, JumpPanel,
TextPropPanel, TextAlignPanel, FlipPanel, UnitPanel, GroupPanel,
- FontPanel,CombinePanel, ToCurvePanel, NodeEditPanel]
\ No newline at end of file
+ FontPanel,CombinePanel, ToCurvePanel, NodeEditPanel, ImagePanel]
\ No newline at end of file
Index: src/app/UI/tkext.py
===================================================================
--- src/app/UI/tkext.py (.../trunk/sK1) (revision 560)
+++ src/app/UI/tkext.py (.../branches/hackontest/sK1) (revision 560)
@@ -196,7 +196,7 @@
# self['image']=self.image
# else:
# self['image']='menu_icon_mask'
- AutoUpdate.SetSensitive(self, on)
+ AutoUpdate.SetSensitive(self, on)
def clean_up(self):
Index: src/app/UI/mainwindow.py
===================================================================
--- src/app/UI/mainwindow.py (.../trunk/sK1) (revision 560)
+++ src/app/UI/mainwindow.py (.../branches/hackontest/sK1) (revision 560)
@@ -39,6 +39,7 @@
UpdatedTButton
import tkext
from context import ctxPanel
+from app.Graphics.image import RGB_IMAGE, RGBA_IMAGE, GRAYSCALE_IMAGE, CMYK_IMAGE,BW_IMAGE
from command import CommandClass, Keymap, Commands
from math import floor, ceil
@@ -885,7 +886,17 @@
AddDocCmd('FillNone', _("No Fill"), 'AddStyle', args = EmptyFillStyle)
AddDocCmd('LineNone', _("No Line"), 'AddStyle', args = EmptyLineStyle)
AddDocCmd('UpdateStyle', _("Update Style"), 'UpdateDynamicStyleSel')
+
+
+ AddDocCmd('Convert_to_CMYK', _("Convert to CMYK"), 'ConvertImage', args = CMYK_IMAGE, sensitive_cb ='CanBeCMYK')
+ AddDocCmd('Convert_to_RGB', _("Convert to RGB"), 'ConvertImage', args = RGB_IMAGE, sensitive_cb ='CanBeRGB')
+ AddDocCmd('Convert_to_Grayscale', _("Convert to Grayscale"), 'ConvertImage', args = GRAYSCALE_IMAGE, sensitive_cb ='CanBeGrayscale')
+ AddDocCmd('Convert_to_BW', _("Convert to B&W"), 'ConvertImage', args = BW_IMAGE, sensitive_cb ='CanBeBW')
+
+ AddDocCmd('Invert', _("Invert Image"), 'Invert', sensitive_cb ='CanInvert')
+ AddDocCmd('Embed', _("Embed Image"), 'Embed', sensitive_cb ='CanEmbed')
+
################### Menu build ############################
def build_menu(self):
mbar = self.mbar
@@ -895,6 +906,7 @@
AppendMenu(mbar, _("Layout"), self.make_layout_menu(), 0)
AppendMenu(mbar, _("Arrange"), self.make_arrange_menu(), 0)
AppendMenu(mbar, _("Effects"), self.make_effects_menu(), 4)
+ AppendMenu(mbar, _("Bitmaps"), self.make_bitmaps_menu(), 0)
# AppendMenu(mbar, _("Curve"), self.make_curve_menu(), 1)
AppendMenu(mbar, _("Style"), self.make_style_menu(), 1)
# AppendMenu(mbar, _("Script"), self.make_script_menu(), 0)
@@ -1099,6 +1111,18 @@
None,
self.commands.ConvertToCurve])
+ def make_bitmaps_menu(self):
+ cmds = self.commands
+ return map(MakeCommand,
+ [cmds.Convert_to_CMYK,
+ cmds.Convert_to_RGB,
+ cmds.Convert_to_Grayscale,
+ cmds.Convert_to_BW,
+ None,
+ cmds.Invert,
+ None,
+ cmds.Embed])
+
def make_style_menu(self):
return map(MakeCommand,
[self.commands.FillNone,
@@ -1453,7 +1477,7 @@
is_eps = eps.IsEpsFileStart(file.read(256))
file.close()
dir, name = os.path.split(filename)
- config.preferences.image_dir = dir
+ config.preferences.dir_for_bitmap_import = dir
if is_eps:
imageobj = eps.EpsImage(filename = sysfilename)
else:
Index: src/extentions/pycms/ImPlatform.h
===================================================================
--- src/extentions/pycms/ImPlatform.h (.../trunk/sK1) (revision 0)
+++ src/extentions/pycms/ImPlatform.h (.../branches/hackontest/sK1) (revision 560)
@@ -0,0 +1,72 @@
+/*
+ * The Python Imaging Library
+ * $Id: ImPlatform.h 2134 2004-10-06 08:55:20Z fredrik $
+ *
+ * platform declarations for the imaging core library
+ *
+ * Copyright (c) Fredrik Lundh 1995-2003.
+ */
+
+#include "Python.h"
+
+/* Check that we have an ANSI compliant compiler */
+#ifndef HAVE_PROTOTYPES
+#error Sorry, this library requires support for ANSI prototypes.
+#endif
+#ifndef STDC_HEADERS
+#error Sorry, this library requires ANSI header files.
+#endif
+
+#if defined(_MSC_VER)
+#ifndef WIN32
+#define WIN32
+#endif
+/* VC++ 4.0 is a bit annoying when it comes to precision issues (like
+ claiming that "float a = 0.0;" would lead to loss of precision). I
+ don't like to see warnings from my code, but since I still want to
+ keep it readable, I simply switch off a few warnings instead of adding
+ the tons of casts that VC++ seem to require. This code is compiled
+ with numerous other compilers as well, so any real errors are likely
+ to be catched anyway. */
+#pragma warning(disable: 4244) /* conversion from 'float' to 'int' */
+#endif
+
+#if defined(_MSC_VER)
+#define inline __inline
+#elif !defined(USE_INLINE)
+#define inline
+#endif
+
+#if SIZEOF_SHORT == 2
+#define INT16 short
+#elif SIZEOF_INT == 2
+#define INT16 int
+#else
+#define INT16 short /* most things works just fine anyway... */
+#endif
+
+#if SIZEOF_SHORT == 4
+#define INT32 short
+#elif SIZEOF_INT == 4
+#define INT32 int
+#elif SIZEOF_LONG == 4
+#define INT32 long
+#else
+#error Cannot find required 32-bit integer type
+#endif
+
+#if SIZEOF_LONG == 8
+#define INT64 long
+#elif SIZEOF_LONG_LONG == 8
+#define INT64 long
+#endif
+
+/* assume IEEE; tweak if necessary (patches are welcome) */
+#define FLOAT32 float
+#define FLOAT64 double
+
+#define INT8 signed char
+#define UINT8 unsigned char
+
+#define UINT16 unsigned INT16
+#define UINT32 unsigned INT32
Property changes on: src/extentions/pycms/ImPlatform.h
___________________________________________________________________
Name: svn:eol-style
+ native
Index: src/extentions/pycms/Imaging.h
===================================================================
--- src/extentions/pycms/Imaging.h (.../trunk/sK1) (revision 0)
+++ src/extentions/pycms/Imaging.h (.../branches/hackontest/sK1) (revision 560)
@@ -0,0 +1,493 @@
+/*
+ * The Python Imaging Library
+ * $Id: Imaging.h 2308 2005-03-02 12:00:55Z fredrik $
+ *
+ * declarations for the imaging core library
+ *
+ * Copyright (c) 1997-2003 by Secret Labs AB
+ * Copyright (c) 1995-2003 by Fredrik Lundh
+ *
+ * See the README file for information on usage and redistribution.
+ */
+
+
+#include "ImPlatform.h"
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#ifndef M_PI
+#define M_PI 3.14159265359
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * Image data organization:
+ *
+ * mode bytes byte order
+ * -------------------------------
+ * 1 1 1
+ * L 1 L
+ * P 1 P
+ * I 4 I (32-bit integer, native byte order)
+ * F 4 F (32-bit IEEE float, native byte order)
+ * RGB 4 R, G, B, -
+ * RGBA 4 R, G, B, A
+ * CMYK 4 C, M, Y, K
+ * YCbCr 4 Y, Cb, Cr, -
+ *
+ * experimental modes (incomplete):
+ * LA 4 L, -, -, A
+ * PA 4 P, -, -, A
+ * I;16 2 I (16-bit integer, native byte order)
+ *
+ * "P" is an 8-bit palette mode, which should be mapped through the
+ * palette member to get an output image. Check palette->mode to
+ * find the corresponding "real" mode.
+ *
+ * For information on how to access Imaging objects from your own C
+ * extensions, see
http://www.effbot.org/zone/pil-extending.htm
+ */
+
+/* Handles */
+
+typedef struct ImagingMemoryInstance* Imaging;
+typedef struct ImagingAccessInstance* ImagingAccess;
+typedef struct ImagingHistogramInstance* ImagingHistogram;
+typedef struct ImagingOutlineInstance* ImagingOutline;
+typedef struct ImagingPaletteInstance* ImagingPalette;
+
+/* handle magics (used with PyCObject). */
+#define IMAGING_MAGIC "PIL Imaging"
+#define IMAGING_ACCESS_MAGIC "PIL ImagingAccess"
+
+/* pixel types */
+#define IMAGING_TYPE_UINT8 0
+#define IMAGING_TYPE_INT32 1
+#define IMAGING_TYPE_FLOAT32 2
+#define IMAGING_TYPE_SPECIAL 3 /* check mode for details */
+
+struct ImagingMemoryInstance {
+
+ /* Format */
+ char mode[4+1]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK") */
+ int type; /* Data type (IMAGING_TYPE_*) */
+ int depth; /* Depth (ignored in this version) */
+ int bands; /* Number of bands (1, 2, 3, or 4) */
+ int xsize; /* Image dimension. */
+ int ysize;
+
+ /* Colour palette (for "P" images only) */
+ ImagingPalette palette;
+
+ /* Data pointers */
+ UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
+ INT32 **image32; /* Set for 32-bit images (pixelsize=4). */
+
+ /* Internals */
+ char **image; /* Actual raster data. */
+ char *block; /* Set if data is allocated in a single block. */
+
+ int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
+ int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
+
+ /* Virtual methods */
+ void (*destroy)(Imaging im);
+
+};
+
+
+#define IMAGING_PIXEL_1(im,x,y) ((im)->image8[(y)][(x)])
+#define IMAGING_PIXEL_L(im,x,y) ((im)->image8[(y)][(x)])
+#define IMAGING_PIXEL_LA(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_P(im,x,y) ((im)->image8[(y)][(x)])
+#define IMAGING_PIXEL_PA(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_I(im,x,y) ((im)->image32[(y)][(x)])
+#define IMAGING_PIXEL_F(im,x,y) (((FLOAT32*)(im)->image32[y])[x])
+#define IMAGING_PIXEL_RGB(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_RGBA(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_CMYK(im,x,y) ((im)->image[(y)][(x)*4])
+#define IMAGING_PIXEL_YCbCr(im,x,y) ((im)->image[(y)][(x)*4])
+
+#define IMAGING_PIXEL_UINT8(im,x,y) ((im)->image8[(y)][(x)])
+#define IMAGING_PIXEL_INT32(im,x,y) ((im)->image32[(y)][(x)])
+#define IMAGING_PIXEL_FLOAT32(im,x,y) (((FLOAT32*)(im)->image32[y])[x])
+
+#define IMAGING_ACCESS_HEAD\
+ int (*getline)(ImagingAccess access, char *buffer, int y);\
+ void (*destroy)(ImagingAccess access)
+
+struct ImagingAccessInstance {
+ IMAGING_ACCESS_HEAD;
+
+ /* Data members */
+ Imaging im;
+
+};
+
+
+struct ImagingHistogramInstance {
+
+ /* Format */
+ char mode[4+1]; /* Band names (of corresponding source image) */
+ int bands; /* Number of bands (1, 3, or 4) */
+
+ /* Data */
+ long *histogram; /* Histogram (bands*256 longs) */
+
+};
+
+
+struct ImagingPaletteInstance {
+
+ /* Format */
+ char mode[4+1]; /* Band names */
+
+ /* Data */
+ UINT8 palette[1024];/* Palette data (same format as image data) */
+
+ INT16* cache; /* Palette cache (used for predefined palettes) */
+ int keep_cache; /* This palette will be reused; keep cache */
+
+};
+
+
+/* Objects */
+/* ------- */
+
+extern Imaging ImagingNew(const char* mode, int xsize, int ysize);
+extern Imaging ImagingNew2(const char* mode, Imaging imOut, Imaging imIn);
+extern void ImagingDelete(Imaging im);
+
+extern Imaging ImagingNewBlock(const char* mode, int xsize, int ysize);
+extern Imaging ImagingNewArray(const char* mode, int xsize, int ysize);
+extern Imaging ImagingNewMap(const char* filename, int readonly,
+ const char* mode, int xsize, int ysize);
+
+extern Imaging ImagingNewPrologue(const char *mode,
+ unsigned xsize, unsigned ysize);
+extern Imaging ImagingNewPrologueSubtype(const char *mode,
+ unsigned xsize, unsigned ysize,
+ int structure_size);
+extern Imaging ImagingNewEpilogue(Imaging im);
+
+extern void ImagingCopyInfo(Imaging destination, Imaging source);
+
+extern void ImagingHistogramDelete(ImagingHistogram histogram);
+
+extern ImagingAccess ImagingAccessNew(Imaging im);
+extern void ImagingAccessDelete(ImagingAccess access);
+
+extern ImagingPalette ImagingPaletteNew(const char *mode);
+extern ImagingPalette ImagingPaletteNewBrowser(void);
+extern ImagingPalette ImagingPaletteDuplicate(ImagingPalette palette);
+extern void ImagingPaletteDelete(ImagingPalette palette);
+
+extern int ImagingPaletteCachePrepare(ImagingPalette palette);
+extern void ImagingPaletteCacheUpdate(ImagingPalette palette,
+ int r, int g, int b);
+extern void ImagingPaletteCacheDelete(ImagingPalette palette);
+
+#define ImagingPaletteCache(p, r, g, b)\
+ p->cache[(r>>2) + (g>>2)*64 + (b>>2)*64*64]
+
+extern Imaging ImagingQuantize(Imaging im, int colours, int mode, int kmeans);
+
+/* Threading */
+/* --------- */
+
+typedef void* ImagingSectionCookie;
+
+extern void ImagingSectionEnter(ImagingSectionCookie* cookie);
+extern void ImagingSectionLeave(ImagingSectionCookie* cookie);
+
+/* Exceptions */
+/* ---------- */
+
+extern void* ImagingError_IOError(void);
+extern void* ImagingError_MemoryError(void);
+extern void* ImagingError_ModeError(void); /* maps to ValueError by default */
+extern void* ImagingError_Mismatch(void); /* maps to ValueError by default */
+extern void* ImagingError_ValueError(const char* message);
+
+/* Transform callbacks */
+/* ------------------- */
+
+/* standard transforms */
+#define IMAGING_TRANSFORM_AFFINE 0
+#define IMAGING_TRANSFORM_PERSPECTIVE 2
+#define IMAGING_TRANSFORM_QUAD 3
+
+
+/* standard filters */
+#define IMAGING_TRANSFORM_NEAREST 0
+#define IMAGING_TRANSFORM_ANTIALIAS 1
+#define IMAGING_TRANSFORM_BILINEAR 2
+#define IMAGING_TRANSFORM_BICUBIC 3
+
+typedef int (*ImagingTransformMap)(double* X, double* Y,
+ int x, int y, void* data);
+typedef int (*ImagingTransformFilter)(void* out, Imaging im,
+ double x, double y,
+ void* data);
+
+/* Image Manipulation Methods */
+/* -------------------------- */
+
+extern Imaging ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha);
+extern Imaging ImagingCopy(Imaging im);
+extern Imaging ImagingConvert(
+ Imaging im, const char* mode, ImagingPalette palette, int dither);
+extern Imaging ImagingConvertMatrix(Imaging im, const char *mode, float m[]);
+extern Imaging ImagingCrop(Imaging im, int x0, int y0, int x1, int y1);
+extern Imaging ImagingExpand(Imaging im, int x, int y, int mode);
+extern Imaging ImagingFill(Imaging im, const void* ink);
+extern int ImagingFill2(
+ Imaging into, const void* ink, Imaging mask,
+ int x0, int y0, int x1, int y1);
+extern Imaging ImagingFillBand(Imaging im, int band, int color);
+extern Imaging ImagingFillLinearGradient(const char* mode);
+extern Imaging ImagingFillRadialGradient(const char* mode);
+extern Imaging ImagingFilter(
+ Imaging im, int xsize, int ysize, const FLOAT32* kernel,
+ FLOAT32 offset, FLOAT32 divisor);
+extern Imaging ImagingFlipLeftRight(Imaging imOut, Imaging imIn);
+extern Imaging ImagingFlipTopBottom(Imaging imOut, Imaging imIn);
+extern Imaging ImagingGetBand(Imaging im, int band);
+extern int ImagingGetBBox(Imaging im, int bbox[4]);
+typedef struct { int x, y; INT32 count; INT32 pixel; } ImagingColorItem;
+extern ImagingColorItem* ImagingGetColors(Imaging im, int maxcolors,
+ int *colors);
+extern int ImagingGetExtrema(Imaging im, void *extrema);
+extern int ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj);
+extern ImagingHistogram ImagingGetHistogram(
+ Imaging im, Imaging mask, void *extrema);
+extern Imaging ImagingModeFilter(Imaging im, int size);
+extern Imaging ImagingNegative(Imaging im);
+extern Imaging ImagingOffset(Imaging im, int xoffset, int yoffset);
+extern int ImagingPaste(
+ Imaging into, Imaging im, Imaging mask,
+ int x0, int y0, int x1, int y1);
+extern Imaging ImagingPoint(
+ Imaging im, const char* tablemode, const void* table);
+extern Imaging ImagingPointTransform(
+ Imaging imIn, double scale, double offset);
+extern Imaging ImagingPutBand(Imaging im, Imaging imIn, int band);
+extern Imaging ImagingRankFilter(Imaging im, int size, int rank);
+extern Imaging ImagingResize(Imaging imOut, Imaging imIn, int filter);
+extern Imaging ImagingRotate(
+ Imaging imOut, Imaging imIn, double theta, int filter);
+extern Imaging ImagingRotate90(Imaging imOut, Imaging imIn);
+extern Imaging ImagingRotate180(Imaging imOut, Imaging imIn);
+extern Imaging ImagingRotate270(Imaging imOut, Imaging imIn);
+extern Imaging ImagingStretch(Imaging imOut, Imaging imIn, int filter);
+extern Imaging ImagingTransformPerspective(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ double a[8], int filter, int fill);
+extern Imaging ImagingTransformAffine(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ double a[6], int filter, int fill);
+extern Imaging ImagingTransformQuad(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ double a[8], int filter, int fill);
+extern Imaging ImagingTransform(
+ Imaging imOut, Imaging imIn, int x0, int y0, int x1, int y1,
+ ImagingTransformMap transform, void* transform_data,
+ ImagingTransformFilter filter, void* filter_data,
+ int fill);
+extern Imaging ImagingCopy2(Imaging imOut, Imaging imIn);
+extern Imaging ImagingConvert2(Imaging imOut, Imaging imIn);
+
+/* Channel operations */
+/* any mode, except "F" */
+extern Imaging ImagingChopLighter(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopDarker(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopDifference(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopMultiply(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopScreen(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopAdd(
+ Imaging imIn1, Imaging imIn2, float scale, int offset);
+extern Imaging ImagingChopSubtract(
+ Imaging imIn1, Imaging imIn2, float scale, int offset);
+extern Imaging ImagingChopAddModulo(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2);
+
+/* "1" images only */
+extern Imaging ImagingChopAnd(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopOr(Imaging imIn1, Imaging imIn2);
+extern Imaging ImagingChopXor(Imaging imIn1, Imaging imIn2);
+
+/* Image measurement */
+extern void ImagingCrack(Imaging im, int x0, int y0);
+
+/* Graphics */
+struct ImagingAffineMatrixInstance {
+ float a[9];
+};
+
+typedef struct ImagingAffineMatrixInstance *ImagingAffineMatrix;
+
+extern int ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int op);
+extern int ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap,
+ const void* ink, int op);
+extern int ImagingDrawChord(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int fill,
+ int op);
+extern int ImagingDrawEllipse(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int fill, int op);
+extern int ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int op);
+extern int ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int width, int op);
+extern int ImagingDrawPieslice(Imaging im, int x0, int y0, int x1, int y1,
+ int start, int end, const void* ink, int fill,
+ int op);
+extern int ImagingDrawPoint(Imaging im, int x, int y, const void* ink, int op);
+extern int ImagingDrawPolygon(Imaging im, int points, int *xy,
+ const void* ink, int fill, int op);
+extern int ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1,
+ const void* ink, int fill, int op);
+
+/* Level 2 graphics (WORK IN PROGRESS) */
+extern ImagingOutline ImagingOutlineNew(void);
+extern void ImagingOutlineDelete(ImagingOutline outline);
+
+extern int ImagingDrawOutline(Imaging im, ImagingOutline outline,
+ const void* ink, int fill, int op);
+
+extern int ImagingOutlineMove(ImagingOutline outline, float x, float y);
+extern int ImagingOutlineLine(ImagingOutline outline, float x, float y);
+extern int ImagingOutlineCurve(ImagingOutline outline, float x1, float y1,
+ float x2, float y2, float x3, float y3);
+extern int ImagingOutlineTransform(ImagingOutline outline, double a[6]);
+
+extern int ImagingOutlineClose(ImagingOutline outline);
+
+/* Special effects */
+extern Imaging ImagingEffectSpread(Imaging imIn, int distance);
+extern Imaging ImagingEffectNoise(int xsize, int ysize, float sigma);
+extern Imaging ImagingEffectMandelbrot(int xsize, int ysize,
+ double extent[4], int quality);
+
+/* Obsolete */
+extern int ImagingToString(Imaging im, int orientation, char *buffer);
+extern int ImagingFromString(Imaging im, int orientation, char *buffer);
+
+
+/* File I/O */
+/* -------- */
+
+/* Built-in drivers */
+extern Imaging ImagingOpenPPM(const char* filename);
+extern int ImagingSavePPM(Imaging im, const char* filename);
+
+/* Utility functions */
+extern UINT32 ImagingCRC32(UINT32 crc, UINT8* buffer, int bytes);
+
+/* Codecs */
+typedef struct ImagingCodecStateInstance *ImagingCodecState;
+typedef int (*ImagingCodec)(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+
+extern int ImagingBitDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingEpsEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingFliDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingGifDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingGifEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingHexDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#ifdef HAVE_LIBJPEG
+extern int ImagingJpegDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingJpegEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#endif
+extern int ImagingLzwDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#ifdef HAVE_LIBMPEG
+extern int ImagingMpegDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#endif
+extern int ImagingMspDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingPcdDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingPcxDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingPcxEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingRawDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingRawEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingSunRleDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingXbmDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingXbmEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#ifdef HAVE_LIBZ
+extern int ImagingZipDecode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+extern int ImagingZipEncode(Imaging im, ImagingCodecState state,
+ UINT8* buffer, int bytes);
+#endif
+
+typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels);
+
+/* Public shufflers */
+extern void ImagingPackRGB(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingPackBGR(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackRGB(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackBGR(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackYCC(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackYCCA(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingUnpackYCbCr(UINT8* out, const UINT8* in, int pixels);
+
+extern void ImagingConvertRGB2YCbCr(UINT8* out, const UINT8* in, int pixels);
+extern void ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels);
+
+extern ImagingShuffler ImagingFindUnpacker(const char* mode,
+ const char* rawmode, int* bits_out);
+extern ImagingShuffler ImagingFindPacker(const char* mode,
+ const char* rawmode, int* bits_out);
+
+struct ImagingCodecStateInstance {
+ int count;
+ int state;
+ int errcode;
+ int x, y;
+ int ystep;
+ int xsize, ysize, xoff, yoff;
+ ImagingShuffler shuffle;
+ int bits, bytes;
+ UINT8 *buffer;
+ void *context;
+};
+
+/* Errcodes */
+#define IMAGING_CODEC_END 1
+#define IMAGING_CODEC_OVERRUN -1
+#define IMAGING_CODEC_BROKEN -2
+#define IMAGING_CODEC_UNKNOWN -3
+#define IMAGING_CODEC_CONFIG -8
+#define IMAGING_CODEC_MEMORY -9
+
+#if defined(__cplusplus)
+}
+#endif
Property changes on: src/extentions/pycms/Imaging.h
___________________________________________________________________
Name: svn:eol-style
+ native
Index: src/extentions/pycms/pyCMSdll.c
===================================================================
--- src/extentions/pycms/pyCMSdll.c (.../trunk/sK1) (revision 0)
+++ src/extentions/pycms/pyCMSdll.c (.../branches/hackontest/sK1) (revision 560)
@@ -0,0 +1,673 @@
+#define COPYRIGHTINFO "\
+pyCMS\n\
+a Python / PIL interface to the littleCMS ICC Color Management System\n\
+Copyright (C) 2002-2003 Kevin Cazabon\n\
[email protected]\n\
+
http://www.cazabon.com\n\
+\n\
+pyCMS home page:
http://www.cazabon.com/pyCMS\n\
+littleCMS home page:
http://www.littlecms.com\n\
+(littleCMS is Copyright (C) 1998-2001 Marti Maria)\n\
+\n\
+This library is free software; you can redistribute it and/or\n\
+modify it under the terms of the GNU Lesser General Public\n\
+License as published by the Free Software Foundation; either\n\
+version 2.1 of the License, or (at your option) any later version.\n\
+\n\
+This library is distributed in the hope that it will be useful,\n\
+but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n\
+Lesser General Public License for more details.\n\
+\n\
+You should have received a copy of the GNU Lesser General Public\n\
+License along with this library; if not, write to the Free Software\n\
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\
+"
+
+/////////////////////////////////////////////////////////////////////////////
+// includes
+/////////////////////////////////////////////////////////////////////////////
+#include "Python.h"
+//#include "patchlevel.h" // so we can include the Python version automatically in pyCMSdll.versions()
+#include "lcms.h"
+#include "Imaging.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+// version information: update this before compiling for the versions you're using
+/////////////////////////////////////////////////////////////////////////////
+#define PYCMSVERSION "0.0.2 alpha"
+#define LITTLECMSVERSION "1.09b"
+#define PILVERSION "1.1.3"
+
+//#ifndef PY_MAJOR_VERSION
+ // before 1.5.2b2, these were not supported
+// #define PY_MAJOR_VERSION 0
+// #define PY_MINOR_VERSION 0
+// #define PY_MICRO_VERSION 0
+//#endif
+#define PYTHONVERSION "2.2.0"
+
+/////////////////////////////////////////////////////////////////////////////
+// version history
+/////////////////////////////////////////////////////////////////////////////
+/*
+0.0.2 alpha: Minor updates, added interfaces to littleCMS features, Jan 6, 2003
+ - fixed some memory holes in how transforms/profiles were created and passed back to Python
+ due to improper destructor setup for PyCObjects
+ - added buildProofTransformFromOpenProfiles() function
+ - eliminated some code redundancy, centralizing several common tasks with internal functions
+
+0.0.1 alpha: First public release Dec 26, 2002
+
+*/
+
+/////////////////////////////////////////////////////////////////////////////
+// known to-do list with current version
+/////////////////////////////////////////////////////////////////////////////
+/*
+getDefaultIntent doesn't seem to work properly... whassup??? I'm getting very large int return values instead of 0-3
+getProfileName and getProfileInfo are a bit shaky... work on these to solidify them!
+
+Add comments to code to make it clearer for others to read/understand!!!
+Verify that PILmode->littleCMStype conversion in findLCMStype is correct for all PIL modes (it probably isn't for the more obscure ones)
+
+Add support for reading and writing embedded profiles in JPEG and TIFF files
+Add support for creating custom RGB profiles on the fly
+Add support for checking presence of a specific tag in a profile
+Add support for other littleCMS features as required
+
+*/
+
+
+/////////////////////////////////////////////////////////////////////////////
+// options / configuration
+/////////////////////////////////////////////////////////////////////////////
+// Set the action to take upon error within the CMS module
+// LCMS_ERROR_SHOW pop-up window showing error, do not close application
+// LCMS_ERROR_ABORT pop-up window showing error, close the application
+// LCMS_ERROR_IGNORE ignore the error and continue
+#define cmsERROR_HANDLER LCMS_ERROR_SHOW
+
+
+/////////////////////////////////////////////////////////////////////////////
+// reference
+/////////////////////////////////////////////////////////////////////////////
+/*
+INTENT_PERCEPTUAL 0
+INTENT_RELATIVE_COLORIMETRIC 1
+INTENT_SATURATION 2
+INTENT_ABSOLUTE_COLORIMETRIC 3
+*/
+
+
+/////////////////////////////////////////////////////////////////////////////
+// structs
+/////////////////////////////////////////////////////////////////////////////
+typedef struct {
+ PyObject_HEAD
+ Imaging image;
+} ImagingObject;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// internal functions
+/////////////////////////////////////////////////////////////////////////////
+DWORD
+findLCMStype (char* PILmode) {
+ char *errorMsg = NULL;
+
+ if (strcmp(PILmode, "RGB") == 0) {
+ return TYPE_RGBA_8;
+ }
+ else if (strcmp(PILmode, "RGBA") == 0) {
+ return TYPE_RGBA_8;
+ }
+ else if (strcmp(PILmode, "RGBX") == 0) {
+ return TYPE_RGBA_8;
+ }
+ else if (strcmp(PILmode, "RGBA;16B") == 0) {
+ return TYPE_RGBA_16;
+ }
+ else if (strcmp(PILmode, "CMYK") == 0) {
+ return TYPE_CMYK_8;
+ }
+ else if (strcmp(PILmode, "L") == 0) {
+ return TYPE_GRAY_8;
+ }
+ else if (strcmp(PILmode, "L;16") == 0) {
+ return TYPE_GRAY_16;
+ }
+ else if (strcmp(PILmode, "L;16B") == 0) {
+ return TYPE_GRAY_16_SE;
+ }
+ else if (strcmp(PILmode, "YCCA") == 0) {
+ return TYPE_YCbCr_8;
+ }
+ else if (strcmp(PILmode, "YCC") == 0) {
+ return TYPE_YCbCr_8;
+ }
+
+ else {
+ // take a wild guess... but you probably should fail instead.
+ return TYPE_GRAY_8; // so there's no buffer overrun...
+ }
+}
+
+int
+pyCMSdoTransform (Imaging im, Imaging imOut, cmsHTRANSFORM hTransform) {
+ int i;
+
+ if (im->xsize > imOut->xsize) {
+ return -1;
+ }
+ if (im->ysize > imOut->ysize) {
+ return -1;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+
+ for (i=0; i < im->ysize; i++)
+ {
+ cmsDoTransform(hTransform, im->image[i],
+ imOut->image[i],
+ im->xsize);
+ }
+
+ Py_END_ALLOW_THREADS
+
+ return 0;
+}
+
+cmsHTRANSFORM
+_buildTransform (cmsHPROFILE hInputProfile, cmsHPROFILE hOutputProfile, char *sInMode, char *sOutMode, int iRenderingIntent) {
+ cmsHTRANSFORM hTransform;
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ Py_BEGIN_ALLOW_THREADS
+
+ // create the transform
+ hTransform = cmsCreateTransform(hInputProfile,
+ findLCMStype(sInMode),
+ hOutputProfile,
+ findLCMStype(sOutMode),
+ iRenderingIntent, 0);
+
+ Py_END_ALLOW_THREADS
+
+ return hTransform;
+}
+
+cmsHTRANSFORM
+_buildProofTransform(cmsHPROFILE hInputProfile, cmsHPROFILE hOutputProfile, cmsHPROFILE hDisplayProfile, char *sInMode, char *sOutMode, int iRenderingIntent, int iDisplayIntent) {
+ cmsHTRANSFORM hTransform;
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ Py_BEGIN_ALLOW_THREADS
+
+ // create the transform
+ hTransform = cmsCreateProofingTransform(hInputProfile,
+ findLCMStype(sInMode),
+ hOutputProfile,
+ findLCMStype(sOutMode),
+ hDisplayProfile,
+ iRenderingIntent,
+ iDisplayIntent,
+ 0);
+
+ Py_END_ALLOW_THREADS
+
+ return hTransform;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Python callable functions
+/////////////////////////////////////////////////////////////////////////////
+static PyObject *
+versions (PyObject *self, PyObject *args) {
+ return Py_BuildValue ("ssss", PYCMSVERSION, LITTLECMSVERSION, PYTHONVERSION, PILVERSION);
+}
+
+static PyObject *
+about (PyObject *self, PyObject *args) {
+ return Py_BuildValue("s", COPYRIGHTINFO);
+}
+
+static PyObject *
+copyright (PyObject *self, PyObject *args) {
+ return about(self, args);
+}
+
+static PyObject *
+getOpenProfile(PyObject *self, PyObject *args) {
+ char *sProfile = NULL;
+
+ cmsHPROFILE hProfile;
+
+ if (!PyArg_ParseTuple(args, "s", &sProfile)) {
+ return Py_BuildValue("s", "ERROR: Could not parse argument tuple passed to pyCMSdll.getOpenProfile()");
+ }
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ hProfile = cmsOpenProfileFromFile(sProfile, "r");
+
+ return Py_BuildValue("O", PyCObject_FromVoidPtr(hProfile, cmsCloseProfile));
+}
+
+static PyObject *
+buildTransform(PyObject *self, PyObject *args) {
+ char *sInputProfile;
+ char *sOutputProfile;
+ char *sInMode;
+ char *sOutMode;
+ int iRenderingIntent = 0;
+ cmsHPROFILE hInputProfile, hOutputProfile;
+ cmsHTRANSFORM transform;
+
+ if (!PyArg_ParseTuple(args, "ssss|i", &sInputProfile, &sOutputProfile, &sInMode, &sOutMode, &iRenderingIntent)) {
+ return Py_BuildValue("s", "ERROR: Could not parse argument tuple passed to pyCMSdll.buildTransform()");
+ }
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ hInputProfile = cmsOpenProfileFromFile(sInputProfile, "r");
+ hOutputProfile = cmsOpenProfileFromFile(sOutputProfile, "r");
+
+ transform = _buildTransform(hInputProfile, hOutputProfile, sInMode, sOutMode, iRenderingIntent);
+
+ cmsCloseProfile(hInputProfile);
+ cmsCloseProfile(hOutputProfile);
+
+ return PyCObject_FromVoidPtr(transform, cmsDeleteTransform); // this may not be right way to call the destructor...?
+}
+
+static PyObject *
+buildTransformFromOpenProfiles (PyObject *self, PyObject *args) {
+ char *sInMode;
+ char *sOutMode;
+ int iRenderingIntent = 0;
+ void *pInputProfile;
+ void *pOutputProfile;
+ cmsHPROFILE hInputProfile, hOutputProfile;
+ void *hTransformPointer = NULL;
+ cmsHTRANSFORM transform;
+
+ if (!PyArg_ParseTuple(args, "OOss|i", &pInputProfile, &pOutputProfile, &sInMode, &sOutMode, &iRenderingIntent)) {
+ return Py_BuildValue("s", "ERROR: Could not parse argument tuple passed to pyCMSdll.buildTransformFromOpenProfiles()");
+ }
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ hInputProfile = (cmsHPROFILE) PyCObject_AsVoidPtr(pInputProfile);
+ hOutputProfile = (cmsHPROFILE) PyCObject_AsVoidPtr(pOutputProfile);
+
+ transform = _buildTransform(hInputProfile, hOutputProfile, sInMode, sOutMode, iRenderingIntent);
+
+ // we don't have to close these profiles... but do we have to decref them?
+
+ return PyCObject_FromVoidPtr(transform, cmsDeleteTransform); // this may not be right way to call the destructor...?
+}
+
+static PyObject *
+buildProofTransform(PyObject *self, PyObject *args) {
+ char *sInputProfile;
+ char *sOutputProfile;
+ char *sDisplayProfile;
+ char *sInMode;
+ char *sOutMode;
+ int iRenderingIntent = 0;
+ int iDisplayIntent = 0;
+ cmsHTRANSFORM transform;
+
+ cmsHPROFILE hInputProfile, hOutputProfile, hDisplayProfile;
+
+ if (!PyArg_ParseTuple(args, "sssss|ii", &sInputProfile, &sOutputProfile, &sDisplayProfile, &sInMode, &sOutMode, &iRenderingIntent, &iDisplayIntent)) {
+ return Py_BuildValue("s", "ERROR: Could not parse argument tuple passed to pyCMSdll.buildProofTransform()");
+ }
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ // open the input and output profiles
+ hInputProfile = cmsOpenProfileFromFile(sInputProfile, "r");
+ hOutputProfile = cmsOpenProfileFromFile(sOutputProfile, "r");
+ hDisplayProfile = cmsOpenProfileFromFile(sDisplayProfile, "r");
+
+ transform = _buildProofTransform(hInputProfile, hOutputProfile, hDisplayProfile, sInMode, sOutMode, iRenderingIntent, iDisplayIntent);
+
+ cmsCloseProfile(hInputProfile);
+ cmsCloseProfile(hOutputProfile);
+ cmsCloseProfile(hDisplayProfile);
+
+ return PyCObject_FromVoidPtr(transform, cmsDeleteTransform); // this may not be right way to call the destructor...?
+
+}
+
+static PyObject *
+buildProofTransformFromOpenProfiles(PyObject *self, PyObject *args) {
+ char *sInMode;
+ char *sOutMode;
+ int iRenderingIntent = 0;
+ int iDisplayIntent = 0;
+ void *pInputProfile;
+ void *pOutputProfile;
+ void *pDisplayProfile;
+ cmsHTRANSFORM transform;
+
+ cmsHPROFILE hInputProfile, hOutputProfile, hDisplayProfile;
+
+ if (!PyArg_ParseTuple(args, "OOOss|ii", &pInputProfile, &pOutputProfile, &pDisplayProfile, &sInMode, &sOutMode, &iRenderingIntent, &iDisplayIntent)) {
+ return Py_BuildValue("s", "ERROR: Could not parse argument tuple passed to pyCMSdll.buildProofTransform()");
+ }
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ hInputProfile = (cmsHPROFILE) PyCObject_AsVoidPtr(pInputProfile);
+ hOutputProfile = (cmsHPROFILE) PyCObject_AsVoidPtr(pOutputProfile);
+ hDisplayProfile = (cmsHPROFILE) PyCObject_AsVoidPtr(pDisplayProfile);
+
+ transform = _buildProofTransform(hInputProfile, hOutputProfile, hDisplayProfile, sInMode, sOutMode, iRenderingIntent, iDisplayIntent);
+
+ // we don't have to close these profiles, but do we have to decref them?
+
+ return PyCObject_FromVoidPtr(transform, cmsDeleteTransform); // this may not be right way to call the destructor...?
+}
+
+static PyObject *
+applyTransform(PyObject *self, PyObject *args) {
+ long idIn;
+ long idOut;
+ void *hTransformPointer;
+ cmsHTRANSFORM hTransform;
+ Imaging im;
+ Imaging imOut;
+
+ int result;
+
+ if (!PyArg_ParseTuple(args, "llO", &idIn, &idOut, &hTransformPointer)) {
+ return Py_BuildValue("s", "ERROR: Could not parse the data passed to pyCMSdll.applyTransform()");
+ }
+
+ im = (Imaging) idIn;
+ imOut = (Imaging) idOut;
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ hTransform = (cmsHTRANSFORM) PyCObject_AsVoidPtr(hTransformPointer);
+
+ result = pyCMSdoTransform(im, imOut, hTransform);
+
+ return Py_BuildValue("i", result);
+}
+
+static PyObject *
+profileToProfile(PyObject *self, PyObject *args)
+{
+ Imaging im;
+ Imaging imOut;
+ long idIn;
+ long idOut = 0L;
+ char *sInputProfile = NULL;
+ char *sOutputProfile = NULL;
+ int iRenderingIntent = 0;
+ char *inMode;
+ char *outMode;
+ int result;
+ cmsHPROFILE hInputProfile, hOutputProfile;
+ cmsHTRANSFORM hTransform;
+
+ // parse the PyObject arguments, assign to variables accordingly
+ if (!PyArg_ParseTuple(args, "llss|i", &idIn, &idOut, &sInputProfile, &sOutputProfile, &iRenderingIntent)) {
+ return Py_BuildValue("s", "ERROR: Could not parse the argument tuple passed to pyCMSdll.profileToProfile()");
+ }
+
+ im = (Imaging) idIn;
+
+ if (idOut != 0L) {
+ imOut = (Imaging) idOut;
+ }
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ // Check the modes of imIn and imOut to set the color type for the transform
+ // Note that the modes do NOT have to be the same, as long as they are each
+ // supported by the relevant profile specified
+
+ inMode = im->mode;
+ if (idOut == 0L) {
+ outMode = inMode;
+ }
+ else {
+ outMode = imOut->mode;
+ }
+
+ // open the input and output profiles
+ hInputProfile = cmsOpenProfileFromFile(sInputProfile, "r");
+ hOutputProfile = cmsOpenProfileFromFile(sOutputProfile, "r");
+
+ // create the transform
+ hTransform = _buildTransform(hInputProfile, hOutputProfile, inMode, outMode, iRenderingIntent);
+
+ // apply the transform to imOut (or directly to im in place if idOut is not supplied)
+ if (idOut != 0L) {
+ result = pyCMSdoTransform (im, imOut, hTransform);
+ }
+ else {
+ result = pyCMSdoTransform (im, im, hTransform);
+ }
+
+ // free the transform and profiles
+ cmsDeleteTransform(hTransform);
+ cmsCloseProfile(hInputProfile);
+ cmsCloseProfile(hOutputProfile);
+
+ // return 0 on success, -1 on failure
+ return Py_BuildValue("i", result);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Python-Callable On-The-Fly profile creation functions
+//////////////////////////////////////////////////////////////////////////////
+static PyObject *
+createProfile(PyObject *self, PyObject *args)
+{
+ char *sColorSpace;
+ cmsHPROFILE hProfile;
+ int iColorTemp = 0;
+ LPcmsCIExyY whitePoint = NULL;
+ int result;
+
+ if (!PyArg_ParseTuple(args, "s|i", &sColorSpace, &iColorTemp)) {
+ return Py_BuildValue("s", "ERROR: Could not parse the argument tuple passed to pyCMSdll.createProfile()");
+ }
+
+ cmsErrorAction(cmsERROR_HANDLER);
+
+ if (strcmp(sColorSpace, "LAB") == 0) {
+ if (iColorTemp > 0) {
+ result = cmsWhitePointFromTemp(iColorTemp, whitePoint);
+ if (result == FALSE) {
+ return Py_BuildValue("s", "ERROR: Could not calculate white point from color temperature provided, must be integer in degrees Kelvin");
+ }
+ hProfile = cmsCreateLabProfile(whitePoint);
+ }
+ else {
+ hProfile = cmsCreateLabProfile(NULL);
+ }
+ }
+ else if (strcmp(sColorSpace, "XYZ") == 0) {
+ hProfile = cmsCreateXYZProfile();
+ }
+ else if (strcmp(sColorSpace, "sRGB") == 0) {
+ hProfile = cmsCreate_sRGBProfile();
+ }
+ else {
+ return Py_BuildValue("s", "ERROR: Color space requested is not valid for built-in profiles");
+ }
+
+ return Py_BuildValue("O", PyCObject_FromVoidPtr(hProfile, cmsCloseProfile));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Python callable profile information functions
+//////////////////////////////////////////////////////////////////////////////
+static PyObject *
+getProfileName(PyObject *self, PyObject *args)
+{
+ // I've had some intermittant problems with this function and getProfileInfo... look at them closer
+ char *sProfile;
+ char name[1024];
+
+ int closeProfile = FALSE;
+
+ cmsHPROFILE hProfile;
+
+ if (!PyArg_ParseTuple(args, "s", &sProfile)) {
+ if (!PyArg_ParseTuple(args, "O", &hProfile)) {
+ return Py_BuildValue("s", "ERROR: Could not parse the argument tuple passed to pyCMSdll.getProfileName()");
+ }
+ }
+ else {
+ hProfile = cmsOpenProfileFromFile(sProfile, "r");
+ closeProfile = TRUE;
+ }
+
+ // is there a better way to do this? I can't seem to work with the const char* return value otherwise
+ sprintf(name, "%s\n", cmsTakeProductName(hProfile));
+
+ if (closeProfile == TRUE) {
+ cmsCloseProfile(hProfile);
+ }
+
+ return Py_BuildValue("s", name);
+}
+
+static PyObject *
+getProfileInfo(PyObject *self, PyObject *args)
+{
+ char *sProfile;
+ char info[4096];
+ int closeProfile = FALSE;
+
+ cmsHPROFILE hProfile;
+
+ if (!PyArg_ParseTuple(args, "s", &sProfile)) {
+ if (!PyArg_ParseTuple(args, "O", &hProfile)) {
+ return Py_BuildValue("s", "ERROR: Could not parse the argument tuple passed to pyCMSdll.getProfileInfo()");
+ }
+ }
+ else {
+ hProfile = cmsOpenProfileFromFile(sProfile, "r");
+ closeProfile = TRUE;
+ }
+
+ // is there a better way to do this? I can't seem to work with the const char* return value otherwise
+ sprintf(info, "%s\n", cmsTakeProductInfo(hProfile));
+
+ if (closeProfile == TRUE) {
+ cmsCloseProfile(hProfile);
+ }
+
+ return Py_BuildValue("s", info);
+}
+
+static PyObject *
+getDefaultIntent(PyObject *self, PyObject *args)
+{
+ char *sProfile;
+ int intent = 0;
+ int closeProfile = FALSE;
+
+ cmsHPROFILE hProfile;
+
+ if (!PyArg_ParseTuple(args, "s", &sProfile)) {
+ if (!PyArg_ParseTuple(args, "O", &hProfile)) {
+ return Py_BuildValue("s", "ERROR: Could not parse the argument tuple passed to pyCMSdll.getDefaultIntent()");
+ }
+ }
+ else {
+ hProfile = cmsOpenProfileFromFile(sProfile, "r");
+ closeProfile = TRUE;
+ }
+
+ intent = cmsTakeRenderingIntent(hProfile);
+
+ if (closeProfile == TRUE) {
+ cmsCloseProfile(hProfile);
+ }
+
+ return Py_BuildValue("i", intent);
+}
+
+static PyObject *
+isIntentSupported(PyObject *self, PyObject *args)
+{
+ char *sProfile;
+ int iIntent;
+ int iDirection;
+ int closeProfile = FALSE;
+
+ int result;
+
+ cmsHPROFILE hProfile;
+
+ if (!PyArg_ParseTuple(args, "sii", &sProfile, &iIntent, &iDirection)) {
+ if (!PyArg_ParseTuple(args, "Oii", &hProfile, &iIntent, &iDirection)) {
+ return Py_BuildValue("s", "ERROR: Could not parse the argument tuple passed to pyCMSdll.isIntentSupported()");
+ }
+ }
+ else {
+ hProfile = cmsOpenProfileFromFile(sProfile, "r");
+ closeProfile = TRUE;
+ }
+
+ result = cmsIsIntentSupported(hProfile, iIntent, iDirection);
+
+ if (closeProfile == TRUE) {
+ cmsCloseProfile(hProfile);
+ }
+
+ if (result == TRUE) {
+ return Py_BuildValue("i", 1);
+ }
+ else {
+ return Py_BuildValue("i", -1);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Python interface setup
+/////////////////////////////////////////////////////////////////////////////
+static PyMethodDef pyCMSdll_methods[] = {
+ // pyCMS info
+ {"versions", versions, 1, "pyCMSdll.versions() returs tuple of pyCMSversion, littleCMSversion, pythonVersion that it was compiled with (don't trust this 100%, they must be set manually in the source code for now)"},
+ {"about", about, 1, "pyCMSdll.about() returns info about pyCMSdll"},
+ {"copyright", copyright, 1, "pyCMSdll.copyright() returns info about pyCMSdll"},
+
+ // profile and transform functions
+ {"profileToProfile", profileToProfile, 1, "pyCMSdll.profileToProfile (idIn, idOut, InputProfile, OutputProfile, [RenderingIntent]) returns 0 on success, -1 on failure. If idOut is the same as idIn, idIn is modified in place, otherwise the results are applied to idOut"},
+ {"getOpenProfile", getOpenProfile, 1, "pyCMSdll.getOpenProfile (profileName) returns a handle to an open pyCMS profile that can be used to build a transform"},
+ {"buildTransform", buildTransform, 1, "pyCMSdll.buildTransform (InputProfile, OutputProfile, InMode, OutMode, [RenderingIntent]) returns a handle to a pre-computed ICC transform that can be used for processing multiple images, saving calculation time"},
+ {"buildProofTransform", buildProofTransform, 1, "pyCMSdll.buildProofTransform (InputProfile, OutputProfile, DisplayProfile, InMode, OutMode, [RenderingIntent], [DisplayRenderingIntent]) returns a handle to a pre-computed soft-proofing (simulating the output device capabilities on the display device) ICC transform that can be used for processing multiple images, saving calculation time"},
+ {"buildProofTransformFromOpenProfiles", buildProofTransformFromOpenProfiles, 1, "pyCMSdll.buildProofTransformFromOpenProfiles(InputProfile, OutputProfile, DisplayProfile, InMode, OutMode, [RenderingIntent], [DisplayRenderingIntent]) returns a handle to a pre-computed soft-proofing transform. Profiles should be HANDLES, not pathnames."},
+ {"applyTransform", applyTransform, 1, "pyCMSdll.applyTransform (idIn, idOut, hTransform) applys a pre-calcuated transform (from pyCMSdll.buildTransform) to an image. If idIn and idOut are the same, it modifies the image in place, otherwise the new image is built in idOut. Returns 0 on success, -1 on failure"},
+ {"buildTransformFromOpenProfiles", buildTransformFromOpenProfiles, 1, "pyCMSdll.buildTransformFromOpenProfiles (InputProfile, OutputProfile, InMode, OutMode, RenderingIntent) returns a handle to a pre-computed ICC transform that can be used for processing multiple images, saving calculation time"},
+
+ // on-the-fly profile creation functions
+ {"createProfile", createProfile, 1, "pyCMSdll.createProfile (colorSpace, [colorTemp]) returns a handle to an open profile created on the fly. colorSpace can be 'LAB', 'XYZ', or 'xRGB'. If using LAB, you can specify a white point color temperature, or let it default to D50 (5000K)"},
+
+ // profile info functions
+ {"getProfileName", getProfileName, 1, "pyCMSdll.getProfileName (profile) returns the internal name of the profile"},
+ {"getProfileInfo", getProfileInfo, 1, "pyCMSdll.getProfileInfo (profile) returns additional information about the profile"},
+ {"getDefaultIntent", getDefaultIntent, 1, "pyCMSdll.getDefaultIntent (profile) returns the default rendering intent of the profile (as an integer)"},
+ {"isIntentSupported", isIntentSupported, 1, "pyCMSdll.isIntentSupported (profile, intent, direction) returns 1 if profile supports that intent, -1 if it doesnt. Direction is what the profile is being used for: INPUT = 0, OUTPUT = 1, PROOF = 2"},
+
+ {NULL, NULL}
+};
+
+void initpyCMSdll(void)
+{
+ Py_InitModule("pyCMSdll", pyCMSdll_methods);
+}
Property changes on: src/extentions/pycms/pyCMSdll.c
___________________________________________________________________
Name: svn:eol-style
+ native
Index: src/share/icons/CrystalSVG/context/context_image_gray_disabled.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: src/share/icons/CrystalSVG/context/context_image_gray_disabled.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Index: src/share/icons/CrystalSVG/context/context_image_gray.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: src/share/icons/CrystalSVG/context/context_image_gray.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Index: src/share/icons/CrystalSVG/context/context_image_cmyk.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: src/share/icons/CrystalSVG/context/context_image_cmyk.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Index: src/share/icons/CrystalSVG/context/context_image_cmyk_disabled.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: src/share/icons/CrystalSVG/context/context_image_cmyk_disabled.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Index: src/share/icons/CrystalSVG/context/context_image_bw_disabled.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: src/share/icons/CrystalSVG/context/context_image_bw_disabled.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Index: src/share/icons/CrystalSVG/context/context_image_rgb_disabled.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: src/share/icons/CrystalSVG/context/context_image_rgb_disabled.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Index: src/share/icons/CrystalSVG/context/context_image_bw.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: src/share/icons/CrystalSVG/context/context_image_bw.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Index: src/share/icons/CrystalSVG/context/context_image_rgb.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: src/share/icons/CrystalSVG/context/context_image_rgb.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Index: setup.cfg
===================================================================
--- setup.cfg (.../trunk/sK1) (revision 560)
+++ setup.cfg (.../branches/hackontest/sK1) (revision 560)
@@ -2,5 +2,5 @@
release = 0
packager = Igor Novikov <
[email protected]>
provides = sk1
-requires = python-imaging libtcl8.5 libtk8.5 python-lcms python-reportlab
+requires = python-imaging libtcl8.5 libtk8.5 python-lcms python-reportlab liblcms