#!/usr/bin/python
# -*- coding: utf-8 -*-#
# Copyright (c) 2008, Xavier Basty
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'''Unit tests for the grapefruit module.'''
# $Id$
__author__ = 'xbasty@gmail.com'
__version__ = '0.1a3'
import unittest
import doctest
import grapefruit
# Also run doctests.
def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite(grapefruit))
return tests
class GrapeFruitTestCase(unittest.TestCase):
def failUnlessNear(self, first, second, diff=9e-5, msg=None):
'''
Fail if the difference between the two objects is greater
than a certain amout (default 9e-5).
'''
if hasattr(first,'__iter__') and hasattr(second,'__iter__'):
if len(first) != len(second):
raise self.failureException(msg or "%r != %r" % (first, second))
for f, s in zip(first, second):
if abs(s-f) > diff:
raise self.failureException(msg or "%r != %r @ %f" % (first, second, diff))
elif abs(second-first) > diff:
raise self.failureException(msg or "%r != %r @ %f" % (first, second, diff))
assertNear = failUnlessNear
class ConversionTest(GrapeFruitTestCase):
'''Test the static color conversion methods.'''
def testRgbHsl(self):
self.assertNear((30.0, 1.0, 0.5), grapefruit.Color.RgbToHsl(1, 0.5, 0))
self.assertNear((20.0, 1.0, 0.625), grapefruit.Color.RgbToHsl(1, 0.5, 0.25)) #ff8040
self.assertNear((40.0, 1.0, 0.375), grapefruit.Color.RgbToHsl(0.75, 0.5, 0)) #bf8000
self.assertNear((1, 0.5, 0), grapefruit.Color.HslToRgb(30.0, 1.0, 0.5))
self.assertNear((1, 0.5, 0.25), grapefruit.Color.HslToRgb(20.0, 1.0, 0.625))
self.assertNear((0.75, 0.5, 0), grapefruit.Color.HslToRgb(40.0, 1.0, 0.375))
def testRgbHsv(self):
self.assertEqual((30.0, 1.0, 1.0), grapefruit.Color.RgbToHsv(1, 0.5, 0))
self.assertEqual((1, 0.5, 0), grapefruit.Color.HsvToRgb(30.0, 1.0, 1.0))
def testRgbYiq(self):
self.assertNear((0.5923, 0.4589, -0.05), grapefruit.Color.RgbToYiq(1, 0.5, 0))
self.assertNear((1, 0.5, 0), grapefruit.Color.YiqToRgb(0.5923, 0.4589, -0.05))
def testRgbYuv(self):
self.assertNear((0.5925, -0.2916, 0.3575), grapefruit.Color.RgbToYuv(1, 0.5, 0))
self.assertNear((1, 0.5, 0), grapefruit.Color.YuvToRgb(0.5925, -0.2916, 0.3575))
def testRgbXyz(self):
self.assertNear((0.4890, 0.3657, 0.04485), grapefruit.Color.RgbToXyz(1, 0.5, 0))
self.assertNear((1, 0.5, 0), grapefruit.Color.XyzToRgb(0.488941, 0.365682, 0.0448137))
def testXyzLab(self):
self.assertNear((66.9518, 0.4308, 0.7397), grapefruit.Color.XyzToLab(0.488941, 0.365682, 0.0448137))
self.assertNear((0.4890, 0.3657, 0.0449), grapefruit.Color.LabToXyz(66.9518, 0.4308, 0.7397))
self.assertNear((66.9518, 0.4117, 0.6728), grapefruit.Color.XyzToLab(0.488941, 0.365682, 0.0448137, grapefruit.Color.WHITE_REFERENCE["std_D50"]))
self.assertNear((0.4890, 0.3657, 0.0449), grapefruit.Color.LabToXyz(66.9518, 0.4117, 0.6728, grapefruit.Color.WHITE_REFERENCE["std_D50"]))
def testCmykCmy(self):
self.assertNear((1, 0.32, 0, 0.5), grapefruit.Color.CmyToCmyk(1.0, 0.66, 0.5))
self.assertNear((1.0, 0.66, 0.5), grapefruit.Color.CmykToCmy(1, 0.32, 0, 0.5))
def testRgbCmy(self):
self.assertEqual((0, 0.5, 1), grapefruit.Color.RgbToCmy(1, 0.5, 0))
self.assertEqual((1, 0.5, 0), grapefruit.Color.CmyToRgb(0, 0.5, 1))
def testRgbHtml(self):
self.assertEqual("#ff8000", grapefruit.Color.RgbToHtml(1, 0.5, 0))
self.assertNear((1.0, 0.5020, 0.0), grapefruit.Color.HtmlToRgb("#ff8000"))
self.assertNear((1.0, 0.5020, 0.0), grapefruit.Color.HtmlToRgb("ff8000"))
self.assertNear((1.0, 0.4, 0.0), grapefruit.Color.HtmlToRgb("#f60"))
self.assertNear((1.0, 0.4, 0.0), grapefruit.Color.HtmlToRgb("f60"))
self.assertNear((1.000000, 0.980392, 0.803922), grapefruit.Color.HtmlToRgb("lemonchiffon"))
def testRgbPil(self):
self.assertNear(0x0080ff, grapefruit.Color.RgbToPil(1, 0.5, 0))
self.assertNear((1.0, 0.5020, 0), grapefruit.Color.PilToRgb(0x0080ff))
def testWebSafeComponent(self):
self.assertEqual(0.2, grapefruit.Color._WebSafeComponent(0.2))
self.assertEqual(0.2, grapefruit.Color._WebSafeComponent(0.25))
self.assertEqual(0.4, grapefruit.Color._WebSafeComponent(0.3))
self.assertEqual(0.4, grapefruit.Color._WebSafeComponent(0.25, True))
self.assertEqual(0.2, grapefruit.Color._WebSafeComponent(0.2, True))
self.assertEqual(0.2, grapefruit.Color._WebSafeComponent(0.3, True))
def testRgbToWebSafe(self):
self.assertEqual((1.0, 0.6, 0.0), grapefruit.Color.RgbToWebSafe(1, 0.55, 0.0))
self.assertEqual((1.0, 0.4, 0.0), grapefruit.Color.RgbToWebSafe(1, 0.55, 0.0, True))
self.assertEqual((1.0, 0.4, 0.0), grapefruit.Color.RgbToWebSafe(1, 0.5, 0.0, True))
def testRgbToGreyscale(self):
self.assertEqual((0.6, 0.6, 0.6), grapefruit.Color.RgbToGreyscale(1, 0.8, 0))
class NewFromTest(GrapeFruitTestCase):
'''Test the static color instanciation methods.'''
def testNewFromRgb(self):
c = grapefruit.Color.NewFromRgb(1.0, 0.5, 0.0)
self.assertEqual(c, (1.0, 0.5, 0.0, 1.0))
c = grapefruit.Color.NewFromRgb(1.0, 0.5, 0.0, 0.5)
self.assertEqual(c, (1.0, 0.5, 0.0, 0.5))
def testNewFromHsl(self):
c = grapefruit.Color.NewFromHsl(30, 1, 0.5)
self.assertEqual(c, (1.0, 0.5, 0.0, 1.0))
c = grapefruit.Color.NewFromHsl(30, 1, 0.5, 0.5)
self.assertEqual(c, (1.0, 0.5, 0.0, 0.5))
def testNewFromHsv(self):
c = grapefruit.Color.NewFromHsv(30, 1, 1)
self.assertEqual(c, (1.0, 0.5, 0.0, 1.0))
c = grapefruit.Color.NewFromHsv(30, 1, 1, 0.5)
self.assertEqual(c, (1.0, 0.5, 0.0, 0.5))
def testNewFromYiq(self):
c = grapefruit.Color.NewFromYiq(0.5923, 0.4589, -0.0499818)
self.assertNear(c, (1, 0.5, 0, 1))
c = grapefruit.Color.NewFromYiq(0.5923, 0.4589,-0.05, 0.5)
self.assertNear(c, (1, 0.5, 0, 0.5))
def testNewFromYuv(self):
c = grapefruit.Color.NewFromYuv(0.5925, -0.2916, 0.3575)
self.assertNear(c, (1, 0.5, 0, 1))
c = grapefruit.Color.NewFromYuv(0.5925, -0.2916, 0.3575, 0.5)
self.assertNear(c, (1, 0.5, 0, 0.5))
def testNewFromXyz(self):
c = grapefruit.Color.NewFromXyz(0.488941, 0.365682, 0.0448137)
self.assertNear(c, (1, 0.5, 0, 1))
c = grapefruit.Color.NewFromXyz(0.488941, 0.365682, 0.0448137, 0.5)
self.assertNear(c, (1, 0.5, 0, 0.5))
def testNewFromLab(self):
c = grapefruit.Color.NewFromLab(66.9518, 0.43084, 0.739692)
self.assertNear(c, (1, 0.5, 0, 1))
c = grapefruit.Color.NewFromLab(66.9518, 0.43084, 0.739692, wref=grapefruit.Color.WHITE_REFERENCE["std_D50"])
self.assertNear(c, (1.0123754, 0.492012, -0.143110, 1))
c = grapefruit.Color.NewFromLab(66.9518, 0.43084, 0.739692, 0.5)
self.assertNear(c, (1, 0.5, 0, 0.5))
c = grapefruit.Color.NewFromLab(66.9518, 0.43084, 0.739692, 0.5, grapefruit.Color.WHITE_REFERENCE["std_D50"])
self.assertNear(c, (1.0123754, 0.492012, -0.143110, 0.5))
def testNewFromLabInteger(self):
# Allow specifying lightness as an integer.
lab = (60, 0.3, 0.3)
c = grapefruit.Color.NewFromLab(*lab)
self.assertNear(c.lab, lab)
self.assertTrue(c.isLegal)
def testNewFromCmy(self):
c = grapefruit.Color.NewFromCmy(0, 0.5, 1)
self.assertEqual(c, (1, 0.5, 0, 1.0))
c = grapefruit.Color.NewFromCmy(0, 0.5, 1, 0.5)
self.assertEqual(c, (1, 0.5, 0, 0.5))
def testNewFromCmyk(self):
c = grapefruit.Color.NewFromCmyk(1, 0.32, 0, 0.5)
self.assertNear(c, (0, 0.34, 0.5, 1))
c = grapefruit.Color.NewFromCmyk(1, 0.32, 0, 0.5, 0.5)
self.assertNear(c, (0, 0.34, 0.5, 0.5))
def testNewFromHtml(self):
c = grapefruit.Color.NewFromHtml("#ff8000")
self.assertNear(c, (1, 0.5020, 0, 1))
c = grapefruit.Color.NewFromHtml("ff8000")
self.assertNear(c, (1, 0.5020, 0, 1))
c = grapefruit.Color.NewFromHtml("#f60")
self.assertNear(c, (1, 0.4, 0, 1))
c = grapefruit.Color.NewFromHtml("f60")
self.assertNear(c, (1, 0.4, 0, 1))
c = grapefruit.Color.NewFromHtml("lemonchiffon")
self.assertNear(c, (1, 0.9804, 0.8039, 1))
c = grapefruit.Color.NewFromHtml("#ff8000", 0.5)
self.assertNear(c, (1, 0.5020, 0, 0.5))
def testNewFromPil(self):
c = grapefruit.Color.NewFromPil(0x0080ff)
self.assertNear(c, (1, 0.5020, 0, 1))
c = grapefruit.Color.NewFromPil(0x0080ff, 0.5)
self.assertNear(c, (1, 0.5020, 0, 0.5))
class ColorTest(GrapeFruitTestCase):
def setUp(self):
self.rgbCol = grapefruit.Color.NewFromRgb(1.0, 0.5, 0.0)
self.hslCol = grapefruit.Color.NewFromHsl(30, 1, 0.5)
self.hslCol2 = grapefruit.Color.NewFromHsl(30, 0.5, 0.5)
def testInit(self):
self.assertEqual(grapefruit.Color((1.0, 0.5, 0.0)), (1.0, 0.5, 0.0, 1.0))
self.assertEqual(grapefruit.Color((1.0, 0.5, 0.0), mode='rgb'), (1.0, 0.5, 0.0, 1.0))
self.assertEqual(grapefruit.Color((30, 1, 0.5), mode='hsl'), (1.0, 0.5, 0.0, 1.0))
self.assertRaises(ValueError, grapefruit.Color, (30, 1, 0.5), 'hsv')
def testEq(self):
self.assertEqual(self.rgbCol, self.hslCol)
self.assertEqual(self.rgbCol, (1.0, 0.5, 0.0, 1.0))
self.assertEqual(self.rgbCol, [1.0, 0.5, 0.0, 1.0])
self.assertEqual([1.0, 0.5, 0.0, 1.0], self.rgbCol)
self.assertNotEqual(self.rgbCol, '(1.0, 0.5, 0.0, 1.0)')
def testRepr(self):
self.assertEqual(repr(self.rgbCol), '(1.0, 0.5, 0.0, 1.0)')
self.assertEqual(repr(self.hslCol), '(1.0, 0.5, 0.0, 1.0)')
def testStr(self):
self.assertEqual(str(self.rgbCol), '(1, 0.5, 0, 1)')
self.assertEqual(str(self.hslCol), '(1, 0.5, 0, 1)')
def testIter(self):
self.assertEqual([1, 0.5, 0, 1], list(iter(self.rgbCol)))
def testProperties(self):
self.assertEqual(self.rgbCol.alpha, 1.0)
self.assertEqual(self.rgbCol.whiteRef, grapefruit.Color.WHITE_REFERENCE['std_D65'])
self.assertEqual(self.rgbCol.rgb, (1, 0.5, 0))
self.assertEqual(self.hslCol.hue, 30)
self.assertEqual(self.rgbCol.hsl, (30, 1, 0.5))
self.assertEqual(self.rgbCol.hsv, (30, 1, 1))
self.assertNear(self.rgbCol.yiq, (0.5923, 0.4589, -0.05))
self.assertNear(self.rgbCol.yuv, (0.5925, -0.2916, 0.3575))
self.assertNear(self.rgbCol.xyz, (0.4890, 0.3657, 0.04485))
self.assertNear(self.rgbCol.lab, (66.9518, 0.4308, 0.7397))
self.assertEqual(self.rgbCol.cmy, (0, 0.5, 1))
self.assertEqual(self.rgbCol.cmyk, (0, 0.5, 1, 0))
self.assertEqual(self.rgbCol.intTuple, (255, 128, 0))
self.assertEqual(self.rgbCol.html, '#ff8000')
self.assertEqual(self.rgbCol.pil, 0x0080ff)
self.assertEqual(self.rgbCol.webSafe, (1, 0.6, 0))
self.assertEqual(self.rgbCol.greyscale, (0.5, 0.5, 0.5))
c = grapefruit.Color.NewFromRgb(1, 0.5, 0, wref=grapefruit.Color.WHITE_REFERENCE['std_D50'])
self.assertNear(c.lab, (66.9518, 0.4117, 0.6728))
def testColorWitgAlpha(self):
self.assertEqual(self.rgbCol.ColorWithAlpha(0.5), (1, 0.5, 0, 0.5))
def testColorWithWhiteRef(self):
self.assertEqual(self.hslCol.ColorWithWhiteRef((0.1, 0.2, 0.3)).whiteRef, (0.1, 0.2, 0.3))
def testColorWithHue(self):
self.assertEqual(self.hslCol.ColorWithHue(60), (1.0, 1.0, 0.0, 1.0))
self.assertEqual(self.hslCol.ColorWithHue(60).hsl, (60, 1, 0.5))
def testColorWithSaturation(self):
self.assertEqual(self.hslCol.ColorWithSaturation(0.5), (0.75, 0.5, 0.25, 1.0))
self.assertEqual(self.hslCol.ColorWithSaturation(0.5).hsl, (30, 0.5, 0.5))
def testColorWithLightness(self):
self.assertEqual(self.hslCol.ColorWithLightness(1), (1.0, 1.0, 1.0, 1.0))
self.assertEqual(self.hslCol.ColorWithLightness(1).hsl, (30, 1.0, 1.0))
def testDarkerColor(self):
self.assertNear(self.hslCol.DarkerColor(0.2), (0.6, 0.3, 0.0, 1.0))
self.assertNear(self.hslCol.DarkerColor(0.2).hsl, (30, 1, 0.3))
def testLighterColor(self):
self.assertNear(self.hslCol.LighterColor(0.2), (1.0, 0.7, 0.4, 1.0))
self.assertNear(self.hslCol.LighterColor(0.2).hsl, (30, 1, 0.7))
def testSaturate(self):
self.assertNear(self.hslCol2.Saturate(0.25), (0.875, 0.5, 0.125, 1.0))
self.assertNear(self.hslCol2.Saturate(0.25).hsl, (30, 0.75, 0.5))
def testDesaturate(self):
self.assertNear(self.hslCol2.Desaturate(0.25), (0.625, 0.5, 0.375, 1.0))
self.assertNear(self.hslCol2.Desaturate(0.25).hsl, (30, 0.25, 0.5))
def testWebSafeDither(self):
dithered = (
(1.0, 0.6, 0.0, 1.0),
(1.0, 0.4, 0.0, 1.0))
self.assertEqual(self.rgbCol.WebSafeDither(), dithered)
def testGradient(self):
gradient = [
(0.75, 0.25, 0.0, 1.0),
(0.5, 0.5, 0.0, 1.0),
(0.25, 0.75, 0.0, 1.0)]
c1 = grapefruit.Color.NewFromRgb(1.0, 0.0, 0.0)
c2 = grapefruit.Color.NewFromRgb(0.0, 1.0, 0.0)
self.assertEqual(gradient, c1.Gradient(c2, 3))
def testComplementaryColor(self):
self.assertEqual(self.hslCol.ComplementaryColor(mode='rgb').hsl, (210, 1, 0.5))
def testMonochromeScheme(self):
monochrome = (
(0.94, 0.8, 0.66, 1.0), # hsl(30, 0.7, 0.8)
(0.6, 0.3, 0.0, 1.0), # hsl(30, 1, 0.3)
(0.88, 0.6, 0.32, 1.0), # hsl(30, 0.7, 0.6)
(1.0, 0.8, 0.6, 1.0)) # hsl(30, 1, 0.8)
scheme = self.rgbCol.MonochromeScheme()
for i in range(len(monochrome)):
self.assertNear(scheme[i], monochrome[i])
def testTriadicScheme(self):
triad = (
(0.0, 1.0, 0.5, 1.0),
(0.5, 0.0, 1.0, 1.0))
self.assertEqual(self.rgbCol.TriadicScheme(mode='rgb'), triad)
def testTetradicScheme(self):
tetrad = (
(0.5, 1.0, 0.0, 1.0),
(0.0, 0.5, 1.0, 1.0),
(0.5, 0.0, 1.0, 1.0))
self.assertEqual(self.rgbCol.TetradicScheme(mode='rgb'), tetrad)
def testAnalogousScheme(self):
scheme = (
(1.0, 0.0, 0.0, 1.0),
(1.0, 1.0, 0.0, 1.0))
self.assertEqual(self.rgbCol.AnalogousScheme(mode='rgb'), scheme)
def testAlphaBlend(self):
c1 = grapefruit.Color.NewFromRgb(1, 0.5, 0, alpha = 0.2)
c2 = grapefruit.Color.NewFromRgb(1, 1, 1, alpha = 0.8)
self.assertNear(c1.AlphaBlend(c2), (1, 0.875, 0.75, 0.84))
def testBlend(self):
c1 = grapefruit.Color.NewFromRgb(1, 0.5, 0, alpha = 0.2)
c2 = grapefruit.Color.NewFromRgb(1, 1, 1, alpha = 0.6)
self.assertEqual(c1.Blend(c2), (1, 0.75, 0.5, 0.4))
def testNearestLegal(self):
c = grapefruit.Color.NewFromRgb(1.1, -0.1, 0.5, alpha=1.1)
self.assertFalse(c.isLegal)
self.assertNear(c.nearestLegal.rgb, (1.0, 0.0, 0.5))
self.assertNear(c.nearestLegal.alpha, 1.0)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
if __name__ == '__main__':
unittest.main(defaultTest='suite')
pass
# vim: ts=2 sts=2 sw=2 et