coloritto, spectral color asset manager

parents
coloritto: *.c
gcc *.c -o coloritto -lm `pkg-config mrg babl --cflags --libs`
clean:
rm coloritto
color/pigment management named after J.C. le Blon an early
inventor/experimentor with 4 color process, of what fundamentally Cyan Magenta
Yellow Key / Blue Yellow Red Key among other books in his coloritto
from 1426, an alternate name from leblon can be coloritto.
it is a color inventory the records and spatiallly visualises known colors
in 3d.
It consumes colors from cxf files and other file formats, re-using python code
from swatchbooker and integrating with zn from python.
it permits exporting sets as searched for by tags and then to export
CxF-4 sets as cxf files.
a 3d rendered color swatch explorer with varying size for quality of
measurement from just coordinates through spectral single samples through
spectral opacity measurements with export to CxF-4.
/*
* Copyright (c) 2014 Øyvind Kolås <pippin@hodefoting.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "mrg.h"
#include <babl/babl.h>
/*
rotation
3d
switch view space
lab / lch
xyz
rgb + chromaticities
NCS?
load icc profile for display
load an image
a color alcyymist studio
an indexed of spectral samples or materials to impact a surface with,
on CIE Lab / Lch providing access to spectral defintions of an ink or
paints impact as well as per wavelength opacity.
create an order to paint
substrate is important
painting black and whiteish first is good, since it is composition
proof
separate
separate+proof
also permit to build additive models
*/
typedef struct
Space_Item {
float x;
float y;
float z;
float sx;
float sy;
float radius;
float rgb[3];
} SpaceItem;
MrgList *items = NULL;
static void scroll_cb (MrgEvent *event, void *data1, void *data2)
{
fprintf (stderr, "foo %s\n", event->scroll_direction?"down":"up");
}
#define SCALEX 500.0
#define SCALEY 500.0
static void add_item (float x, float y, float z,
float radius,
float rgb[3])
{
SpaceItem *item = calloc (sizeof (SpaceItem), 1);
float sx = y/SCALEX+0.5;
float sy = z/SCALEY+0.5;
item->x = x;
item->y = y;
item->z = z;
item->sx = sx;
item->sy = sy;
item->rgb[0] = rgb[0];
item->rgb[1] = rgb[1];
item->rgb[2] = rgb[2];
item->radius = radius;
mrg_list_prepend (&items, item);
}
static void xyz_to_xy (float x, float y, float z, float *sx, float *sy)
{
/* */
/* */
}
static void add_items ()
{
float xyz[3];
float rgb[3];
float lab[3];
#if 0
for (rgb[0] = 0.0; rgb[0] <= 1.0; rgb[0] += 0.1)
for (rgb[1] = 0.0; rgb[1] <= 1.0; rgb[1] += 0.1)
for (rgb[2] = 0.0; rgb[2] <= 1.0; rgb[2] += 0.1)
{
babl_process (babl_fish (babl_format ("RGB float"), babl_format ("CIE Lab float")), rgb, lab, 1);
add_item (lab[0],lab[1],lab[2],
0.01, rgb);
}
#endif
#if 0
for (xyz[0] = 0.0; xyz[0] <= 1.0; xyz[0] += 0.1)
for (xyz[1] = 0.0; xyz[1] <= 1.0; xyz[1] += 0.1)
for (xyz[2] = 0.0; xyz[2] <= 1.0; xyz[2] += 0.1)
{
babl_process (babl_fish (babl_format ("CIE XYZ float"), babl_format ("CIE Lab float")), xyz, lab, 1);
babl_process (babl_fish (babl_format ("CIE XYZ float"), babl_format ("R'G'B' float")), xyz, rgb, 1);
add_item (lab[0],lab[1],lab[2],
0.01, rgb);
}
#endif
#if 1
lab[1] = 0.0;
lab[2] = 0.0;
for (lab[0] = 0.0; lab[0] <= 100.0; lab[0] += 10.0)
{
babl_process (babl_fish (babl_format ("CIE Lab float"), babl_format ("R'G'B' float")), lab, rgb, 1);
add_item (lab[0],lab[1],lab[2],
0.01, rgb);
}
#if 1
lab[0] = 0.0;
for (lab[1] = -150.0; lab[1] <= 150.0; lab[1] += 10.0)
for (lab[2] = -150.0; lab[2] <= 150.0; lab[2] += 10.0)
{
babl_process (babl_fish (babl_format ("CIE Lab float"), babl_format ("R'G'B' float")), lab, rgb, 1);
add_item (lab[0],lab[1],lab[2],
0.005, rgb);
}
#endif
#endif
}
static void update_projection ()
{
/* here 3d projection and rotation can be incorporated */
for (MrgList *l = items; l; l = l->next)
{
SpaceItem *item = l->data;
item->sx = item->y/SCALEX+0.5 + item->x / SCALEX;
item->sy = item->z/SCALEY+0.5 + item->x / SCALEY;
}
}
static void draw_items (Mrg *mrg)
{
float w = mrg_width (mrg);
float h = mrg_height (mrg);
cairo_t *cr = mrg_cr (mrg);
for (MrgList *l = items; l; l = l->next)
{
SpaceItem *item = l->data;
cairo_arc (cr, item->sx * h + (w - h) / 2, item->sy * h,
item->radius * h, 0.0, M_PI * 2);
cairo_set_source_rgb (cr, item->rgb[0], item->rgb[1], item->rgb[2]);
cairo_fill (cr);
}
}
static void ui (Mrg *mrg, void *data)
{
float w = mrg_width (mrg);
float h = mrg_height (mrg);
cairo_t *cr = mrg_cr (mrg);
cairo_set_source_rgb (cr, .5, .5, .5);
cairo_paint (cr); /* todo: use a form of structured noise here */
update_projection ();
draw_items (mrg);
mrg_text_listen (mrg, MRG_SCROLL, scroll_cb, NULL, NULL);
mrg_print (mrg, "scroll me");
mrg_text_listen_done (mrg);
mrg_add_binding (mrg, "control-q", NULL, NULL, mrg_quit_cb, NULL);
}
/* validate rgb/lab mappings in read cxf files when parsing to validate
* our code
*/
int main (int argc, char **argv)
{
Mrg *mrg = mrg_new (640, 480, NULL);
babl_init ();
//Mrg *mrg = mrg_new (-1, -1, NULL);
add_items ();
mrg_set_ui (mrg, ui, NULL);
mrg_main (mrg);
return 0;
}
#include "luz-xml.h"
#include <string.h>
#include <stdlib.h>
static int
file_get_contents (const char *path,
char **contents,
long *length)
{
FILE *file;
long size;
long remaining;
char *buffer;
file = fopen (path, "rb");
if (!file)
return -1;
fseek (file, 0, SEEK_END);
*length = size = remaining = ftell (file);
rewind (file);
buffer = malloc(size + 8);
if (!buffer)
{
fclose(file);
return -1;
}
remaining -= fread (buffer, 1, remaining, file);
if (remaining)
{
fclose (file);
free (buffer);
return -1;
}
fclose (file);
*contents = buffer;
buffer[size] = 0;
return 0;
}
int dump_cxf_main (int argc, char **argv)
{
char *contents = NULL;
int pos = 0;
long length;
LuzXml *xmltok;
int type = t_none;
file_get_contents (argv[1], &contents, &length);
xmltok = xmltok_buf_new (contents);
while (type != t_eof)
{
char *data = NULL;
type = xmltok_get (xmltok, &data, &pos);
switch (type)
{
case t_entity:
{
fprintf (stderr, "ent: %s\n", data);
}
break;
case t_word:
case t_whitespace:
{
fprintf (stderr, "%s", data);
}
break;
case t_tag:
{
fprintf (stderr, " tag:%s", data);
}
break;
case t_att:
{
fprintf (stderr, " att:%s", data);
}
break;
case t_val:
{
fprintf (stderr, " val:%s", data);
}
break;
}
}
return 0;
}
This diff is collapsed.
/* luz - MicroRaptor Gui
* Copyright (c) 2014 Øyvind Kolås <pippin@hodefoting.com>
*
* This library 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 2 of the License, or (at your option) any later version.
*
* This library 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 library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "luz-string.h"
#include "luz-utf8.h"
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void luz_string_init (LuzString *string, int initial_size)
{
string->allocated_length = initial_size;
string->length = 0;
string->utf8_length = 0;
string->str = malloc (string->allocated_length);
string->str[0]='\0';
}
static void luz_string_destroy (LuzString *string)
{
if (string->str)
{
free (string->str);
string->str = NULL;
}
}
void luz_string_clear (LuzString *string)
{
string->length = 0;
string->utf8_length = 0;
string->str[string->length]=0;
}
static inline void _luz_string_append_byte (LuzString *string, char val)
{
if ((val & 0xC0) != 0x80)
string->utf8_length++;
if (string->length + 1 >= string->allocated_length)
{
char *old = string->str;
string->allocated_length *= 2;
string->str = malloc (string->allocated_length);
memcpy (string->str, old, string->allocated_length/2);
free (old);
}
string->str[string->length++] = val;
string->str[string->length] = '\0';
}
void luz_string_append_byte (LuzString *string, char val)
{
_luz_string_append_byte (string, val);
}
void luz_string_append_unichar (LuzString *string, unsigned int unichar)
{
char *str;
char utf8[5];
utf8[luz_unichar_to_utf8 (unichar, (unsigned char*)utf8)]=0;
str = utf8;
while (str && *str)
{
_luz_string_append_byte (string, *str);
str++;
}
}
static inline void _luz_string_append_str (LuzString *string, const char *str)
{
if (!str) return;
while (*str)
{
_luz_string_append_byte (string, *str);
str++;
}
}
void luz_string_append_str (LuzString *string, const char *str)
{
_luz_string_append_str (string, str);
}
LuzString *luz_string_new_with_size (const char *initial, int initial_size)
{
LuzString *string = calloc (sizeof (LuzString), 1);
luz_string_init (string, initial_size);
if (initial)
_luz_string_append_str (string, initial);
return string;
}
LuzString *luz_string_new (const char *initial)
{
return luz_string_new_with_size (initial, 8);
}
void luz_string_append_data (LuzString *string, const char *str, int len)
{
int i;
for (i = 0; i<len; i++)
_luz_string_append_byte (string, str[i]);
}
void luz_string_append_string (LuzString *string, LuzString *string2)
{
const char *str = luz_string_get (string2);
while (str && *str)
{
_luz_string_append_byte (string, *str);
str++;
}
}
const char *luz_string_get (LuzString *string)
{
return string->str;
}
int luz_string_get_length (LuzString *string)
{
return string->length;
}
/* dissolving a string, means destroying it, but returning
* the string, that should be manually freed.
*/
char *luz_string_dissolve (LuzString *string)
{
char *ret = string->str;
string->str = NULL;
free (string);
return ret;
}
void
luz_string_free (LuzString *string, int freealloc)
{
if (freealloc)
{
luz_string_destroy (string);
}
free (string);
}
void
luz_string_append_printf (LuzString *string, const char *format, ...)
{
va_list ap;
size_t needed;
char *buffer;
va_start(ap, format);
needed = vsnprintf(NULL, 0, format, ap) + 1;
buffer = malloc(needed);
va_end (ap);
va_start(ap, format);
vsnprintf(buffer, needed, format, ap);
va_end (ap);
_luz_string_append_str (string, buffer);
free (buffer);
}
void
luz_string_set (LuzString *string, const char *new_string)
{
luz_string_clear (string);
_luz_string_append_str (string, new_string);
}
#if 0
#include "luz-list.h"
static LuzList *interns = NULL;
const char * luz_intern_string (const char *str)
{
LuzList *i;
for (i = interns; i; i = i->next)
{
if (!strcmp (i->data, str))
return i->data;
}
str = strdup (str);
luz_list_append (&interns, (void*)str);
return str;
}
#endif
void luz_string_replace_utf8 (LuzString *string, int pos, const char *new_glyph)
{
int new_len = luz_utf8_len (*new_glyph);
int old_len = string->utf8_length;
char tmpg[3]=" ";
if (new_len <= 1 && new_glyph[0] < 32)
{
tmpg[0]=new_glyph[0]+64;
new_glyph = tmpg;
}
if (pos == old_len)
{
_luz_string_append_str (string, new_glyph);
return;
}
{
for (int i = old_len; i <= pos; i++)
{
_luz_string_append_byte (string, ' ');
old_len++;
}
}
if (string->length + new_len > string->allocated_length)
{
char *tmp;
char *defer;
string->allocated_length = string->length + new_len;
tmp = calloc (string->allocated_length, 1);
strcpy (tmp, string->str);
defer = string->str;
string->str = tmp;
free (defer);
}
char *p = (void*)luz_utf8_skip (string->str, pos);
int prev_len = luz_utf8_len (*p);
char *rest;
if (*p == 0 || *(p+prev_len) == 0)
{
rest = strdup("");
}
else
{
rest = strdup (p + prev_len);
}
memcpy (p, new_glyph, new_len);
memcpy (p + new_len, rest, strlen (rest) + 1);
string->length += new_len;
string->length -= prev_len;
free (rest);
string->utf8_length = luz_utf8_strlen (string->str);
}
void luz_string_insert_utf8 (LuzString *string, int pos, const char *new_glyph)
{
int new_len = luz_utf8_len (*new_glyph);
int old_len = string->utf8_length;
char tmpg[3]=" ";
if (new_len <= 1 && new_glyph[0] < 32)
{
tmpg[0]=new_glyph[0]+64;
new_glyph = tmpg;
}
if (pos == old_len)
{
_luz_string_append_str (string, new_glyph);
return;
}
{
for (int i = old_len; i <= pos; i++)
{
_luz_string_append_byte (string, ' ');
old_len++;
}
}
if (string->length + new_len + 1 > string->allocated_length)
{
char *tmp;
char *defer;
string->allocated_length = string->length + new_len + 1;
tmp = calloc (string->allocated_length, 1);
strcpy (tmp, string->str);
defer = string->str;
string->str = tmp;
free (defer);
}
char *p = (void*)luz_utf8_skip (string->str, pos);
int prev_len = luz_utf8_len (*p);
char *rest;
if (*p == 0 || *(p+prev_len) == 0)
{
rest = strdup("");
}
else
{
rest = strdup (p);
}
memcpy (p, new_glyph, new_len);
memcpy (p + new_len, rest, strlen (rest) + 1);
string->length += new_len;
free (rest);
string->utf8_length = luz_utf8_strlen (string->str);
}
int luz_string_get_utf8_length (LuzString *string)
{
//return luz_utf8_strlen (string->str);
return string->utf8_length;
}
void luz_string_remove_utf8 (LuzString *string, int pos)
{
int old_len = string->utf8_length;
{
for (int i = old_len; i <= pos; i++)
{
_luz_string_append_byte (string, ' ');
old_len++;
}
}
char *p = (void*)luz_utf8_skip (string->str, pos);
int prev_len = luz_utf8_len (*p);
char *rest;
if (*p == 0 || *(p+prev_len) == 0)
{
rest = strdup("");
}
else
{
rest = strdup (p + prev_len);
}
memcpy (p, rest, strlen (rest) + 1);
string->length -= prev_len;
free (rest);
string->utf8_length = luz_utf8_strlen (string->str);
}
/* luz - MicroRaptor Gui
* Copyright (c) 2014 Øyvind Kolås <pippin@hodefoting.com>
*
* This library 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 2 of the License, or (at your option) any later version.
*
* This library 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 library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LUZ_STRING_H
#define LUZ_STRING_H
#include "luz-utf8.h"
typedef struct _LuzString LuzString;
struct _LuzString
{
char *str;
int length;
int utf8_length;
int allocated_length;
} __attribute((packed));
LuzString *luz_string_new_with_size (const char *initial, int initial_size);
LuzString *luz_string_new (const char *initial);
void luz_string_free (LuzString *string, int freealloc);
char *luz_string_dissolve (LuzString *string);
const char *luz_string_get (LuzString *string);
int luz_string_get_length (LuzString *string);
int luz_string_get_utf8_length (LuzString *string);
void luz_string_set (LuzString *string, const char *new_string);
void luz_string_clear (LuzString *