diff options
author | Tavian Barnes <tavianator@gmail.com> | 2009-03-01 01:25:13 +0000 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2009-03-01 01:25:13 +0000 |
commit | ef4dbe789201bcb92596a67eb3fb3f3f03a09b49 (patch) | |
tree | d1591af1f8d50139c2eb154cca7b2fb9b0307785 /libdimension | |
parent | c7d93bfa183df3a22552c33c0af1dfc7658269ec (diff) | |
download | dimension-ef4dbe789201bcb92596a67eb3fb3f3f03a09b49.tar.xz |
Initial commit.
Diffstat (limited to 'libdimension')
-rw-r--r-- | libdimension/Makefile.am | 25 | ||||
-rw-r--r-- | libdimension/canvas.c | 203 | ||||
-rw-r--r-- | libdimension/dimension.h | 39 | ||||
-rw-r--r-- | libdimension/dimension/canvas.h | 50 | ||||
-rw-r--r-- | libdimension/dimension/color.h | 46 | ||||
-rw-r--r-- | libdimension/dimension/geometry.h | 92 |
6 files changed, 455 insertions, 0 deletions
diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am new file mode 100644 index 0000000..293093c --- /dev/null +++ b/libdimension/Makefile.am @@ -0,0 +1,25 @@ +########################################################################### +## Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> ## +## ## +## This file is part of the Dimension Build Suite. ## +## ## +## The Dimension Build Suite is free software; you can redistribute it ## +## and/or modify it under the terms of the GNU General Public License as ## +## published by the Free Software Foundation; either version 3 of the ## +## License, or (at your option) any later version. ## +## ## +## The Dimension Build Suite is distributed in the hope that it will be ## +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## +## General Public License for more details. ## +## ## +## You should have received a copy of the GNU General Public License ## +## along with this program. If not, see <http://www.gnu.org/licenses/>. ## +########################################################################### + +nobase_include_HEADERS = dimension.h dimension/geometry.h dimension/color.h dimension/canvas.h + +lib_LTLIBRARIES = libdimension.la + +libdimension_la_SOURCES = dimension.h dimension/geometry.h dimension/color.h dimension/canvas.h canvas.c +libdimension_la_LDFLAGS = -version-info 0:0:0 diff --git a/libdimension/canvas.c b/libdimension/canvas.c new file mode 100644 index 0000000..c730b53 --- /dev/null +++ b/libdimension/canvas.c @@ -0,0 +1,203 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> * + * * + * This file is part of Dimension. * + * * + * Dimension is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * Dimension is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +#include "dimension.h" +#include <math.h> +#include <stdlib.h> + +/* Conversions between CIE 1931 XYZ and sRGB color. */ + +dmnsn_pixel +dmnsn_pixel_from_color(dmnsn_color color) +{ + double Rlinear, Glinear, Blinear; /* Linear RGB values - no gamma */ + double R, G, B; /* sRGB values */ + dmnsn_pixel pixel; + + /* + * First, the linear conversion. Expressed as matrix multiplication, it looks + * like this: + * + * [Rlinear] [ 3.2410 -1.5374 -0.4986] [X] + * [Glinear] = [-0.9692 1.8760 0.0416]*[Y] + * [Blinear] [ 0.0556 -0.2040 1.0570] [Z] + */ + Rlinear = 3.2410*color.X - 1.5374*color.Y - 0.4986*color.Z; + Glinear = -0.9692*color.X + 1.8760*color.Y + 0.0416*color.Z; + Blinear = 0.0556*color.X - 0.2040*color.Y + 1.0570*color.Z; + + /* + * If C represents R, G, and B, then the sRGB values are now found as follows: + * + * { 12.92*Clinear, Clinear <= 0.0031308 + * Csrgb = { 1/2.4 + * { (1.055)*Clinear - 0.055, Clinear > 0.0031308 + */ + + if (Rlinear <= 0.0031308) { + R = 12.92*Rlinear; + } else { + R = 1.055*pow(Rlinear, 1.0/2.4) - 0.055; + } + + if (Glinear <= 0.0031308) { + G = 12.92*Glinear; + } else { + G = 1.055*pow(Glinear, 1.0/2.4) - 0.055; + } + + if (Blinear <= 0.0031308) { + B = 12.92*Blinear; + } else { + B = 1.055*pow(Blinear, 1.0/2.4) - 0.055; + } + + /* Now we go from unlimited to limited light, saturating at UINT16_MAX */ + + if (R < 0) { + pixel.r = 0; + } else if (R > 1) { + pixel.r = UINT16_MAX; + } else { + pixel.r = UINT16_MAX*R; + } + + if (G < 0) { + pixel.g = 0; + } else if (G > 1) { + pixel.g = UINT16_MAX; + } else { + pixel.g = UINT16_MAX*G; + } + + if (B < 0) { + pixel.b = 0; + } else if (B > 1) { + pixel.b = UINT16_MAX; + } else { + pixel.b = UINT16_MAX*B; + } + + if (color.alpha < 0) { + pixel.a = 0; + } else if (color.alpha > 1) { + pixel.a = UINT16_MAX; + } else { + pixel.a = UINT16_MAX*color.alpha; + } + + if (color.trans < 0) { + pixel.t = 0; + } else if (color.trans > 1) { + pixel.t = UINT16_MAX; + } else { + pixel.t = UINT16_MAX*color.trans; + } + + return pixel; +} + +dmnsn_color +dmnsn_color_from_pixel(dmnsn_pixel pixel) +{ + double R, G, B; /* sRGB values */ + double Rlinear, Glinear, Blinear; /* Linear RGB values - no gamma */ + dmnsn_color color; + + /* Conversion back to unlimited light */ + R = ((double)pixel.r)/UINT16_MAX; + G = ((double)pixel.g)/UINT16_MAX; + B = ((double)pixel.b)/UINT16_MAX; + + /* + * If C represents R, G, and B, then the Clinear values are now found as + * follows: + * + * { Csrgb/12.92, Csrgb <= 0.04045 + * Clinear = { 1/2.4 + * { ((Csrgb + 0.055)/1.055) , Csrgb > 0.04045 + */ + + if (R <= 0.04045) { + Rlinear = R/19.92; + } else { + Rlinear = pow((R + 0.055)/1.055, 2.4); + } + + if (G <= 0.04045) { + Glinear = G/19.92; + } else { + Glinear = pow((G + 0.055)/1.055, 2.4); + } + + if (B <= 0.04045) { + Blinear = B/19.92; + } else { + Blinear = pow((B + 0.055)/1.055, 2.4); + } + + /* + * Now, the linear conversion. Expressed as matrix multiplication, it looks + * like this: + * + * [X] [0.4124 0.3576 0.1805] [Rlinear] + * [Y] = [0.2126 0.7152 0.0722]*[Glinear] + * [X] [0.0193 0.1192 0.9505] [Blinear] + */ + + color.X = 0.4124*Rlinear + 0.3576*Glinear + 0.1805*Blinear; + color.Y = 0.2126*Rlinear + 0.7152*Glinear + 0.0722*Blinear; + color.Z = 0.0193*Rlinear + 0.1192*Glinear + 0.9505*Blinear; + + color.alpha = ((double)pixel.a)/UINT16_MAX; + color.trans = ((double)pixel.t)/UINT16_MAX; + + return color; +} + +dmnsn_canvas * +dmnsn_new_canvas(unsigned int x, unsigned int y) +{ + dmnsn_canvas *canvas = malloc(sizeof(dmnsn_canvas)); + + if (canvas) { + canvas->x = x; + canvas->y = y; + canvas->pixels = malloc(sizeof(dmnsn_pixel)*x*y); + + if (canvas->pixels) { + return canvas; + } else { + free(canvas); + return NULL; + } + } else { + return NULL; + } +} + +void +dmnsn_delete_canvas(dmnsn_canvas *canvas) +{ + if (canvas) { + free(canvas->pixels); + free(canvas); + } +} diff --git a/libdimension/dimension.h b/libdimension/dimension.h new file mode 100644 index 0000000..558c9ed --- /dev/null +++ b/libdimension/dimension.h @@ -0,0 +1,39 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> * + * * + * This file is part of Dimension. * + * * + * Dimension is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * Dimension is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +#ifndef DIMENSION_H +#define DIMENSION_H + +#include <stdbool.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <dimension/geometry.h> +#include <dimension/color.h> +#include <dimension/canvas.h> + +#ifdef __cplusplus +} +#endif + +#endif /* DIMENSION_H */ diff --git a/libdimension/dimension/canvas.h b/libdimension/dimension/canvas.h new file mode 100644 index 0000000..251c64a --- /dev/null +++ b/libdimension/dimension/canvas.h @@ -0,0 +1,50 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> * + * * + * This file is part of Dimension. * + * * + * Dimension is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * Dimension is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/* + * A canvas which is rendered to. + */ + +#ifndef DIMENSION_CANVAS_H +#define DIMENSION_CANVAS_H + +/* 48-bit sRGB color for pixels. */ +typedef struct { + uint16_t r, g, b; + uint16_t a, t; +} dmnsn_pixel; + +dmnsn_pixel dmnsn_pixel_from_color(dmnsn_color color); +dmnsn_color dmnsn_color_from_pixel(dmnsn_pixel pixel); + +typedef struct { + unsigned int x, y; + + /* + * Stored in first-quadrant representation (origin is bottom-left). The pixel + * at (a,b) is accessible as pixels[b*x + a]. + */ + dmnsn_pixel *pixels; +} dmnsn_canvas; + +dmnsn_canvas *dmnsn_new_canvas(unsigned int x, unsigned int y); +void dmnsn_delete_canvas(dmnsn_canvas *canvas); + +#endif /* DIMENSION_CANVAS_H */ diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h new file mode 100644 index 0000000..1f4a42e --- /dev/null +++ b/libdimension/dimension/color.h @@ -0,0 +1,46 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> * + * * + * This file is part of Dimension. * + * * + * Dimension is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * Dimension is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/* + * Types to represent color. + */ + +#ifndef DIMENSION_COLOR_H +#define DIMENSION_COLOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* CIE 1931 XYZ color. */ +typedef struct { + double X, Y, Z; /* X, Y, and Z are the tristimulus values of a color in CIE + 1931 XYZ color space. We use an unlimited light model + here, where the range of X, Y, and Z are unbounded >= 0. */ + double alpha, trans; /* Alpha transparancy only lets light of this color + through; regular transparancy lets all colors + through */ +} dmnsn_color; + +#ifdef __cplusplus +} +#endif + +#endif /* DIMENSION_COLOR_H */ diff --git a/libdimension/dimension/geometry.h b/libdimension/dimension/geometry.h new file mode 100644 index 0000000..2c0c204 --- /dev/null +++ b/libdimension/dimension/geometry.h @@ -0,0 +1,92 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> * + * * + * This file is part of Dimension. * + * * + * Dimension is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * Dimension is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/* + * Core geometric types like scalars, vectors, and rays. + */ + +#ifndef DIMENSION_GEOMETRY_H +#define DIMENSION_GEOMETRY_H + +/* Scalar and vector types. */ +typedef double dmnsn_scalar; +typedef struct { dmnsn_scalar x, y, z; } dmnsn_vector; + +/* Vector arithmetic */ + +inline dmnsn_vector +dmnsn_vector_construct(dmnsn_scalar x, dmnsn_scalar y, dmnsn_scalar z) +{ + dmnsn_vector v = { .x = x, .y = y, .z = z }; + return v; +} + +inline dmnsn_vector +dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs) +{ + return dmnsn_vector_construct(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); +} + +inline dmnsn_vector +dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs) +{ + return dmnsn_vector_construct(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); +} + +inline dmnsn_vector +dmnsn_vector_mul(dmnsn_scalar lhs, dmnsn_vector rhs) +{ + return dmnsn_vector_construct(lhs*rhs.x, lhs*rhs.y, lhs*rhs.z); +} + +inline dmnsn_vector +dmnsn_vector_div(dmnsn_vector lhs, dmnsn_scalar rhs) +{ + return dmnsn_vector_construct(lhs.x/rhs, lhs.y/rhs, lhs.z/rhs); +} + +inline dmnsn_scalar +dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs) +{ + return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z; +} + +inline dmnsn_vector +dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs) +{ + return dmnsn_vector_construct(lhs.y*rhs.z - lhs.z*rhs.y, + lhs.z*rhs.x - lhs.x*rhs.z, + lhs.x*rhs.y - lhs.y*rhs.x); +} + +/* A line, or ray. */ +typedef struct { + dmnsn_vector x0; /* A point on the line */ + dmnsn_vector n; /* A normal vector; the direction of the line */ +} dmnsn_line; + +/* A point on a line, defined by x0 + t*n */ +inline dmnsn_vector +dmnsn_line_point(dmnsn_line l, dmnsn_scalar t) +{ + return dmnsn_vector_add(l.x0, dmnsn_vector_mul(t, l.n)); +} + +#endif /* DIMENSION_GEOMETRY_H */ |