From b2e1763c7d54e76a49f6f4434996f37882ae2171 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 18 Sep 2011 14:04:19 -0400 Subject: Round correctly when converting colors to integers. --- libdimension/canvas_pigment.c | 6 +++--- libdimension/dimension/color.h | 12 ++++++++++++ libdimension/gl.c | 20 ++++++++++---------- libdimension/png.c | 21 ++++++++++----------- 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 * + * Copyright (C) 2010-2011 Tavian Barnes * * * * 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 */ -- cgit v1.2.3