Skip to content

Commit

Permalink
Merge pull request #380 from wiredfool/lcms2
Browse files Browse the repository at this point in the history
LCMS1 replaced with LCMS2
  • Loading branch information
aclark4life committed Oct 16, 2013
2 parents 646364d + deb424c commit 55a0792
Show file tree
Hide file tree
Showing 17 changed files with 432 additions and 85 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ python:
- 3.2
- 3.3

install: "sudo apt-get -qq install libfreetype6-dev liblcms1-dev libwebp-dev"
install: "sudo apt-get -qq install libfreetype6-dev liblcms2-dev libwebp-dev"

script:
- python setup.py clean
Expand Down
2 changes: 2 additions & 0 deletions PIL/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ def isImageType(t):
"RGBA": ("RGB", "L", ("R", "G", "B", "A")),
"CMYK": ("RGB", "L", ("C", "M", "Y", "K")),
"YCbCr": ("RGB", "L", ("Y", "Cb", "Cr")),
"LAB": ("RGB", "L", ("L", "A", "B")),

# Experimental modes include I;16, I;16L, I;16B, RGBa, BGR;15, and
# BGR;24. Use these modes only if you know exactly what you're
Expand All @@ -224,6 +225,7 @@ def isImageType(t):
"RGBA": ('|u1', 4),
"CMYK": ('|u1', 4),
"YCbCr": ('|u1', 3),
"LAB": ('|u1', 3), # UNDONE - unsigned |u1i1i1
"I;16": ('=u2', None),
"I;16B": ('>u2', None),
"I;16L": ('<u2', None),
Expand Down
152 changes: 143 additions & 9 deletions PIL/ImageCms.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
Version History:
1.0.0 pil Oct 2013 Port to LCMS 2.
0.1.0 pil mod March 10, 2009
Renamed display profile to proof profile. The proof
Expand Down Expand Up @@ -77,7 +79,7 @@
"""

VERSION = "0.1.0 pil"
VERSION = "1.0.0 pil"

# --------------------------------------------------------------------.

Expand Down Expand Up @@ -151,8 +153,8 @@ def _set(self, profile, filename=None):
self.profile = profile
self.filename = filename
if profile:
self.product_name = profile.product_name
self.product_info = profile.product_info
self.product_name = None #profile.product_name
self.product_info = None #profile.product_info
else:
self.product_name = None
self.product_info = None
Expand Down Expand Up @@ -564,10 +566,10 @@ def createProfile(colorSpace, colorTemp=-1):
raise PyCMSError("Color space not supported for on-the-fly profile creation (%s)" % colorSpace)

if colorSpace == "LAB":
if isinstance(colorTemp, float):
colorTemp = int(colorTemp + 0.5)
if not isinstance(colorTemp, int):
raise PyCMSError("Color temperature must be a positive integer, \"%s\" not valid" % colorTemp)
try:
colorTemp = float(colorTemp)
except:
raise PyCMSError("Color temperature must be numeric, \"%s\" not valid" % colorTemp)

try:
return core.createProfile(colorSpace, colorTemp)
Expand Down Expand Up @@ -597,7 +599,19 @@ def getProfileName(profile):
# add an extra newline to preserve pyCMS compatibility
if not isinstance(profile, ImageCmsProfile):
profile = ImageCmsProfile(profile)
return profile.profile.product_name + "\n"
# do it in python, not c.
# // name was "%s - %s" (model, manufacturer) || Description ,
# // but if the Model and Manufacturer were the same or the model
# // was long, Just the model, in 1.x
model = profile.profile.product_model
manufacturer = profile.profile.product_manufacturer

if not (model or manufacturer):
return profile.profile.product_description+"\n"
if not manufacturer or len(model) > 30:
return model + "\n"
return "%s - %s\n" % (model, manufacturer)

except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v)

Expand Down Expand Up @@ -625,10 +639,130 @@ def getProfileInfo(profile):
if not isinstance(profile, ImageCmsProfile):
profile = ImageCmsProfile(profile)
# add an extra newline to preserve pyCMS compatibility
return profile.product_info + "\n"
# Python, not C. the white point bits weren't working well, so skipping.
# // info was description \r\n\r\n copyright \r\n\r\n K007 tag \r\n\r\n whitepoint
description = profile.profile.product_description
cpright = profile.profile.product_copyright
arr = []
for elt in (description, cpright):
if elt:
arr.append(elt)
return "\r\n\r\n".join(arr)+"\r\n\r\n"

except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v)


##
# (pyCMS) Gets the copyright for the given profile.
#
# If profile isn't a valid CmsProfile object or filename to a profile,
# a PyCMSError is raised.
#
# If an error occurs while trying to obtain the copyright tag, a PyCMSError
# is raised
#
# Use this function to obtain the information stored in the profile's
# copyright tag.
#
# @param profile EITHER a valid CmsProfile object, OR a string of the filename
# of an ICC profile.
# @return A string containing the internal profile information stored in an ICC
# tag.
# @exception PyCMSError

def getProfileCopyright(profile):
try:
# add an extra newline to preserve pyCMS compatibility
if not isinstance(profile, ImageCmsProfile):
profile = ImageCmsProfile(profile)
return profile.profile.product_copyright + "\n"
except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v)

##
# (pyCMS) Gets the manufacturer for the given profile.
#
# If profile isn't a valid CmsProfile object or filename to a profile,
# a PyCMSError is raised.
#
# If an error occurs while trying to obtain the manufacturer tag, a PyCMSError
# is raised
#
# Use this function to obtain the information stored in the profile's
# manufacturer tag.
#
# @param profile EITHER a valid CmsProfile object, OR a string of the filename
# of an ICC profile.
# @return A string containing the internal profile information stored in an ICC
# tag.
# @exception PyCMSError

def getProfileManufacturer(profile):
try:
# add an extra newline to preserve pyCMS compatibility
if not isinstance(profile, ImageCmsProfile):
profile = ImageCmsProfile(profile)
return profile.profile.product_manufacturer + "\n"
except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v)

##
# (pyCMS) Gets the model for the given profile.
#
# If profile isn't a valid CmsProfile object or filename to a profile,
# a PyCMSError is raised.
#
# If an error occurs while trying to obtain the model tag, a PyCMSError
# is raised
#
# Use this function to obtain the information stored in the profile's
# model tag.
#
# @param profile EITHER a valid CmsProfile object, OR a string of the filename
# of an ICC profile.
# @return A string containing the internal profile information stored in an ICC
# tag.
# @exception PyCMSError

def getProfileModel(profile):
try:
# add an extra newline to preserve pyCMS compatibility
if not isinstance(profile, ImageCmsProfile):
profile = ImageCmsProfile(profile)
return profile.profile.product_model + "\n"
except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v)

##
# (pyCMS) Gets the description for the given profile.
#
# If profile isn't a valid CmsProfile object or filename to a profile,
# a PyCMSError is raised.
#
# If an error occurs while trying to obtain the description tag, a PyCMSError
# is raised
#
# Use this function to obtain the information stored in the profile's
# description tag.
#
# @param profile EITHER a valid CmsProfile object, OR a string of the filename
# of an ICC profile.
# @return A string containing the internal profile information stored in an ICC
# tag.
# @exception PyCMSError

def getProfileDescription(profile):
try:
# add an extra newline to preserve pyCMS compatibility
if not isinstance(profile, ImageCmsProfile):
profile = ImageCmsProfile(profile)
return profile.profile.product_description + "\n"
except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v)



##
# (pyCMS) Gets the default intent name for the given profile.
#
Expand Down
Binary file added Tests/images/lab-green.tif
Binary file not shown.
Binary file added Tests/images/lab-red.tif
Binary file not shown.
Binary file added Tests/images/lab.tif
Binary file not shown.
Binary file added Tests/images/lena.Lab.tif
Binary file not shown.
41 changes: 41 additions & 0 deletions Tests/test_format_lab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from tester import *

from PIL import Image

def test_white():
i = Image.open('Tests/images/lab.tif')

bits = i.load()

assert_equal(i.mode, 'LAB')

assert_equal(i.getbands(), ('L','A', 'B'))

k = i.getpixel((0,0))
assert_equal(k, (255,128,128))

L = i.getdata(0)
a = i.getdata(1)
b = i.getdata(2)

assert_equal(list(L), [255]*100)
assert_equal(list(a), [128]*100)
assert_equal(list(b), [128]*100)


def test_green():
# l= 50 (/100), a = -100 (-128 .. 128) b=0 in PS
# == RGB: 0, 152, 117
i = Image.open('Tests/images/lab-green.tif')

k = i.getpixel((0,0))
assert_equal(k, (128,28,128))


def test_red():
# l= 50 (/100), a = 100 (-128 .. 128) b=0 in PS
# == RGB: 255, 0, 124
i = Image.open('Tests/images/lab-red.tif')

k = i.getpixel((0,0))
assert_equal(k, (128,228,128))
Loading

0 comments on commit 55a0792

Please sign in to comment.