summaryrefslogtreecommitdiffstats
path: root/libdimension-python
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2011-12-14 19:27:22 -0500
committerTavian Barnes <tavianator@gmail.com>2011-12-14 19:52:36 -0500
commitbfbe9e43e108f6816c17b9b7764b75284ac78313 (patch)
tree189f85eeec18a76ccb626e45455fa7e45406db7c /libdimension-python
parent7db5342a36341b061a8785a3b349cf0fcad69ebf (diff)
downloaddimension-bfbe9e43e108f6816c17b9b7764b75284ac78313.tar.xz
Re-think colors.
Color is a property of light, and thus doesn't include information about transparency. But canvas pixels and object pigments represent a color and a degree of transparency. The new type dmnsn_tcolor/ TColor encapsulates that information. Also, fix the transparent shadow implementation.
Diffstat (limited to 'libdimension-python')
-rw-r--r--libdimension-python/dimension.pxd36
-rw-r--r--libdimension-python/dimension.pyx110
-rwxr-xr-xlibdimension-python/tests/color.py12
3 files changed, 99 insertions, 59 deletions
diff --git a/libdimension-python/dimension.pxd b/libdimension-python/dimension.pxd
index 94966f3..0d0fcc4 100644
--- a/libdimension-python/dimension.pxd
+++ b/libdimension-python/dimension.pxd
@@ -43,8 +43,7 @@ cdef extern from "../libdimension/dimension.h":
# Arrays #
##########
- ctypedef struct dmnsn_array:
- pass
+ ctypedef struct dmnsn_array
dmnsn_array *dmnsn_new_array(size_t objsize)
void dmnsn_delete_array(dmnsn_array *array)
@@ -148,12 +147,8 @@ cdef extern from "../libdimension/dimension.h":
double R
double G
double B
- double trans
- double filter
dmnsn_color dmnsn_new_color(double R, double G, double B)
- dmnsn_color dmnsn_new_color5(double R, double G, double B,
- double trans, double filter)
double dmnsn_sRGB_gamma(double Clinear)
dmnsn_color dmnsn_color_to_sRGB(dmnsn_color color)
@@ -162,11 +157,11 @@ cdef extern from "../libdimension/dimension.h":
double dmnsn_color_intensity(dmnsn_color color)
dmnsn_color dmnsn_color_add(dmnsn_color color1, dmnsn_color color2)
+ dmnsn_color dmnsn_color_sub(dmnsn_color color1, dmnsn_color color2)
dmnsn_color dmnsn_color_mul(double n, dmnsn_color color)
dmnsn_color dmnsn_black
dmnsn_color dmnsn_white
- dmnsn_color dmnsn_clear
dmnsn_color dmnsn_red
dmnsn_color dmnsn_green
dmnsn_color dmnsn_blue
@@ -175,6 +170,18 @@ cdef extern from "../libdimension/dimension.h":
dmnsn_color dmnsn_yellow
dmnsn_color dmnsn_cyan
+ ctypedef struct dmnsn_tcolor:
+ dmnsn_color c
+ double T
+ double F
+
+ dmnsn_tcolor dmnsn_new_tcolor(dmnsn_color c, double T, double F)
+ dmnsn_tcolor DMNSN_TCOLOR(dmnsn_color c)
+ dmnsn_tcolor dmnsn_new_tcolor5(double R, double G, double B,
+ double T, double F)
+
+ dmnsn_tcolor dmnsn_clear
+
############
# Canvases #
############
@@ -186,11 +193,11 @@ cdef extern from "../libdimension/dimension.h":
dmnsn_canvas *dmnsn_new_canvas(size_t width, size_t height)
void dmnsn_delete_canvas(dmnsn_canvas *canvas)
- dmnsn_color dmnsn_canvas_get_pixel(dmnsn_canvas *canvas, size_t x, size_t y)
+ dmnsn_tcolor dmnsn_canvas_get_pixel(dmnsn_canvas *canvas, size_t x, size_t y)
void dmnsn_canvas_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y,
- dmnsn_color color)
+ dmnsn_tcolor tcolor)
- void dmnsn_canvas_clear(dmnsn_canvas *canvas, dmnsn_color color)
+ void dmnsn_canvas_clear(dmnsn_canvas *canvas, dmnsn_tcolor tcolor)
int dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
int dmnsn_png_write_canvas(dmnsn_canvas *canvas, FILE *file)
@@ -234,7 +241,7 @@ cdef extern from "../libdimension/dimension.h":
ctypedef struct dmnsn_pigment:
dmnsn_matrix trans
- dmnsn_color quick_color
+ dmnsn_tcolor quick_color
ctypedef enum dmnsn_pigment_map_flags:
DMNSN_PIGMENT_MAP_REGULAR
@@ -242,7 +249,7 @@ cdef extern from "../libdimension/dimension.h":
void dmnsn_delete_pigment(dmnsn_pigment *pigment)
- dmnsn_pigment *dmnsn_new_solid_pigment(dmnsn_color color)
+ dmnsn_pigment *dmnsn_new_solid_pigment(dmnsn_tcolor tcolor)
dmnsn_pigment *dmnsn_new_canvas_pigment(dmnsn_canvas *canvas)
dmnsn_pigment *dmnsn_new_pigment_map_pigment(dmnsn_pattern *pattern,
dmnsn_map *map,
@@ -270,7 +277,7 @@ cdef extern from "../libdimension/dimension.h":
void dmnsn_finish_cascade(dmnsn_finish *default_finish, dmnsn_finish *finish)
- dmnsn_ambient *dmnsn_new_basic_ambient(dmnsn_color ambient)
+ dmnsn_ambient *dmnsn_new_ambient(dmnsn_color ambient)
dmnsn_diffuse *dmnsn_new_lambertian(double diffuse)
dmnsn_specular *dmnsn_new_phong(double specular, double exp)
dmnsn_reflection *dmnsn_new_basic_reflection(dmnsn_color min, dmnsn_color max,
@@ -332,7 +339,8 @@ cdef extern from "../libdimension/dimension.h":
# Lights #
##########
- ctypedef struct dmnsn_light
+ ctypedef struct dmnsn_light:
+ dmnsn_vector x0
dmnsn_light *dmnsn_new_light()
void dmnsn_delete_light(dmnsn_light *light)
diff --git a/libdimension-python/dimension.pyx b/libdimension-python/dimension.pyx
index 8e48a5c..1e79620 100644
--- a/libdimension-python/dimension.pyx
+++ b/libdimension-python/dimension.pyx
@@ -408,13 +408,11 @@ cdef class _BaseColor:
red -- The red component
green -- The green component
blue -- The blue component
- trans -- The transparency of the color, 0.0 meaning opaque (default 0.0)
- filter -- How filtered the transparency is (default 0.0)
Alternatively, you can pass another Color, a gray intensity like 0.5, or a
- tuple or other sequence (red, green, blue[, trans[, filter]]).
+ tuple or other sequence (red, green, blue).
"""
- if len(args) == 1:
+ if len(args) == 1 and len(kwargs) == 0:
if isinstance(args[0], _BaseColor):
self._clin = (<_BaseColor>args[0])._clin
self._unlinearize()
@@ -428,9 +426,8 @@ cdef class _BaseColor:
self._linearize()
- def _real_init(self, double red, double green, double blue,
- double trans = 0.0, double filter = 0.0):
- self._c = dmnsn_new_color5(red, green, blue, trans, filter)
+ def _real_init(self, double red, double green, double blue):
+ self._c = dmnsn_new_color(red, green, blue)
property red:
"""The red component."""
@@ -444,14 +441,6 @@ cdef class _BaseColor:
"""The blue component."""
def __get__(self):
return self._c.B
- property trans:
- """The transparency of the color."""
- def __get__(self):
- return self._c.trans
- property filter:
- """How filtered the transparency is."""
- def __get__(self):
- return self._c.filter
def intensity(self):
return dmnsn_color_intensity(self._c)
@@ -489,10 +478,7 @@ cdef class _BaseColor:
cdef double rdiff = clhs.red - crhs.red
cdef double gdiff = clhs.green - crhs.green
cdef double bdiff = clhs.blue - crhs.blue
- cdef double tdiff = clhs.trans - crhs.trans
- cdef double fdiff = clhs.filter - crhs.filter
- cdef double sum = rdiff*rdiff + gdiff*gdiff + bdiff*bdiff \
- + tdiff*tdiff + fdiff*fdiff
+ cdef double sum = rdiff*rdiff + gdiff*gdiff + bdiff*bdiff
equal = sqrt(sum) < dmnsn_epsilon
if op == 2: # ==
return equal
@@ -502,17 +488,11 @@ cdef class _BaseColor:
return NotImplemented
def __repr__(self):
- return "dimension.%s(%r, %r, %r, %r, %r)" % \
- (type(self).__name__, self.red, self.green, self.blue, self.trans,
- self.filter)
+ return "dimension.%s(%r, %r, %r)" % \
+ (type(self).__name__, self.red, self.green, self.blue)
def __str__(self):
- if self.trans >= dmnsn_epsilon:
- return "%s<%s, %s, %s, trans = %s, filter = %s>" % \
- (type(self).__name__,
- self.red, self.green, self.blue, self.trans, self.filter)
- else:
- return "%s<%s, %s, %s>" % \
- (type(self).__name__, self.red, self.green, self.blue)
+ return "%s<%s, %s, %s>" % \
+ (type(self).__name__, self.red, self.green, self.blue)
cdef class Color(_BaseColor):
"""
@@ -551,7 +531,6 @@ cdef _BaseColor _Color(dmnsn_color c, type t):
Black = _Color(dmnsn_black, Color)
White = _Color(dmnsn_white, Color)
-Clear = _Color(dmnsn_clear, Color)
Red = _Color(dmnsn_red, Color)
Green = _Color(dmnsn_green, Color)
Blue = _Color(dmnsn_blue, Color)
@@ -560,6 +539,65 @@ Orange = _Color(dmnsn_orange, Color)
Yellow = _Color(dmnsn_yellow, Color)
Cyan = _Color(dmnsn_cyan, Color)
+cdef class TColor:
+ """
+ A transparent color.
+
+ This type is used for representing pigments and pixels, as it carries color as
+ well as transparency information.
+ """
+ cdef dmnsn_tcolor _tc
+
+ def __init__(self, *args, **kwargs):
+ """
+ Create a transparent color.
+
+ Keyword arguments:
+ color -- The Color() (or sRGB()) component
+ trans -- The transparency component
+ filter -- The proportion of the transparency that is filtered
+
+ Alternatively, you can pass another TColor.
+ """
+ if len(args) == 1 and len(kwargs) == 0:
+ if isinstance(args[0], TColor):
+ self._tc = (<TColor>args[0])._tc
+ else:
+ self._real_init(*args, **kwargs)
+ else:
+ self._real_init(*args, **kwargs)
+
+ def _real_init(self, color, double trans = 0, double filter = 0):
+ self._tc = dmnsn_new_tcolor(Color(color)._clin, trans, filter)
+
+ property color:
+ """The color component."""
+ def __get__(self):
+ return _Color(self._tc.c, Color)
+ property trans:
+ """The transparency component."""
+ def __get__(self):
+ return self._tc.T
+ property filter:
+ """The filter proportion."""
+ def __get__(self):
+ return self._tc.F
+
+ def __repr__(self):
+ return "dimension.TColor(%r, %r, %r)" % \
+ (self.color, self.trans, self.filter)
+ def __str__(self):
+ return "TColor<%s, %s, %s>" % \
+ (self.color, self.trans, self.filter)
+
+cdef TColor _TColor(dmnsn_tcolor tc):
+ """Wrap a TColor around a dmnsn_tcolor."""
+ cdef TColor self = TColor.__new__(TColor)
+ self._tc = tc
+ return self
+
+Clear = _TColor(dmnsn_clear)
+
############
# Canvases #
############
@@ -612,7 +650,7 @@ cdef class Canvas:
def clear(self, c):
"""Clear a canvas with a solid color."""
- dmnsn_canvas_clear(self._canvas, Color(c)._c)
+ dmnsn_canvas_clear(self._canvas, TColor(c)._tc)
def write_PNG(self, path):
"""Export the canvas as a PNG file."""
@@ -660,10 +698,10 @@ cdef class _CanvasProxy:
return self._canvas.height
def __getitem__(self, int y):
self._bounds_check(y)
- return _Color(dmnsn_canvas_get_pixel(self._canvas, self._x, y), Color)
+ return _TColor(dmnsn_canvas_get_pixel(self._canvas, self._x, y))
def __setitem__(self, int y, color):
self._bounds_check(y)
- dmnsn_canvas_set_pixel(self._canvas, self._x, y, Color(color)._c)
+ dmnsn_canvas_set_pixel(self._canvas, self._x, y, TColor(color)._tc)
def _bounds_check(self, int y):
if y < 0 or y >= self._canvas.height:
@@ -734,9 +772,9 @@ cdef class Pigment(_Transformable):
self._pigment = (<Pigment>quick_color)._pigment
DMNSN_INCREF(self._pigment)
else:
- self._pigment = dmnsn_new_solid_pigment(Color(quick_color)._c)
+ self._pigment = dmnsn_new_solid_pigment(TColor(quick_color)._tc)
else:
- self._pigment.quick_color = Color(quick_color)._c
+ self._pigment.quick_color = TColor(quick_color)._tc
def __dealloc__(self):
dmnsn_delete_pigment(self._pigment)
@@ -858,7 +896,7 @@ cdef class Ambient(Finish):
Keyword arguments:
color -- the color and intensity of the ambient light
"""
- self._finish.ambient = dmnsn_new_basic_ambient(Color(color)._c)
+ self._finish.ambient = dmnsn_new_ambient(Color(color)._c)
cdef class Diffuse(Finish):
"""Lambertian diffuse reflection."""
diff --git a/libdimension-python/tests/color.py b/libdimension-python/tests/color.py
index 9482545..8bf1836 100755
--- a/libdimension-python/tests/color.py
+++ b/libdimension-python/tests/color.py
@@ -24,21 +24,15 @@ from dimension import *
# Treat warnings as errors for tests
die_on_warnings(True)
-c = Color(0, 0.5, 1, trans = 0.5, filter = 0.35)
-assert repr(c) == "dimension.Color(0.0, 0.5, 1.0, 0.5, 0.35)", repr(c)
-assert str(c) == "Color<0.0, 0.5, 1.0, trans = 0.5, filter = 0.35>", str(c)
+c = Color(0, 0.5, 1)
+assert repr(c) == "dimension.Color(0.0, 0.5, 1.0)", repr(c)
+assert str(c) == "Color<0.0, 0.5, 1.0>", str(c)
assert c.red == 0, c.red
assert c.green == 0.5, c.green
assert c.blue == 1, c.blue
-assert c.trans == 0.5, c.filter
-assert c.filter == 0.35, c.trans
-
-c = Color(1, 0.5, 0)
-assert str(c) == "Color<1.0, 0.5, 0.0>", str(c)
assert Black == Color(0, 0, 0), Black
assert White == Color(1, 1, 1), White
-assert Clear == Color(0, 0, 0, trans = 1), Clear
assert Red == Color(1, 0, 0), Red
assert Green == Color(0, 1, 0), Green
assert Blue == Color(0, 0, 1), Blue