summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2011-09-18 14:04:19 -0400
committerTavian Barnes <tavianator@gmail.com>2011-09-18 14:04:19 -0400
commitb2e1763c7d54e76a49f6f4434996f37882ae2171 (patch)
treecefad99c5d5d2724d432c43ef762bc9e23f2eb2e
parent126211b917626fe7531310971981ee5d06026625 (diff)
downloaddimension-b2e1763c7d54e76a49f6f4434996f37882ae2171.tar.xz
Round correctly when converting colors to integers.
-rw-r--r--libdimension/canvas_pigment.c6
-rw-r--r--libdimension/dimension/color.h12
-rw-r--r--libdimension/gl.c20
-rw-r--r--libdimension/png.c21
4 files changed, 35 insertions, 24 deletions
diff --git a/libdimension/canvas_pigment.c b/libdimension/canvas_pigment.c
index 3ab9de4..8a7e7d3 100644
--- a/libdimension/canvas_pigment.c
+++ b/libdimension/canvas_pigment.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright (C) 2010 Tavian Barnes <tavianator@tavianator.com> *
+ * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> *
* *
* This file is part of The Dimension Library. *
* *
@@ -31,8 +31,8 @@ dmnsn_canvas_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v)
{
dmnsn_canvas *canvas = pigment->ptr;
- int x = (fmod(v.x, 1.0) + 1.0)*(canvas->width - 1) + 0.5;
- int y = (fmod(v.y, 1.0) + 1.0)*(canvas->height - 1) + 0.5;
+ size_t x = llround((fmod(v.x, 1.0) + 1.0)*(canvas->width - 1));
+ size_t y = llround((fmod(v.y, 1.0) + 1.0)*(canvas->height - 1));
dmnsn_color c = dmnsn_get_pixel(canvas, x%canvas->width, y%canvas->height);
return c;
}
diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h
index ecf7005..9664d22 100644
--- a/libdimension/dimension/color.h
+++ b/libdimension/dimension/color.h
@@ -81,6 +81,18 @@ dmnsn_color_is_black(dmnsn_color color)
&& fabs(color.trans) < dmnsn_epsilon;
}
+/** Saturate the color components to [0.0, 1.0]. */
+DMNSN_INLINE dmnsn_color
+dmnsn_color_saturate(dmnsn_color color)
+{
+ color.R = dmnsn_min(dmnsn_max(color.R, 0.0), 1.0);
+ color.G = dmnsn_min(dmnsn_max(color.G, 0.0), 1.0);
+ color.B = dmnsn_min(dmnsn_max(color.B, 0.0), 1.0);
+ color.trans = dmnsn_min(dmnsn_max(color.trans, 0.0), 1.0);
+ color.filter = dmnsn_min(dmnsn_max(color.filter, 0.0), 1.0);
+ return color;
+}
+
/* Perceptual color manipulation */
/** Convert from sRGB space. */
diff --git a/libdimension/gl.c b/libdimension/gl.c
index be79094..a2825f9 100644
--- a/libdimension/gl.c
+++ b/libdimension/gl.c
@@ -37,12 +37,12 @@ dmnsn_gl_optimizer_fn(const dmnsn_canvas *canvas,
dmnsn_color color = dmnsn_get_pixel(canvas, x, y);
color = dmnsn_remove_filter(color);
color = dmnsn_color_to_sRGB(color);
+ color = dmnsn_color_saturate(color);
- /* Saturate R, G, and B to [0, UINT16_MAX] */
- pixel[0] = dmnsn_min(dmnsn_max(color.R, 0.0), 1.0)*UINT16_MAX;
- pixel[1] = dmnsn_min(dmnsn_max(color.G, 0.0), 1.0)*UINT16_MAX;
- pixel[2] = dmnsn_min(dmnsn_max(color.B, 0.0), 1.0)*UINT16_MAX;
- pixel[3] = dmnsn_min(dmnsn_max(color.trans, 0.0), 1.0)*UINT16_MAX;
+ pixel[0] = lround(color.R*UINT16_MAX);
+ pixel[1] = lround(color.G*UINT16_MAX);
+ pixel[2] = lround(color.B*UINT16_MAX);
+ pixel[3] = lround(color.trans*UINT16_MAX);
}
/* Optimize canvas for GL drawing */
@@ -97,12 +97,12 @@ dmnsn_gl_write_canvas(const dmnsn_canvas *canvas)
color = dmnsn_get_pixel(canvas, x, y);
color = dmnsn_remove_filter(color);
color = dmnsn_color_to_sRGB(color);
+ color = dmnsn_color_saturate(color);
- /* Saturate R, G, and B to [0, UINT16_MAX] */
- pixel[0] = dmnsn_min(dmnsn_max(color.R, 0.0), 1.0)*UINT16_MAX;
- pixel[1] = dmnsn_min(dmnsn_max(color.G, 0.0), 1.0)*UINT16_MAX;
- pixel[2] = dmnsn_min(dmnsn_max(color.B, 0.0), 1.0)*UINT16_MAX;
- pixel[3] = dmnsn_min(dmnsn_max(color.trans, 0.0), 1.0)*UINT16_MAX;
+ pixel[0] = lround(color.R*UINT16_MAX);
+ pixel[1] = lround(color.G*UINT16_MAX);
+ pixel[2] = lround(color.B*UINT16_MAX);
+ pixel[3] = lround(color.trans*UINT16_MAX);
}
}
diff --git a/libdimension/png.c b/libdimension/png.c
index 7f5da8f..21ad764 100644
--- a/libdimension/png.c
+++ b/libdimension/png.c
@@ -67,12 +67,12 @@ dmnsn_png_optimizer_fn(const dmnsn_canvas *canvas,
color = dmnsn_get_pixel(canvas, x, y);
color = dmnsn_remove_filter(color);
color = dmnsn_color_to_sRGB(color);
+ color = dmnsn_color_saturate(color);
- /* Saturate R, G, and B to [0, UINT16_MAX] */
- pixel[0] = dmnsn_min(dmnsn_max(color.R, 0.0), 1.0)*UINT16_MAX;
- pixel[1] = dmnsn_min(dmnsn_max(color.G, 0.0), 1.0)*UINT16_MAX;
- pixel[2] = dmnsn_min(dmnsn_max(color.B, 0.0), 1.0)*UINT16_MAX;
- pixel[3] = dmnsn_min(dmnsn_max(color.trans, 0.0), 1.0)*UINT16_MAX;
+ pixel[0] = lround(color.R*UINT16_MAX);
+ pixel[1] = lround(color.G*UINT16_MAX);
+ pixel[2] = lround(color.B*UINT16_MAX);
+ pixel[3] = lround(color.trans*UINT16_MAX);
}
/** Payload type for PNG write thread callback. */
@@ -241,13 +241,12 @@ dmnsn_png_write_canvas_thread(void *ptr)
dmnsn_color color = dmnsn_get_pixel(payload->canvas, x, height - y - 1);
color = dmnsn_remove_filter(color);
color = dmnsn_color_to_sRGB(color);
+ color = dmnsn_color_saturate(color);
- /* Saturate R, G, and B to [0, UINT16_MAX] */
-
- row[4*x] = dmnsn_min(dmnsn_max(color.R, 0.0), 1.0)*UINT16_MAX;
- row[4*x + 1] = dmnsn_min(dmnsn_max(color.G, 0.0), 1.0)*UINT16_MAX;
- row[4*x + 2] = dmnsn_min(dmnsn_max(color.B, 0.0), 1.0)*UINT16_MAX;
- row[4*x + 3] = dmnsn_min(dmnsn_max(color.trans, 0.0), 1.0)*UINT16_MAX;
+ row[4*x] = lround(color.R*UINT16_MAX);
+ row[4*x + 1] = lround(color.G*UINT16_MAX);
+ row[4*x + 2] = lround(color.B*UINT16_MAX);
+ row[4*x + 3] = lround(color.trans*UINT16_MAX);
}
/* Write the row */