Initial checkin of Pika from heckimp
This commit is contained in:
32
libpikacolor/Makefile.gi
Normal file
32
libpikacolor/Makefile.gi
Normal file
@ -0,0 +1,32 @@
|
||||
# Introspectable sources for libpikacolor
|
||||
|
||||
libpikacolor_introspectable_headers = \
|
||||
../libpikacolor/pikacolortypes.h \
|
||||
../libpikacolor/pikaadaptivesupersample.h \
|
||||
../libpikacolor/pikabilinear.h \
|
||||
../libpikacolor/pikacairo.h \
|
||||
../libpikacolor/pikacmyk.h \
|
||||
../libpikacolor/pikacolormanaged.h \
|
||||
../libpikacolor/pikacolorprofile.h \
|
||||
../libpikacolor/pikacolorspace.h \
|
||||
../libpikacolor/pikacolortransform.h \
|
||||
../libpikacolor/pikahsl.h \
|
||||
../libpikacolor/pikahsv.h \
|
||||
../libpikacolor/pikapixbuf.h \
|
||||
../libpikacolor/pikargb.h
|
||||
|
||||
libpikacolor_introspectable = \
|
||||
../libpikacolor/pikaadaptivesupersample.c \
|
||||
../libpikacolor/pikabilinear.c \
|
||||
../libpikacolor/pikacairo.c \
|
||||
../libpikacolor/pikacmyk.c \
|
||||
../libpikacolor/pikacolormanaged.c \
|
||||
../libpikacolor/pikacolorprofile.c \
|
||||
../libpikacolor/pikacolorspace.c \
|
||||
../libpikacolor/pikacolortransform.c \
|
||||
../libpikacolor/pikahsl.c \
|
||||
../libpikacolor/pikahsv.c \
|
||||
../libpikacolor/pikapixbuf.c \
|
||||
../libpikacolor/pikargb.c \
|
||||
../libpikacolor/pikargb-parse.c \
|
||||
$(libpikacolor_introspectable_headers)
|
76
libpikacolor/meson.build
Normal file
76
libpikacolor/meson.build
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
libpikacolor_sources = files(
|
||||
'pikaadaptivesupersample.c',
|
||||
'pikabilinear.c',
|
||||
'pikacairo.c',
|
||||
'pikacmyk.c',
|
||||
'pikacolormanaged.c',
|
||||
'pikacolorprofile.c',
|
||||
'pikacolorspace.c',
|
||||
'pikacolortransform.c',
|
||||
'pikahsl.c',
|
||||
'pikahsv.c',
|
||||
'pikapixbuf.c',
|
||||
'pikargb-parse.c',
|
||||
'pikargb.c',
|
||||
)
|
||||
|
||||
libpikacolor_headers_introspectable = files(
|
||||
'pikacolortypes.h',
|
||||
'pikaadaptivesupersample.h',
|
||||
'pikabilinear.h',
|
||||
'pikacairo.h',
|
||||
'pikacmyk.h',
|
||||
'pikacolormanaged.h',
|
||||
'pikacolorprofile.h',
|
||||
'pikacolorspace.h',
|
||||
'pikacolortransform.h',
|
||||
'pikahsl.h',
|
||||
'pikahsv.h',
|
||||
'pikapixbuf.h',
|
||||
'pikargb.h',
|
||||
)
|
||||
|
||||
libpikacolor_headers = [
|
||||
libpikacolor_headers_introspectable,
|
||||
'pikacolor.h',
|
||||
]
|
||||
|
||||
libpikacolor_introspectable = [
|
||||
libpikacolor_sources,
|
||||
libpikacolor_headers_introspectable,
|
||||
]
|
||||
|
||||
|
||||
libpikacolor = library('pikacolor-' + pika_api_version,
|
||||
libpikacolor_sources,
|
||||
include_directories: rootInclude,
|
||||
dependencies: [
|
||||
cairo, gdk_pixbuf, gegl, lcms, math,
|
||||
],
|
||||
c_args: [ '-DG_LOG_DOMAIN="LibPikaColor"', '-DPIKA_COLOR_COMPILATION', ],
|
||||
link_with: [ libpikabase, ],
|
||||
vs_module_defs: 'pikacolor.def',
|
||||
install: true,
|
||||
version: so_version,
|
||||
)
|
||||
|
||||
install_headers(
|
||||
libpikacolor_headers,
|
||||
subdir: pika_api_name / 'libpikacolor',
|
||||
)
|
||||
|
||||
|
||||
# Test program, not installed
|
||||
executable('test-color-parser',
|
||||
'test-color-parser.c',
|
||||
include_directories: rootInclude,
|
||||
dependencies: [
|
||||
cairo, gdk_pixbuf, gegl, lcms, math,
|
||||
babl,
|
||||
# glib,
|
||||
],
|
||||
c_args: '-DG_LOG_DOMAIN="LibPikaColor"',
|
||||
link_with: [ libpikabase, libpikacolor, ],
|
||||
install: false,
|
||||
)
|
414
libpikacolor/pikaadaptivesupersample.c
Normal file
414
libpikacolor/pikaadaptivesupersample.c
Normal file
@ -0,0 +1,414 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikaadaptivesupersample.h"
|
||||
#include "pikargb.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikaadaptivesupersample
|
||||
* @title: PikaAdaptiveSupersample
|
||||
* @short_description: Functions to perform adaptive supersampling on
|
||||
* an area.
|
||||
*
|
||||
* Functions to perform adaptive supersampling on an area.
|
||||
**/
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
/* Sumpersampling code (Quartic) */
|
||||
/* This code is *largely* based on the sources for POV-Ray 3.0. I am */
|
||||
/* grateful to the POV-Team for such a great program and for making */
|
||||
/* their sources available. All comments / bug reports / */
|
||||
/* etc. regarding this code should be addressed to me, not to the */
|
||||
/* POV-Ray team. Any bugs are my responsibility, not theirs. */
|
||||
/*********************************************************************/
|
||||
|
||||
|
||||
typedef struct _PikaSampleType PikaSampleType;
|
||||
|
||||
struct _PikaSampleType
|
||||
{
|
||||
guchar ready;
|
||||
PikaRGB color;
|
||||
};
|
||||
|
||||
|
||||
static gulong
|
||||
pika_render_sub_pixel (gint max_depth,
|
||||
gint depth,
|
||||
PikaSampleType **block,
|
||||
gint x,
|
||||
gint y,
|
||||
gint x1,
|
||||
gint y1,
|
||||
gint x3,
|
||||
gint y3,
|
||||
gdouble threshold,
|
||||
gint sub_pixel_size,
|
||||
PikaRGB *color,
|
||||
PikaRenderFunc render_func,
|
||||
gpointer render_data)
|
||||
{
|
||||
gint x2, y2; /* Coords of center sample */
|
||||
gdouble dx1, dy1; /* Delta to upper left sample */
|
||||
gdouble dx3, dy3; /* Delta to lower right sample */
|
||||
PikaRGB c[4]; /* Sample colors */
|
||||
gulong num_samples = 0;
|
||||
gint cnt;
|
||||
|
||||
g_return_val_if_fail (render_func != NULL, 0);
|
||||
|
||||
/* Get offsets for corners */
|
||||
|
||||
dx1 = (gdouble) (x1 - sub_pixel_size / 2) / sub_pixel_size;
|
||||
dx3 = (gdouble) (x3 - sub_pixel_size / 2) / sub_pixel_size;
|
||||
|
||||
dy1 = (gdouble) (y1 - sub_pixel_size / 2) / sub_pixel_size;
|
||||
dy3 = (gdouble) (y3 - sub_pixel_size / 2) / sub_pixel_size;
|
||||
|
||||
/* Render upper left sample */
|
||||
|
||||
if (! block[y1][x1].ready)
|
||||
{
|
||||
num_samples++;
|
||||
|
||||
render_func (x + dx1, y + dy1, &c[0], render_data);
|
||||
|
||||
block[y1][x1].ready = TRUE;
|
||||
block[y1][x1].color = c[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
c[0] = block[y1][x1].color;
|
||||
}
|
||||
|
||||
/* Render upper right sample */
|
||||
|
||||
if (! block[y1][x3].ready)
|
||||
{
|
||||
num_samples++;
|
||||
|
||||
render_func (x + dx3, y + dy1, &c[1], render_data);
|
||||
|
||||
block[y1][x3].ready = TRUE;
|
||||
block[y1][x3].color = c[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
c[1] = block[y1][x3].color;
|
||||
}
|
||||
|
||||
/* Render lower left sample */
|
||||
|
||||
if (! block[y3][x1].ready)
|
||||
{
|
||||
num_samples++;
|
||||
|
||||
render_func (x + dx1, y + dy3, &c[2], render_data);
|
||||
|
||||
block[y3][x1].ready = TRUE;
|
||||
block[y3][x1].color = c[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
c[2] = block[y3][x1].color;
|
||||
}
|
||||
|
||||
/* Render lower right sample */
|
||||
|
||||
if (! block[y3][x3].ready)
|
||||
{
|
||||
num_samples++;
|
||||
|
||||
render_func (x + dx3, y + dy3, &c[3], render_data);
|
||||
|
||||
block[y3][x3].ready = TRUE;
|
||||
block[y3][x3].color = c[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
c[3] = block[y3][x3].color;
|
||||
}
|
||||
|
||||
/* Check for supersampling */
|
||||
|
||||
if (depth <= max_depth)
|
||||
{
|
||||
/* Check whether we have to supersample */
|
||||
|
||||
if ((pika_rgba_distance (&c[0], &c[1]) >= threshold) ||
|
||||
(pika_rgba_distance (&c[0], &c[2]) >= threshold) ||
|
||||
(pika_rgba_distance (&c[0], &c[3]) >= threshold) ||
|
||||
(pika_rgba_distance (&c[1], &c[2]) >= threshold) ||
|
||||
(pika_rgba_distance (&c[1], &c[3]) >= threshold) ||
|
||||
(pika_rgba_distance (&c[2], &c[3]) >= threshold))
|
||||
{
|
||||
/* Calc coordinates of center subsample */
|
||||
|
||||
x2 = (x1 + x3) / 2;
|
||||
y2 = (y1 + y3) / 2;
|
||||
|
||||
/* Render sub-blocks */
|
||||
|
||||
num_samples += pika_render_sub_pixel (max_depth, depth + 1, block,
|
||||
x, y, x1, y1, x2, y2,
|
||||
threshold, sub_pixel_size,
|
||||
&c[0],
|
||||
render_func, render_data);
|
||||
|
||||
num_samples += pika_render_sub_pixel (max_depth, depth + 1, block,
|
||||
x, y, x2, y1, x3, y2,
|
||||
threshold, sub_pixel_size,
|
||||
&c[1],
|
||||
render_func, render_data);
|
||||
|
||||
num_samples += pika_render_sub_pixel (max_depth, depth + 1, block,
|
||||
x, y, x1, y2, x2, y3,
|
||||
threshold, sub_pixel_size,
|
||||
&c[2],
|
||||
render_func, render_data);
|
||||
|
||||
num_samples += pika_render_sub_pixel (max_depth, depth + 1, block,
|
||||
x, y, x2, y2, x3, y3,
|
||||
threshold, sub_pixel_size,
|
||||
&c[3],
|
||||
render_func, render_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (c[0].a == 0.0 || c[1].a == 0.0 || c[2].a == 0.0 || c[3].a == 0.0)
|
||||
{
|
||||
PikaRGB tmpcol;
|
||||
gdouble weight;
|
||||
|
||||
pika_rgb_set (&tmpcol, 0.0, 0.0, 0.0);
|
||||
|
||||
weight = 2.0;
|
||||
|
||||
for (cnt = 0; cnt < 4; cnt++)
|
||||
{
|
||||
if (c[cnt].a != 0.0)
|
||||
{
|
||||
tmpcol.r += c[cnt].r;
|
||||
tmpcol.g += c[cnt].g;
|
||||
tmpcol.b += c[cnt].b;
|
||||
|
||||
weight /= 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
color->r = weight * tmpcol.r;
|
||||
color->g = weight * tmpcol.g;
|
||||
color->b = weight * tmpcol.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
color->r = 0.25 * (c[0].r + c[1].r + c[2].r + c[3].r);
|
||||
color->g = 0.25 * (c[0].g + c[1].g + c[2].g + c[3].g);
|
||||
color->b = 0.25 * (c[0].b + c[1].b + c[2].b + c[3].b);
|
||||
}
|
||||
|
||||
color->a = 0.25 * (c[0].a + c[1].a + c[2].a + c[3].a);
|
||||
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_adaptive_supersample_area:
|
||||
* @x1: left x coordinate of the area to process.
|
||||
* @y1: top y coordinate of the area to process.
|
||||
* @x2: right x coordinate of the area to process.
|
||||
* @y2: bottom y coordinate of the area to process.
|
||||
* @max_depth: maximum depth of supersampling.
|
||||
* @threshold: lower threshold of pixel difference that stops
|
||||
* supersampling.
|
||||
* @render_func: (scope call): function calculate the color value at
|
||||
* given coordinates.
|
||||
* @render_data: user data passed to @render_func.
|
||||
* @put_pixel_func: (scope call): function to a pixels to a color at
|
||||
* given coordinates.
|
||||
* @put_pixel_data: user data passed to @put_pixel_func.
|
||||
* @progress_func: (scope call): function to report progress.
|
||||
* @progress_data: user data passed to @progress_func.
|
||||
*
|
||||
* Returns: the number of pixels processed.
|
||||
**/
|
||||
gulong
|
||||
pika_adaptive_supersample_area (gint x1,
|
||||
gint y1,
|
||||
gint x2,
|
||||
gint y2,
|
||||
gint max_depth,
|
||||
gdouble threshold,
|
||||
PikaRenderFunc render_func,
|
||||
gpointer render_data,
|
||||
PikaPutPixelFunc put_pixel_func,
|
||||
gpointer put_pixel_data,
|
||||
PikaProgressFunc progress_func,
|
||||
gpointer progress_data)
|
||||
{
|
||||
gint x, y, width; /* Counters, width of region */
|
||||
gint xt, xtt, yt; /* Temporary counters */
|
||||
gint sub_pixel_size; /* Number of samples per pixel (1D) */
|
||||
PikaRGB color; /* Rendered pixel's color */
|
||||
PikaSampleType tmp_sample; /* For swapping samples */
|
||||
PikaSampleType *top_row, *bot_row, *tmp_row; /* Sample rows */
|
||||
PikaSampleType **block; /* Sample block matrix */
|
||||
gulong num_samples;
|
||||
|
||||
g_return_val_if_fail (render_func != NULL, 0);
|
||||
g_return_val_if_fail (put_pixel_func != NULL, 0);
|
||||
|
||||
/* Initialize color */
|
||||
|
||||
pika_rgba_set (&color, 0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
/* Calculate sub-pixel size */
|
||||
|
||||
sub_pixel_size = 1 << max_depth;
|
||||
|
||||
/* Create row arrays */
|
||||
|
||||
width = x2 - x1 + 1;
|
||||
|
||||
top_row = gegl_scratch_new (PikaSampleType, sub_pixel_size * width + 1);
|
||||
bot_row = gegl_scratch_new (PikaSampleType, sub_pixel_size * width + 1);
|
||||
|
||||
for (x = 0; x < (sub_pixel_size * width + 1); x++)
|
||||
{
|
||||
top_row[x].ready = FALSE;
|
||||
|
||||
pika_rgba_set (&top_row[x].color, 0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
bot_row[x].ready = FALSE;
|
||||
|
||||
pika_rgba_set (&bot_row[x].color, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
/* Allocate block matrix */
|
||||
|
||||
block = gegl_scratch_new (PikaSampleType *, sub_pixel_size + 1); /* Rows */
|
||||
|
||||
for (y = 0; y < (sub_pixel_size + 1); y++)
|
||||
{
|
||||
block[y] = gegl_scratch_new (PikaSampleType, sub_pixel_size + 1); /* Columns */
|
||||
|
||||
for (x = 0; x < (sub_pixel_size + 1); x++)
|
||||
{
|
||||
block[y][x].ready = FALSE;
|
||||
|
||||
pika_rgba_set (&block[y][x].color, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Render region */
|
||||
|
||||
num_samples = 0;
|
||||
|
||||
for (y = y1; y <= y2; y++)
|
||||
{
|
||||
/* Clear the bottom row */
|
||||
|
||||
for (xt = 0; xt < (sub_pixel_size * width + 1); xt++)
|
||||
bot_row[xt].ready = FALSE;
|
||||
|
||||
/* Clear first column */
|
||||
|
||||
for (yt = 0; yt < (sub_pixel_size + 1); yt++)
|
||||
block[yt][0].ready = FALSE;
|
||||
|
||||
/* Render row */
|
||||
|
||||
for (x = x1; x <= x2; x++)
|
||||
{
|
||||
/* Initialize block by clearing all but first row/column */
|
||||
|
||||
for (yt = 1; yt < (sub_pixel_size + 1); yt++)
|
||||
for (xt = 1; xt < (sub_pixel_size + 1); xt++)
|
||||
block[yt][xt].ready = FALSE;
|
||||
|
||||
/* Copy samples from top row to block */
|
||||
|
||||
for (xtt = 0, xt = (x - x1) * sub_pixel_size;
|
||||
xtt < (sub_pixel_size + 1);
|
||||
xtt++, xt++)
|
||||
block[0][xtt] = top_row[xt];
|
||||
|
||||
/* Render pixel on (x, y) */
|
||||
|
||||
num_samples += pika_render_sub_pixel (max_depth, 1, block, x, y, 0, 0,
|
||||
sub_pixel_size, sub_pixel_size,
|
||||
threshold, sub_pixel_size,
|
||||
&color,
|
||||
render_func, render_data);
|
||||
|
||||
if (put_pixel_func)
|
||||
(* put_pixel_func) (x, y, &color, put_pixel_data);
|
||||
|
||||
/* Copy block information to rows */
|
||||
|
||||
top_row[(x - x1 + 1) * sub_pixel_size] = block[0][sub_pixel_size];
|
||||
|
||||
for (xtt = 0, xt = (x - x1) * sub_pixel_size;
|
||||
xtt < (sub_pixel_size + 1);
|
||||
xtt++, xt++)
|
||||
bot_row[xt] = block[sub_pixel_size][xtt];
|
||||
|
||||
/* Swap first and last columns */
|
||||
|
||||
for (yt = 0; yt < (sub_pixel_size + 1); yt++)
|
||||
{
|
||||
tmp_sample = block[yt][0];
|
||||
block[yt][0] = block[yt][sub_pixel_size];
|
||||
block[yt][sub_pixel_size] = tmp_sample;
|
||||
}
|
||||
}
|
||||
|
||||
/* Swap rows */
|
||||
|
||||
tmp_row = top_row;
|
||||
top_row = bot_row;
|
||||
bot_row = tmp_row;
|
||||
|
||||
/* Call progress display function (if any) */
|
||||
|
||||
if (progress_func != NULL)
|
||||
(* progress_func) (y1, y2, y, progress_data);
|
||||
}
|
||||
|
||||
/* Free memory */
|
||||
|
||||
for (y = 0; y < (sub_pixel_size + 1); y++)
|
||||
gegl_scratch_free (block[y]);
|
||||
|
||||
gegl_scratch_free (block);
|
||||
gegl_scratch_free (top_row);
|
||||
gegl_scratch_free (bot_row);
|
||||
|
||||
return num_samples;
|
||||
}
|
82
libpikacolor/pikaadaptivesupersample.h
Normal file
82
libpikacolor/pikaadaptivesupersample.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_ADAPTIVE_SUPERSAMPLE_H__
|
||||
#define __PIKA_ADAPTIVE_SUPERSAMPLE_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
/**
|
||||
* PikaRenderFunc:
|
||||
* @x:
|
||||
* @y:
|
||||
* @color: (out caller-allocates): The rendered pixel as RGB
|
||||
* @data: (closure):
|
||||
*/
|
||||
typedef void (* PikaRenderFunc) (gdouble x,
|
||||
gdouble y,
|
||||
PikaRGB *color,
|
||||
gpointer data);
|
||||
/**
|
||||
* PikaPutPixelFunc:
|
||||
* @x:
|
||||
* @y:
|
||||
* @color:
|
||||
* @data: (closure):
|
||||
*/
|
||||
typedef void (* PikaPutPixelFunc) (gint x,
|
||||
gint y,
|
||||
PikaRGB *color,
|
||||
gpointer data);
|
||||
/**
|
||||
* PikaProgressFunc:
|
||||
* @min:
|
||||
* @max:
|
||||
* @current:
|
||||
* @data: (closure):
|
||||
*/
|
||||
typedef void (* PikaProgressFunc) (gint min,
|
||||
gint max,
|
||||
gint current,
|
||||
gpointer data);
|
||||
|
||||
|
||||
gulong pika_adaptive_supersample_area (gint x1,
|
||||
gint y1,
|
||||
gint x2,
|
||||
gint y2,
|
||||
gint max_depth,
|
||||
gdouble threshold,
|
||||
PikaRenderFunc render_func,
|
||||
gpointer render_data,
|
||||
PikaPutPixelFunc put_pixel_func,
|
||||
gpointer put_pixel_data,
|
||||
PikaProgressFunc progress_func,
|
||||
gpointer progress_data);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_ADAPTIVE_SUPERSAMPLE_H__ */
|
273
libpikacolor/pikabilinear.c
Normal file
273
libpikacolor/pikabilinear.c
Normal file
@ -0,0 +1,273 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikabilinear.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikabilinear
|
||||
* @title: PikaBilinear
|
||||
* @short_description: Utility functions for bilinear interpolation.
|
||||
*
|
||||
* Utility functions for bilinear interpolation.
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* pika_bilinear:
|
||||
* @x:
|
||||
* @y:
|
||||
* @values: (array fixed-size=4):
|
||||
*/
|
||||
gdouble
|
||||
pika_bilinear (gdouble x,
|
||||
gdouble y,
|
||||
gdouble *values)
|
||||
{
|
||||
gdouble m0, m1;
|
||||
|
||||
g_return_val_if_fail (values != NULL, 0.0);
|
||||
|
||||
x = fmod (x, 1.0);
|
||||
y = fmod (y, 1.0);
|
||||
|
||||
if (x < 0.0)
|
||||
x += 1.0;
|
||||
if (y < 0.0)
|
||||
y += 1.0;
|
||||
|
||||
m0 = (1.0 - x) * values[0] + x * values[1];
|
||||
m1 = (1.0 - x) * values[2] + x * values[3];
|
||||
|
||||
return (1.0 - y) * m0 + y * m1;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_bilinear_8:
|
||||
* @x:
|
||||
* @y:
|
||||
* @values: (array fixed-size=4):
|
||||
*/
|
||||
guchar
|
||||
pika_bilinear_8 (gdouble x,
|
||||
gdouble y,
|
||||
guchar *values)
|
||||
{
|
||||
gdouble m0, m1;
|
||||
|
||||
g_return_val_if_fail (values != NULL, 0);
|
||||
|
||||
x = fmod (x, 1.0);
|
||||
y = fmod (y, 1.0);
|
||||
|
||||
if (x < 0.0)
|
||||
x += 1.0;
|
||||
if (y < 0.0)
|
||||
y += 1.0;
|
||||
|
||||
m0 = (1.0 - x) * values[0] + x * values[1];
|
||||
m1 = (1.0 - x) * values[2] + x * values[3];
|
||||
|
||||
return (guchar) ((1.0 - y) * m0 + y * m1);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_bilinear_16:
|
||||
* @x:
|
||||
* @y:
|
||||
* @values: (array fixed-size=4):
|
||||
*/
|
||||
guint16
|
||||
pika_bilinear_16 (gdouble x,
|
||||
gdouble y,
|
||||
guint16 *values)
|
||||
{
|
||||
gdouble m0, m1;
|
||||
|
||||
g_return_val_if_fail (values != NULL, 0);
|
||||
|
||||
x = fmod (x, 1.0);
|
||||
y = fmod (y, 1.0);
|
||||
|
||||
if (x < 0.0)
|
||||
x += 1.0;
|
||||
if (y < 0.0)
|
||||
y += 1.0;
|
||||
|
||||
m0 = (1.0 - x) * values[0] + x * values[1];
|
||||
m1 = (1.0 - x) * values[2] + x * values[3];
|
||||
|
||||
return (guint16) ((1.0 - y) * m0 + y * m1);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_bilinear_32:
|
||||
* @x:
|
||||
* @y:
|
||||
* @values: (array fixed-size=4):
|
||||
*/
|
||||
guint32
|
||||
pika_bilinear_32 (gdouble x,
|
||||
gdouble y,
|
||||
guint32 *values)
|
||||
{
|
||||
gdouble m0, m1;
|
||||
|
||||
g_return_val_if_fail (values != NULL, 0);
|
||||
|
||||
x = fmod (x, 1.0);
|
||||
y = fmod (y, 1.0);
|
||||
|
||||
if (x < 0.0)
|
||||
x += 1.0;
|
||||
if (y < 0.0)
|
||||
y += 1.0;
|
||||
|
||||
m0 = (1.0 - x) * values[0] + x * values[1];
|
||||
m1 = (1.0 - x) * values[2] + x * values[3];
|
||||
|
||||
return (guint32) ((1.0 - y) * m0 + y * m1);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_bilinear_rgb:
|
||||
* @x:
|
||||
* @y:
|
||||
* @values: (array fixed-size=4):
|
||||
*/
|
||||
PikaRGB
|
||||
pika_bilinear_rgb (gdouble x,
|
||||
gdouble y,
|
||||
PikaRGB *values)
|
||||
{
|
||||
gdouble m0, m1;
|
||||
gdouble ix, iy;
|
||||
PikaRGB v = { 0, };
|
||||
|
||||
g_return_val_if_fail (values != NULL, v);
|
||||
|
||||
x = fmod(x, 1.0);
|
||||
y = fmod(y, 1.0);
|
||||
|
||||
if (x < 0)
|
||||
x += 1.0;
|
||||
if (y < 0)
|
||||
y += 1.0;
|
||||
|
||||
ix = 1.0 - x;
|
||||
iy = 1.0 - y;
|
||||
|
||||
/* Red */
|
||||
|
||||
m0 = ix * values[0].r + x * values[1].r;
|
||||
m1 = ix * values[2].r + x * values[3].r;
|
||||
|
||||
v.r = iy * m0 + y * m1;
|
||||
|
||||
/* Green */
|
||||
|
||||
m0 = ix * values[0].g + x * values[1].g;
|
||||
m1 = ix * values[2].g + x * values[3].g;
|
||||
|
||||
v.g = iy * m0 + y * m1;
|
||||
|
||||
/* Blue */
|
||||
|
||||
m0 = ix * values[0].b + x * values[1].b;
|
||||
m1 = ix * values[2].b + x * values[3].b;
|
||||
|
||||
v.b = iy * m0 + y * m1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_bilinear_rgba:
|
||||
* @x:
|
||||
* @y:
|
||||
* @values: (array fixed-size=4):
|
||||
*/
|
||||
PikaRGB
|
||||
pika_bilinear_rgba (gdouble x,
|
||||
gdouble y,
|
||||
PikaRGB *values)
|
||||
{
|
||||
gdouble m0, m1;
|
||||
gdouble ix, iy;
|
||||
gdouble a0, a1, a2, a3, alpha;
|
||||
PikaRGB v = { 0, };
|
||||
|
||||
g_return_val_if_fail (values != NULL, v);
|
||||
|
||||
x = fmod (x, 1.0);
|
||||
y = fmod (y, 1.0);
|
||||
|
||||
if (x < 0)
|
||||
x += 1.0;
|
||||
if (y < 0)
|
||||
y += 1.0;
|
||||
|
||||
ix = 1.0 - x;
|
||||
iy = 1.0 - y;
|
||||
|
||||
a0 = values[0].a;
|
||||
a1 = values[1].a;
|
||||
a2 = values[2].a;
|
||||
a3 = values[3].a;
|
||||
|
||||
/* Alpha */
|
||||
|
||||
m0 = ix * a0 + x * a1;
|
||||
m1 = ix * a2 + x * a3;
|
||||
|
||||
alpha = v.a = iy * m0 + y * m1;
|
||||
|
||||
if (alpha > 0)
|
||||
{
|
||||
/* Red */
|
||||
|
||||
m0 = ix * a0 * values[0].r + x * a1 * values[1].r;
|
||||
m1 = ix * a2 * values[2].r + x * a3 * values[3].r;
|
||||
|
||||
v.r = (iy * m0 + y * m1)/alpha;
|
||||
|
||||
/* Green */
|
||||
|
||||
m0 = ix * a0 * values[0].g + x * a1 * values[1].g;
|
||||
m1 = ix * a2 * values[2].g + x * a3 * values[3].g;
|
||||
|
||||
v.g = (iy * m0 + y * m1)/alpha;
|
||||
|
||||
/* Blue */
|
||||
|
||||
m0 = ix * a0 * values[0].b + x * a1 * values[1].b;
|
||||
m1 = ix * a2 * values[2].b + x * a3 * values[3].b;
|
||||
|
||||
v.b = (iy * m0 + y * m1)/alpha;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
56
libpikacolor/pikabilinear.h
Normal file
56
libpikacolor/pikabilinear.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_BILINEAR_H__
|
||||
#define __PIKA_BILINEAR_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
/* bilinear interpolation functions taken from LibGCK */
|
||||
|
||||
|
||||
gdouble pika_bilinear (gdouble x,
|
||||
gdouble y,
|
||||
gdouble *values);
|
||||
guchar pika_bilinear_8 (gdouble x,
|
||||
gdouble y,
|
||||
guchar *values);
|
||||
guint16 pika_bilinear_16 (gdouble x,
|
||||
gdouble y,
|
||||
guint16 *values);
|
||||
guint32 pika_bilinear_32 (gdouble x,
|
||||
gdouble y,
|
||||
guint32 *values);
|
||||
PikaRGB pika_bilinear_rgb (gdouble x,
|
||||
gdouble y,
|
||||
PikaRGB *values);
|
||||
PikaRGB pika_bilinear_rgba (gdouble x,
|
||||
gdouble y,
|
||||
PikaRGB *values);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_BILINEAR_H__ */
|
210
libpikacolor/pikacairo.c
Normal file
210
libpikacolor/pikacairo.c
Normal file
@ -0,0 +1,210 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* pikacairo.c
|
||||
* Copyright (C) 2007 Sven Neumann <sven@gimp.org>
|
||||
* 2010-2012 Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* 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 3 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cairo.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikacairo.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikacairo
|
||||
* @title: PikaCairo
|
||||
* @short_description: Color utility functions for cairo
|
||||
*
|
||||
* Utility functions that make cairo easier to use with PIKA color
|
||||
* data types.
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* pika_cairo_set_source_rgb:
|
||||
* @cr: Cairo context
|
||||
* @color: PikaRGB color
|
||||
*
|
||||
* Sets the source pattern within @cr to the solid opaque color
|
||||
* described by @color.
|
||||
*
|
||||
* This function calls cairo_set_source_rgb() for you.
|
||||
*
|
||||
* Since: 2.6
|
||||
**/
|
||||
void
|
||||
pika_cairo_set_source_rgb (cairo_t *cr,
|
||||
const PikaRGB *color)
|
||||
{
|
||||
cairo_set_source_rgb (cr, color->r, color->g, color->b);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cairo_set_source_rgba:
|
||||
* @cr: Cairo context
|
||||
* @color: PikaRGB color
|
||||
*
|
||||
* Sets the source pattern within @cr to the solid translucent color
|
||||
* described by @color.
|
||||
*
|
||||
* This function calls cairo_set_source_rgba() for you.
|
||||
*
|
||||
* Since: 2.6
|
||||
**/
|
||||
void
|
||||
pika_cairo_set_source_rgba (cairo_t *cr,
|
||||
const PikaRGB *color)
|
||||
{
|
||||
cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cairo_checkerboard_create:
|
||||
* @cr: Cairo context
|
||||
* @size: check size
|
||||
* @light: light check color or %NULL to use the default light gray
|
||||
* @dark: dark check color or %NULL to use the default dark gray
|
||||
*
|
||||
* Create a repeating checkerboard pattern.
|
||||
*
|
||||
* Returns: a new Cairo pattern that can be used as a source on @cr.
|
||||
*
|
||||
* Since: 2.6
|
||||
**/
|
||||
cairo_pattern_t *
|
||||
pika_cairo_checkerboard_create (cairo_t *cr,
|
||||
gint size,
|
||||
const PikaRGB *light,
|
||||
const PikaRGB *dark)
|
||||
{
|
||||
cairo_t *context;
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *pattern;
|
||||
|
||||
g_return_val_if_fail (cr != NULL, NULL);
|
||||
g_return_val_if_fail (size > 0, NULL);
|
||||
|
||||
surface = cairo_surface_create_similar (cairo_get_target (cr),
|
||||
CAIRO_CONTENT_COLOR,
|
||||
2 * size, 2 * size);
|
||||
context = cairo_create (surface);
|
||||
|
||||
if (light)
|
||||
pika_cairo_set_source_rgb (context, light);
|
||||
else
|
||||
cairo_set_source_rgb (context,
|
||||
PIKA_CHECK_LIGHT, PIKA_CHECK_LIGHT, PIKA_CHECK_LIGHT);
|
||||
|
||||
cairo_rectangle (context, 0, 0, size, size);
|
||||
cairo_rectangle (context, size, size, size, size);
|
||||
cairo_fill (context);
|
||||
|
||||
if (dark)
|
||||
pika_cairo_set_source_rgb (context, dark);
|
||||
else
|
||||
cairo_set_source_rgb (context,
|
||||
PIKA_CHECK_DARK, PIKA_CHECK_DARK, PIKA_CHECK_DARK);
|
||||
|
||||
cairo_rectangle (context, 0, size, size, size);
|
||||
cairo_rectangle (context, size, 0, size, size);
|
||||
cairo_fill (context);
|
||||
|
||||
cairo_destroy (context);
|
||||
|
||||
pattern = cairo_pattern_create_for_surface (surface);
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cairo_surface_get_format:
|
||||
* @surface: a Cairo surface
|
||||
*
|
||||
* This function returns a #Babl format that corresponds to @surface's
|
||||
* pixel format.
|
||||
*
|
||||
* Returns: the #Babl format of @surface.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
const Babl *
|
||||
pika_cairo_surface_get_format (cairo_surface_t *surface)
|
||||
{
|
||||
g_return_val_if_fail (surface != NULL, NULL);
|
||||
g_return_val_if_fail (cairo_surface_get_type (surface) ==
|
||||
CAIRO_SURFACE_TYPE_IMAGE, NULL);
|
||||
|
||||
switch (cairo_image_surface_get_format (surface))
|
||||
{
|
||||
case CAIRO_FORMAT_RGB24: return babl_format ("cairo-RGB24");
|
||||
case CAIRO_FORMAT_ARGB32: return babl_format ("cairo-ARGB32");
|
||||
case CAIRO_FORMAT_A8: return babl_format ("cairo-A8");
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cairo_surface_create_buffer:
|
||||
* @surface: a Cairo surface
|
||||
*
|
||||
* This function returns a #GeglBuffer which wraps @surface's pixels.
|
||||
* It must only be called on image surfaces, calling it on other surface
|
||||
* types is an error.
|
||||
*
|
||||
* Returns: (transfer full): a #GeglBuffer
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
GeglBuffer *
|
||||
pika_cairo_surface_create_buffer (cairo_surface_t *surface)
|
||||
{
|
||||
const Babl *format;
|
||||
gint width;
|
||||
gint height;
|
||||
|
||||
g_return_val_if_fail (surface != NULL, NULL);
|
||||
g_return_val_if_fail (cairo_surface_get_type (surface) ==
|
||||
CAIRO_SURFACE_TYPE_IMAGE, NULL);
|
||||
|
||||
format = pika_cairo_surface_get_format (surface);
|
||||
width = cairo_image_surface_get_width (surface);
|
||||
height = cairo_image_surface_get_height (surface);
|
||||
|
||||
return
|
||||
gegl_buffer_linear_new_from_data (cairo_image_surface_get_data (surface),
|
||||
format,
|
||||
GEGL_RECTANGLE (0, 0, width, height),
|
||||
cairo_image_surface_get_stride (surface),
|
||||
(GDestroyNotify) cairo_surface_destroy,
|
||||
cairo_surface_reference (surface));
|
||||
}
|
159
libpikacolor/pikacairo.h
Normal file
159
libpikacolor/pikacairo.h
Normal file
@ -0,0 +1,159 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* pikacairo.h
|
||||
* Copyright (C) 2007 Sven Neumann <sven@gimp.org>
|
||||
* 2010-2012 Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* 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 3 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CAIRO_H__
|
||||
#define __PIKA_CAIRO_H__
|
||||
|
||||
|
||||
void pika_cairo_set_source_rgb (cairo_t *cr,
|
||||
const PikaRGB *color);
|
||||
void pika_cairo_set_source_rgba (cairo_t *cr,
|
||||
const PikaRGB *color);
|
||||
|
||||
cairo_pattern_t * pika_cairo_checkerboard_create (cairo_t *cr,
|
||||
gint size,
|
||||
const PikaRGB *light,
|
||||
const PikaRGB *dark);
|
||||
|
||||
const Babl * pika_cairo_surface_get_format (cairo_surface_t *surface);
|
||||
GeglBuffer * pika_cairo_surface_create_buffer (cairo_surface_t *surface);
|
||||
|
||||
|
||||
/* some useful macros for writing directly to a Cairo surface */
|
||||
|
||||
/**
|
||||
* PIKA_CAIRO_RGB24_SET_PIXEL:
|
||||
* @d: pointer to the destination buffer
|
||||
* @r: red component
|
||||
* @g: green component
|
||||
* @b: blue component
|
||||
*
|
||||
* Sets a single pixel in an Cairo image surface in %CAIRO_FORMAT_RGB24.
|
||||
*
|
||||
* Since: 2.6
|
||||
**/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define PIKA_CAIRO_RGB24_SET_PIXEL(d, r, g, b) \
|
||||
G_STMT_START { d[0] = (b); d[1] = (g); d[2] = (r); } G_STMT_END
|
||||
#else
|
||||
#define PIKA_CAIRO_RGB24_SET_PIXEL(d, r, g, b) \
|
||||
G_STMT_START { d[1] = (r); d[2] = (g); d[3] = (b); } G_STMT_END
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* PIKA_CAIRO_RGB24_GET_PIXEL:
|
||||
* @s: pointer to the source buffer
|
||||
* @r: red component
|
||||
* @g: green component
|
||||
* @b: blue component
|
||||
*
|
||||
* Gets a single pixel from a Cairo image surface in %CAIRO_FORMAT_RGB24.
|
||||
*
|
||||
* Since: 2.8
|
||||
**/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define PIKA_CAIRO_RGB24_GET_PIXEL(s, r, g, b) \
|
||||
G_STMT_START { (b) = s[0]; (g) = s[1]; (r) = s[2]; } G_STMT_END
|
||||
#else
|
||||
#define PIKA_CAIRO_RGB24_GET_PIXEL(s, r, g, b) \
|
||||
G_STMT_START { (r) = s[1]; (g) = s[2]; (b) = s[3]; } G_STMT_END
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* PIKA_CAIRO_ARGB32_SET_PIXEL:
|
||||
* @d: pointer to the destination buffer
|
||||
* @r: red component, not pre-multiplied
|
||||
* @g: green component, not pre-multiplied
|
||||
* @b: blue component, not pre-multiplied
|
||||
* @a: alpha component
|
||||
*
|
||||
* Sets a single pixel in an Cairo image surface in %CAIRO_FORMAT_ARGB32.
|
||||
*
|
||||
* Since: 2.6
|
||||
**/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define PIKA_CAIRO_ARGB32_SET_PIXEL(d, r, g, b, a) \
|
||||
G_STMT_START { \
|
||||
const guint tr = (a) * (r) + 0x80; \
|
||||
const guint tg = (a) * (g) + 0x80; \
|
||||
const guint tb = (a) * (b) + 0x80; \
|
||||
(d)[0] = (((tb) >> 8) + (tb)) >> 8; \
|
||||
(d)[1] = (((tg) >> 8) + (tg)) >> 8; \
|
||||
(d)[2] = (((tr) >> 8) + (tr)) >> 8; \
|
||||
(d)[3] = (a); \
|
||||
} G_STMT_END
|
||||
#else
|
||||
#define PIKA_CAIRO_ARGB32_SET_PIXEL(d, r, g, b, a) \
|
||||
G_STMT_START { \
|
||||
const guint tr = (a) * (r) + 0x80; \
|
||||
const guint tg = (a) * (g) + 0x80; \
|
||||
const guint tb = (a) * (b) + 0x80; \
|
||||
(d)[0] = (a); \
|
||||
(d)[1] = (((tr) >> 8) + (tr)) >> 8; \
|
||||
(d)[2] = (((tg) >> 8) + (tg)) >> 8; \
|
||||
(d)[3] = (((tb) >> 8) + (tb)) >> 8; \
|
||||
} G_STMT_END
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* PIKA_CAIRO_ARGB32_GET_PIXEL:
|
||||
* @s: pointer to the source buffer
|
||||
* @r: red component, not pre-multiplied
|
||||
* @g: green component, not pre-multiplied
|
||||
* @b: blue component, not pre-multiplied
|
||||
* @a: alpha component
|
||||
*
|
||||
* Gets a single pixel from a Cairo image surface in %CAIRO_FORMAT_ARGB32.
|
||||
*
|
||||
* Since: 2.8
|
||||
**/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define PIKA_CAIRO_ARGB32_GET_PIXEL(s, r, g, b, a) \
|
||||
G_STMT_START { \
|
||||
const guint tb = (s)[0]; \
|
||||
const guint tg = (s)[1]; \
|
||||
const guint tr = (s)[2]; \
|
||||
const guint ta = (s)[3]; \
|
||||
(r) = (tr << 8) / (ta + 1); \
|
||||
(g) = (tg << 8) / (ta + 1); \
|
||||
(b) = (tb << 8) / (ta + 1); \
|
||||
(a) = ta; \
|
||||
} G_STMT_END
|
||||
#else
|
||||
#define PIKA_CAIRO_ARGB32_GET_PIXEL(s, r, g, b, a) \
|
||||
G_STMT_START { \
|
||||
const guint ta = (s)[0]; \
|
||||
const guint tr = (s)[1]; \
|
||||
const guint tg = (s)[2]; \
|
||||
const guint tb = (s)[3]; \
|
||||
(r) = (tr << 8) / (ta + 1); \
|
||||
(g) = (tg << 8) / (ta + 1); \
|
||||
(b) = (tb << 8) / (ta + 1); \
|
||||
(a) = ta; \
|
||||
} G_STMT_END
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __PIKA_CAIRO_H__ */
|
223
libpikacolor/pikacmyk.c
Normal file
223
libpikacolor/pikacmyk.c
Normal file
@ -0,0 +1,223 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikacmyk.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikacmyk
|
||||
* @title: PikaCMYK
|
||||
* @short_description: Definitions and Functions relating to CMYK colors.
|
||||
*
|
||||
* Definitions and Functions relating to CMYK colors.
|
||||
**/
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_CMYK
|
||||
*/
|
||||
|
||||
static PikaCMYK * pika_cmyk_copy (const PikaCMYK *cmyk);
|
||||
|
||||
|
||||
G_DEFINE_BOXED_TYPE (PikaCMYK, pika_cmyk, pika_cmyk_copy, g_free)
|
||||
|
||||
static PikaCMYK *
|
||||
pika_cmyk_copy (const PikaCMYK *cmyk)
|
||||
{
|
||||
return g_memdup2 (cmyk, sizeof (PikaCMYK));
|
||||
}
|
||||
|
||||
|
||||
/* CMYK functions */
|
||||
|
||||
/**
|
||||
* pika_cmyk_set:
|
||||
* @cmyk: A #PikaCMYK structure which will hold the specified CMYK value.
|
||||
* @cyan: The Cyan channel of the CMYK value
|
||||
* @magenta: The Magenta channel
|
||||
* @yellow: The Yellow channel
|
||||
* @black: The blacK channel
|
||||
*
|
||||
* Very basic initialiser for the internal #PikaCMYK structure. Channel
|
||||
* values are doubles in the range 0 to 1.
|
||||
**/
|
||||
void
|
||||
pika_cmyk_set (PikaCMYK *cmyk,
|
||||
gdouble cyan,
|
||||
gdouble magenta,
|
||||
gdouble yellow,
|
||||
gdouble black)
|
||||
{
|
||||
g_return_if_fail (cmyk != NULL);
|
||||
|
||||
cmyk->c = cyan;
|
||||
cmyk->m = magenta;
|
||||
cmyk->y = yellow;
|
||||
cmyk->k = black;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cmyk_set_uchar:
|
||||
* @cmyk: A #PikaCMYK structure which will hold the specified CMYK value.
|
||||
* @cyan: The Cyan channel of the CMYK value
|
||||
* @magenta: The Magenta channel
|
||||
* @yellow: The Yellow channel
|
||||
* @black: The blacK channel
|
||||
*
|
||||
* The same as pika_cmyk_set(), except that channel values are
|
||||
* unsigned chars in the range 0 to 255.
|
||||
**/
|
||||
void
|
||||
pika_cmyk_set_uchar (PikaCMYK *cmyk,
|
||||
guchar cyan,
|
||||
guchar magenta,
|
||||
guchar yellow,
|
||||
guchar black)
|
||||
{
|
||||
g_return_if_fail (cmyk != NULL);
|
||||
|
||||
cmyk->c = (gdouble) cyan / 255.0;
|
||||
cmyk->m = (gdouble) magenta / 255.0;
|
||||
cmyk->y = (gdouble) yellow / 255.0;
|
||||
cmyk->k = (gdouble) black / 255.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cmyk_get_uchar:
|
||||
* @cmyk: A #PikaCMYK structure which will hold the specified CMYK value.
|
||||
* @cyan: (out) (optional): The Cyan channel of the CMYK value
|
||||
* @magenta: (out) (optional): The Magenta channel
|
||||
* @yellow: (out) (optional): The Yellow channel
|
||||
* @black: (out) (optional): The blacK channel
|
||||
*
|
||||
* Retrieve individual channel values from a #PikaCMYK structure. Channel
|
||||
* values are pointers to unsigned chars in the range 0 to 255.
|
||||
**/
|
||||
void
|
||||
pika_cmyk_get_uchar (const PikaCMYK *cmyk,
|
||||
guchar *cyan,
|
||||
guchar *magenta,
|
||||
guchar *yellow,
|
||||
guchar *black)
|
||||
{
|
||||
g_return_if_fail (cmyk != NULL);
|
||||
|
||||
if (cyan) *cyan = ROUND (CLAMP (cmyk->c, 0.0, 1.0) * 255.0);
|
||||
if (magenta) *magenta = ROUND (CLAMP (cmyk->m, 0.0, 1.0) * 255.0);
|
||||
if (yellow) *yellow = ROUND (CLAMP (cmyk->y, 0.0, 1.0) * 255.0);
|
||||
if (black) *black = ROUND (CLAMP (cmyk->k, 0.0, 1.0) * 255.0);
|
||||
}
|
||||
|
||||
|
||||
/* CMYKA functions */
|
||||
|
||||
/**
|
||||
* pika_cmyka_set:
|
||||
* @cmyka: A #PikaCMYK structure which will hold the specified CMYKA value.
|
||||
* @cyan: The Cyan channel of the CMYK value
|
||||
* @magenta: The Magenta channel
|
||||
* @yellow: The Yellow channel
|
||||
* @black: The blacK channel
|
||||
* @alpha: The Alpha channel
|
||||
*
|
||||
* Initialiser for the internal #PikaCMYK structure. Channel values are
|
||||
* doubles in the range 0 to 1.
|
||||
**/
|
||||
void
|
||||
pika_cmyka_set (PikaCMYK *cmyka,
|
||||
gdouble cyan,
|
||||
gdouble magenta,
|
||||
gdouble yellow,
|
||||
gdouble black,
|
||||
gdouble alpha)
|
||||
{
|
||||
g_return_if_fail (cmyka != NULL);
|
||||
|
||||
cmyka->c = cyan;
|
||||
cmyka->m = magenta;
|
||||
cmyka->y = yellow;
|
||||
cmyka->k = black;
|
||||
cmyka->a = alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cmyka_set_uchar:
|
||||
* @cmyka: A #PikaCMYK structure which will hold the specified CMYKA value.
|
||||
* @cyan: The Cyan channel of the CMYK value
|
||||
* @magenta: The Magenta channel
|
||||
* @yellow: The Yellow channel
|
||||
* @black: The blacK channel
|
||||
* @alpha: The Alpha channel
|
||||
*
|
||||
* The same as pika_cmyka_set(), except that channel values are
|
||||
* unsigned chars in the range 0 to 255.
|
||||
**/
|
||||
void
|
||||
pika_cmyka_set_uchar (PikaCMYK *cmyka,
|
||||
guchar cyan,
|
||||
guchar magenta,
|
||||
guchar yellow,
|
||||
guchar black,
|
||||
guchar alpha)
|
||||
{
|
||||
g_return_if_fail (cmyka != NULL);
|
||||
|
||||
cmyka->c = (gdouble) cyan / 255.0;
|
||||
cmyka->m = (gdouble) magenta / 255.0;
|
||||
cmyka->y = (gdouble) yellow / 255.0;
|
||||
cmyka->k = (gdouble) black / 255.0;
|
||||
cmyka->a = (gdouble) alpha / 255.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cmyka_get_uchar:
|
||||
* @cmyka: A #PikaCMYK structure which will hold the specified CMYKA value.
|
||||
* @cyan: (out) (optional): The Cyan channel of the CMYK value
|
||||
* @magenta: (out) (optional): The Magenta channel
|
||||
* @yellow: (out) (optional): The Yellow channel
|
||||
* @black: (out) (optional): The blacK channel
|
||||
* @alpha: (out) (optional): The Alpha channel
|
||||
*
|
||||
* Retrieve individual channel values from a #PikaCMYK structure.
|
||||
* Channel values are pointers to unsigned chars in the range 0 to 255.
|
||||
**/
|
||||
void
|
||||
pika_cmyka_get_uchar (const PikaCMYK *cmyka,
|
||||
guchar *cyan,
|
||||
guchar *magenta,
|
||||
guchar *yellow,
|
||||
guchar *black,
|
||||
guchar *alpha)
|
||||
{
|
||||
g_return_if_fail (cmyka != NULL);
|
||||
|
||||
if (cyan) *cyan = ROUND (CLAMP (cmyka->c, 0.0, 1.0) * 255.0);
|
||||
if (magenta) *magenta = ROUND (CLAMP (cmyka->m, 0.0, 1.0) * 255.0);
|
||||
if (yellow) *yellow = ROUND (CLAMP (cmyka->y, 0.0, 1.0) * 255.0);
|
||||
if (black) *black = ROUND (CLAMP (cmyka->k, 0.0, 1.0) * 255.0);
|
||||
if (alpha) *alpha = ROUND (CLAMP (cmyka->a, 0.0, 1.0) * 255.0);
|
||||
}
|
78
libpikacolor/pikacmyk.h
Normal file
78
libpikacolor/pikacmyk.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_CMYK_H__
|
||||
#define __PIKA_CMYK_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_CMYK
|
||||
*/
|
||||
|
||||
#define PIKA_TYPE_CMYK (pika_cmyk_get_type ())
|
||||
|
||||
GType pika_cmyk_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_cmyk_set (PikaCMYK *cmyk,
|
||||
gdouble cyan,
|
||||
gdouble magenta,
|
||||
gdouble yellow,
|
||||
gdouble black);
|
||||
void pika_cmyk_set_uchar (PikaCMYK *cmyk,
|
||||
guchar cyan,
|
||||
guchar magenta,
|
||||
guchar yellow,
|
||||
guchar black);
|
||||
void pika_cmyk_get_uchar (const PikaCMYK *cmyk,
|
||||
guchar *cyan,
|
||||
guchar *magenta,
|
||||
guchar *yellow,
|
||||
guchar *black);
|
||||
|
||||
void pika_cmyka_set (PikaCMYK *cmyka,
|
||||
gdouble cyan,
|
||||
gdouble magenta,
|
||||
gdouble yellow,
|
||||
gdouble black,
|
||||
gdouble alpha);
|
||||
void pika_cmyka_set_uchar (PikaCMYK *cmyka,
|
||||
guchar cyan,
|
||||
guchar magenta,
|
||||
guchar yellow,
|
||||
guchar black,
|
||||
guchar alpha);
|
||||
void pika_cmyka_get_uchar (const PikaCMYK *cmyka,
|
||||
guchar *cyan,
|
||||
guchar *magenta,
|
||||
guchar *yellow,
|
||||
guchar *black,
|
||||
guchar *alpha);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_CMYK_H__ */
|
119
libpikacolor/pikacolor.def
Normal file
119
libpikacolor/pikacolor.def
Normal file
@ -0,0 +1,119 @@
|
||||
EXPORTS
|
||||
pika_adaptive_supersample_area
|
||||
pika_bilinear
|
||||
pika_bilinear_16
|
||||
pika_bilinear_32
|
||||
pika_bilinear_8
|
||||
pika_bilinear_rgb
|
||||
pika_bilinear_rgba
|
||||
pika_cairo_checkerboard_create
|
||||
pika_cairo_set_source_rgb
|
||||
pika_cairo_set_source_rgba
|
||||
pika_cairo_surface_create_buffer
|
||||
pika_cairo_surface_get_format
|
||||
pika_cmyk_get_type
|
||||
pika_cmyk_get_uchar
|
||||
pika_cmyk_set
|
||||
pika_cmyk_set_uchar
|
||||
pika_cmyk_to_rgb
|
||||
pika_cmyka_get_uchar
|
||||
pika_cmyka_set
|
||||
pika_cmyka_set_uchar
|
||||
pika_color_managed_get_color_profile
|
||||
pika_color_managed_get_icc_profile
|
||||
pika_color_managed_get_simulation_bpc
|
||||
pika_color_managed_get_simulation_intent
|
||||
pika_color_managed_get_simulation_profile
|
||||
pika_color_managed_get_type
|
||||
pika_color_managed_profile_changed
|
||||
pika_color_managed_simulation_bpc_changed
|
||||
pika_color_managed_simulation_intent_changed
|
||||
pika_color_managed_simulation_profile_changed
|
||||
pika_color_profile_get_copyright
|
||||
pika_color_profile_get_description
|
||||
pika_color_profile_get_format
|
||||
pika_color_profile_get_icc_profile
|
||||
pika_color_profile_get_label
|
||||
pika_color_profile_get_lcms_format
|
||||
pika_color_profile_get_lcms_profile
|
||||
pika_color_profile_get_manufacturer
|
||||
pika_color_profile_get_model
|
||||
pika_color_profile_get_space
|
||||
pika_color_profile_get_summary
|
||||
pika_color_profile_get_type
|
||||
pika_color_profile_is_cmyk
|
||||
pika_color_profile_is_equal
|
||||
pika_color_profile_is_gray
|
||||
pika_color_profile_is_linear
|
||||
pika_color_profile_is_rgb
|
||||
pika_color_profile_new_d50_gray_lab_trc
|
||||
pika_color_profile_new_d65_gray_linear
|
||||
pika_color_profile_new_d65_gray_srgb_trc
|
||||
pika_color_profile_new_from_file
|
||||
pika_color_profile_new_from_icc_profile
|
||||
pika_color_profile_new_from_lcms_profile
|
||||
pika_color_profile_new_linear_from_color_profile
|
||||
pika_color_profile_new_rgb_adobe
|
||||
pika_color_profile_new_rgb_srgb
|
||||
pika_color_profile_new_rgb_srgb_linear
|
||||
pika_color_profile_new_srgb_trc_from_color_profile
|
||||
pika_color_profile_save_to_file
|
||||
pika_color_transform_can_gegl_copy
|
||||
pika_color_transform_get_type
|
||||
pika_color_transform_new
|
||||
pika_color_transform_new_proofing
|
||||
pika_color_transform_process_buffer
|
||||
pika_color_transform_process_pixels
|
||||
pika_hsl_get_type
|
||||
pika_hsl_set
|
||||
pika_hsl_set_alpha
|
||||
pika_hsl_to_rgb
|
||||
pika_hsv_clamp
|
||||
pika_hsv_get_type
|
||||
pika_hsv_set
|
||||
pika_hsv_to_rgb
|
||||
pika_hsva_set
|
||||
pika_param_rgb_get_type
|
||||
pika_param_spec_rgb
|
||||
pika_param_spec_rgb_get_default
|
||||
pika_param_spec_rgb_has_alpha
|
||||
pika_pixbuf_create_buffer
|
||||
pika_pixbuf_get_format
|
||||
pika_pixbuf_get_icc_profile
|
||||
pika_rgb_add
|
||||
pika_rgb_clamp
|
||||
pika_rgb_composite
|
||||
pika_rgb_distance
|
||||
pika_rgb_gamma
|
||||
pika_rgb_get_pixel
|
||||
pika_rgb_get_type
|
||||
pika_rgb_get_uchar
|
||||
pika_rgb_list_names
|
||||
pika_rgb_luminance
|
||||
pika_rgb_luminance_uchar
|
||||
pika_rgb_max
|
||||
pika_rgb_min
|
||||
pika_rgb_multiply
|
||||
pika_rgb_parse_css
|
||||
pika_rgb_parse_hex
|
||||
pika_rgb_parse_name
|
||||
pika_rgb_set
|
||||
pika_rgb_set_alpha
|
||||
pika_rgb_set_pixel
|
||||
pika_rgb_set_uchar
|
||||
pika_rgb_subtract
|
||||
pika_rgb_to_cmyk
|
||||
pika_rgb_to_hsl
|
||||
pika_rgb_to_hsv
|
||||
pika_rgba_add
|
||||
pika_rgba_distance
|
||||
pika_rgba_get_pixel
|
||||
pika_rgba_get_uchar
|
||||
pika_rgba_multiply
|
||||
pika_rgba_parse_css
|
||||
pika_rgba_set
|
||||
pika_rgba_set_pixel
|
||||
pika_rgba_set_uchar
|
||||
pika_rgba_subtract
|
||||
pika_value_get_rgb
|
||||
pika_value_set_rgb
|
41
libpikacolor/pikacolor.h
Normal file
41
libpikacolor/pikacolor.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_COLOR_H__
|
||||
#define __PIKA_COLOR_H__
|
||||
|
||||
#define __PIKA_COLOR_H_INSIDE__
|
||||
|
||||
#include <libpikacolor/pikacolortypes.h>
|
||||
|
||||
#include <libpikacolor/pikaadaptivesupersample.h>
|
||||
#include <libpikacolor/pikabilinear.h>
|
||||
#include <libpikacolor/pikacairo.h>
|
||||
#include <libpikacolor/pikacolormanaged.h>
|
||||
#include <libpikacolor/pikacolorprofile.h>
|
||||
#include <libpikacolor/pikacolorspace.h>
|
||||
#include <libpikacolor/pikacolortransform.h>
|
||||
#include <libpikacolor/pikacmyk.h>
|
||||
#include <libpikacolor/pikahsl.h>
|
||||
#include <libpikacolor/pikahsv.h>
|
||||
#include <libpikacolor/pikapixbuf.h>
|
||||
#include <libpikacolor/pikargb.h>
|
||||
|
||||
#undef __PIKA_COLOR_H_INSIDE__
|
||||
|
||||
#endif /* __PIKA_COLOR_H__ */
|
300
libpikacolor/pikacolormanaged.c
Normal file
300
libpikacolor/pikacolormanaged.c
Normal file
@ -0,0 +1,300 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* PikaColorManaged interface
|
||||
* Copyright (C) 2007 Sven Neumann <sven@gimp.org>
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikacolormanaged.h"
|
||||
#include "pikacolorprofile.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikacolormanaged
|
||||
* @title: PikaColorManaged
|
||||
* @short_description: An interface dealing with color profiles.
|
||||
*
|
||||
* An interface dealing with color profiles.
|
||||
**/
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROFILE_CHANGED,
|
||||
SIMULATION_PROFILE_CHANGED,
|
||||
SIMULATION_INTENT_CHANGED,
|
||||
SIMULATION_BPC_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
||||
G_DEFINE_INTERFACE (PikaColorManaged, pika_color_managed, G_TYPE_OBJECT)
|
||||
|
||||
|
||||
static guint pika_color_managed_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
|
||||
static void
|
||||
pika_color_managed_default_init (PikaColorManagedInterface *iface)
|
||||
{
|
||||
pika_color_managed_signals[PROFILE_CHANGED] =
|
||||
g_signal_new ("profile-changed",
|
||||
G_TYPE_FROM_INTERFACE (iface),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PikaColorManagedInterface,
|
||||
profile_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
pika_color_managed_signals[SIMULATION_PROFILE_CHANGED] =
|
||||
g_signal_new ("simulation-profile-changed",
|
||||
G_TYPE_FROM_INTERFACE (iface),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PikaColorManagedInterface,
|
||||
simulation_profile_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
pika_color_managed_signals[SIMULATION_INTENT_CHANGED] =
|
||||
g_signal_new ("simulation-intent-changed",
|
||||
G_TYPE_FROM_INTERFACE (iface),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PikaColorManagedInterface,
|
||||
simulation_intent_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
pika_color_managed_signals[SIMULATION_BPC_CHANGED] =
|
||||
g_signal_new ("simulation-bpc-changed",
|
||||
G_TYPE_FROM_INTERFACE (iface),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PikaColorManagedInterface,
|
||||
simulation_bpc_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
|
||||
/**
|
||||
* pika_color_managed_get_icc_profile:
|
||||
* @managed: an object the implements the #PikaColorManaged interface
|
||||
* @len: (out): return location for the number of bytes in the profile data
|
||||
*
|
||||
* Returns: (array length=len): A blob of data that represents an ICC color
|
||||
* profile.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
const guint8 *
|
||||
pika_color_managed_get_icc_profile (PikaColorManaged *managed,
|
||||
gsize *len)
|
||||
{
|
||||
PikaColorManagedInterface *iface;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_MANAGED (managed), NULL);
|
||||
g_return_val_if_fail (len != NULL, NULL);
|
||||
|
||||
*len = 0;
|
||||
|
||||
iface = PIKA_COLOR_MANAGED_GET_IFACE (managed);
|
||||
|
||||
if (iface->get_icc_profile)
|
||||
return iface->get_icc_profile (managed, len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_managed_get_color_profile:
|
||||
* @managed: an object the implements the #PikaColorManaged interface
|
||||
*
|
||||
* This function always returns a #PikaColorProfile and falls back to
|
||||
* pika_color_profile_new_rgb_srgb() if the method is not implemented.
|
||||
*
|
||||
* Returns: (transfer full): The @managed's #PikaColorProfile.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
PikaColorProfile *
|
||||
pika_color_managed_get_color_profile (PikaColorManaged *managed)
|
||||
{
|
||||
PikaColorManagedInterface *iface;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_MANAGED (managed), NULL);
|
||||
|
||||
iface = PIKA_COLOR_MANAGED_GET_IFACE (managed);
|
||||
|
||||
if (iface->get_color_profile)
|
||||
return iface->get_color_profile (managed);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_managed_get_simulation_profile:
|
||||
* @managed: an object the implements the #PikaColorManaged interface
|
||||
*
|
||||
* This function always returns a #PikaColorProfile
|
||||
*
|
||||
* Returns: (transfer full): The @managed's simulation #PikaColorProfile.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
PikaColorProfile *
|
||||
pika_color_managed_get_simulation_profile (PikaColorManaged *managed)
|
||||
{
|
||||
PikaColorManagedInterface *iface;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_MANAGED (managed), NULL);
|
||||
|
||||
iface = PIKA_COLOR_MANAGED_GET_IFACE (managed);
|
||||
|
||||
if (iface->get_simulation_profile)
|
||||
return iface->get_simulation_profile (managed);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_managed_get_simulation_intent:
|
||||
* @managed: an object the implements the #PikaColorManaged interface
|
||||
*
|
||||
* This function always returns a #PikaColorRenderingIntent
|
||||
*
|
||||
* Returns: The @managed's simulation #PikaColorRenderingIntent.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
PikaColorRenderingIntent
|
||||
pika_color_managed_get_simulation_intent (PikaColorManaged *managed)
|
||||
{
|
||||
PikaColorManagedInterface *iface;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_MANAGED (managed),
|
||||
PIKA_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC);
|
||||
|
||||
iface = PIKA_COLOR_MANAGED_GET_IFACE (managed);
|
||||
|
||||
if (iface->get_simulation_intent)
|
||||
return iface->get_simulation_intent (managed);
|
||||
|
||||
return PIKA_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_managed_get_simulation_bpc:
|
||||
* @managed: an object the implements the #PikaColorManaged interface
|
||||
*
|
||||
* This function always returns a gboolean representing whether
|
||||
* Black Point Compensation is enabled
|
||||
*
|
||||
* Returns: The @managed's simulation Black Point Compensation value.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
gboolean
|
||||
pika_color_managed_get_simulation_bpc (PikaColorManaged *managed)
|
||||
{
|
||||
PikaColorManagedInterface *iface;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_MANAGED (managed), FALSE);
|
||||
|
||||
iface = PIKA_COLOR_MANAGED_GET_IFACE (managed);
|
||||
|
||||
if (iface->get_simulation_bpc)
|
||||
return iface->get_simulation_bpc (managed);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pika_color_managed_profile_changed:
|
||||
* @managed: an object that implements the #PikaColorManaged interface
|
||||
*
|
||||
* Emits the "profile-changed" signal.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
void
|
||||
pika_color_managed_profile_changed (PikaColorManaged *managed)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_COLOR_MANAGED (managed));
|
||||
|
||||
g_signal_emit (managed, pika_color_managed_signals[PROFILE_CHANGED], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_managed_simulation_profile_changed:
|
||||
* @managed: an object that implements the #PikaColorManaged interface
|
||||
*
|
||||
* Emits the "simulation-profile-changed" signal.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
void
|
||||
pika_color_managed_simulation_profile_changed (PikaColorManaged *managed)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_COLOR_MANAGED (managed));
|
||||
|
||||
g_signal_emit (managed, pika_color_managed_signals[SIMULATION_PROFILE_CHANGED], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_managed_simulation_intent_changed:
|
||||
* @managed: an object that implements the #PikaColorManaged interface
|
||||
*
|
||||
* Emits the "simulation-intent-changed" signal.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
void
|
||||
pika_color_managed_simulation_intent_changed (PikaColorManaged *managed)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_COLOR_MANAGED (managed));
|
||||
|
||||
g_signal_emit (managed, pika_color_managed_signals[SIMULATION_INTENT_CHANGED], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_managed_simulation_bpc_changed:
|
||||
* @managed: an object that implements the #PikaColorManaged interface
|
||||
*
|
||||
* Emits the "simulation-bpc-changed" signal.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
void
|
||||
pika_color_managed_simulation_bpc_changed (PikaColorManaged *managed)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_COLOR_MANAGED (managed));
|
||||
|
||||
g_signal_emit (managed, pika_color_managed_signals[SIMULATION_BPC_CHANGED], 0);
|
||||
}
|
109
libpikacolor/pikacolormanaged.h
Normal file
109
libpikacolor/pikacolormanaged.h
Normal file
@ -0,0 +1,109 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* PikaColorManaged interface
|
||||
* Copyright (C) 2007 Sven Neumann <sven@gimp.org>
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_COLOR_MANAGED_H__
|
||||
#define __PIKA_COLOR_MANAGED_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
#define PIKA_TYPE_COLOR_MANAGED (pika_color_managed_get_type ())
|
||||
G_DECLARE_INTERFACE (PikaColorManaged, pika_color_managed, PIKA, COLOR_MANAGED, GObject)
|
||||
|
||||
/**
|
||||
* PikaColorManagedInterface:
|
||||
* @base_iface: The parent interface
|
||||
* @get_icc_profile: Returns the ICC profile of the pixels managed by
|
||||
* the object
|
||||
* @profile_changed: This signal is emitted when the object's color profile
|
||||
* has changed
|
||||
* @get_color_profile: Returns the #PikaColorProfile of the pixels managed
|
||||
* by the object
|
||||
* @get_simulation_profile: Returns the simulation #PikaColorProfile of the
|
||||
* pixels managed by the object
|
||||
* @get_simulation_rendering_intent: Returns the simulation #PikaColorRenderingIntent
|
||||
* of the pixels managed by the object
|
||||
* @get_simulation_bpc: Returns whether black point compensation is enabled for the
|
||||
* simulation of the pixels managed by the object
|
||||
**/
|
||||
struct _PikaColorManagedInterface
|
||||
{
|
||||
GTypeInterface base_iface;
|
||||
|
||||
/**
|
||||
* PikaColorManagedInterface::get_icc_profile:
|
||||
* @managed: an object the implements the #PikaColorManaged interface
|
||||
* @len: (out): return location for the number of bytes in the profile data
|
||||
*
|
||||
* Returns: (array length=len): A blob of data that represents an ICC color
|
||||
* profile.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
const guint8 * (* get_icc_profile) (PikaColorManaged *managed,
|
||||
gsize *len);
|
||||
|
||||
/* signals */
|
||||
void (* profile_changed) (PikaColorManaged *managed);
|
||||
|
||||
void (* simulation_profile_changed) (PikaColorManaged *managed);
|
||||
|
||||
void (* simulation_intent_changed) (PikaColorManaged *managed);
|
||||
|
||||
void (* simulation_bpc_changed) (PikaColorManaged *managed);
|
||||
|
||||
/* virtual functions */
|
||||
PikaColorProfile * (* get_color_profile) (PikaColorManaged *managed);
|
||||
PikaColorProfile * (* get_simulation_profile) (PikaColorManaged *managed);
|
||||
PikaColorRenderingIntent
|
||||
(* get_simulation_intent) (PikaColorManaged *managed);
|
||||
gboolean (* get_simulation_bpc) (PikaColorManaged *managed);
|
||||
};
|
||||
|
||||
|
||||
const guint8 * pika_color_managed_get_icc_profile (PikaColorManaged *managed,
|
||||
gsize *len);
|
||||
PikaColorProfile * pika_color_managed_get_color_profile (PikaColorManaged *managed);
|
||||
|
||||
PikaColorProfile * pika_color_managed_get_simulation_profile (PikaColorManaged *managed);
|
||||
|
||||
PikaColorRenderingIntent pika_color_managed_get_simulation_intent (PikaColorManaged *managed);
|
||||
|
||||
gboolean pika_color_managed_get_simulation_bpc (PikaColorManaged *managed);
|
||||
|
||||
void pika_color_managed_profile_changed (PikaColorManaged *managed);
|
||||
|
||||
void pika_color_managed_simulation_profile_changed (PikaColorManaged *managed);
|
||||
|
||||
void pika_color_managed_simulation_intent_changed (PikaColorManaged *managed);
|
||||
|
||||
void pika_color_managed_simulation_bpc_changed (PikaColorManaged *managed);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_COLOR_MANAGED_IFACE_H__ */
|
1826
libpikacolor/pikacolorprofile.c
Normal file
1826
libpikacolor/pikacolorprofile.c
Normal file
File diff suppressed because it is too large
Load Diff
132
libpikacolor/pikacolorprofile.h
Normal file
132
libpikacolor/pikacolorprofile.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikacolorprofile.h
|
||||
* Copyright (C) 2014 Michael Natterer <mitch@gimp.org>
|
||||
* Elle Stone <ellestone@ninedegreesbelow.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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_COLOR_PROFILE_H__
|
||||
#define __PIKA_COLOR_PROFILE_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
#define PIKA_TYPE_COLOR_PROFILE (pika_color_profile_get_type ())
|
||||
#define PIKA_COLOR_PROFILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_COLOR_PROFILE, PikaColorProfile))
|
||||
#define PIKA_COLOR_PROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_COLOR_PROFILE, PikaColorProfileClass))
|
||||
#define PIKA_IS_COLOR_PROFILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_COLOR_PROFILE))
|
||||
#define PIKA_IS_COLOR_PROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_COLOR_PROFILE))
|
||||
#define PIKA_COLOR_PROFILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_COLOR_PROFILE, PikaColorProfileClass))
|
||||
|
||||
|
||||
typedef struct _PikaColorProfilePrivate PikaColorProfilePrivate;
|
||||
typedef struct _PikaColorProfileClass PikaColorProfileClass;
|
||||
|
||||
struct _PikaColorProfile
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
PikaColorProfilePrivate *priv;
|
||||
};
|
||||
|
||||
struct _PikaColorProfileClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (* _pika_reserved1) (void);
|
||||
void (* _pika_reserved2) (void);
|
||||
void (* _pika_reserved3) (void);
|
||||
void (* _pika_reserved4) (void);
|
||||
void (* _pika_reserved5) (void);
|
||||
void (* _pika_reserved6) (void);
|
||||
void (* _pika_reserved7) (void);
|
||||
void (* _pika_reserved8) (void);
|
||||
};
|
||||
|
||||
|
||||
GType pika_color_profile_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaColorProfile * pika_color_profile_new_rgb_srgb (void);
|
||||
PikaColorProfile * pika_color_profile_new_rgb_srgb_linear (void);
|
||||
PikaColorProfile * pika_color_profile_new_rgb_adobe (void);
|
||||
|
||||
PikaColorProfile * pika_color_profile_new_d65_gray_srgb_trc (void);
|
||||
PikaColorProfile * pika_color_profile_new_d65_gray_linear (void);
|
||||
PikaColorProfile * pika_color_profile_new_d50_gray_lab_trc (void);
|
||||
|
||||
PikaColorProfile *
|
||||
pika_color_profile_new_srgb_trc_from_color_profile (PikaColorProfile *profile);
|
||||
PikaColorProfile *
|
||||
pika_color_profile_new_linear_from_color_profile (PikaColorProfile *profile);
|
||||
|
||||
PikaColorProfile * pika_color_profile_new_from_file (GFile *file,
|
||||
GError **error);
|
||||
|
||||
PikaColorProfile * pika_color_profile_new_from_icc_profile (const guint8 *data,
|
||||
gsize length,
|
||||
GError **error);
|
||||
PikaColorProfile * pika_color_profile_new_from_lcms_profile (gpointer lcms_profile,
|
||||
GError **error);
|
||||
|
||||
gboolean pika_color_profile_save_to_file (PikaColorProfile *profile,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
|
||||
const guint8 * pika_color_profile_get_icc_profile (PikaColorProfile *profile,
|
||||
gsize *length);
|
||||
gpointer pika_color_profile_get_lcms_profile (PikaColorProfile *profile);
|
||||
|
||||
const gchar * pika_color_profile_get_description (PikaColorProfile *profile);
|
||||
const gchar * pika_color_profile_get_manufacturer (PikaColorProfile *profile);
|
||||
const gchar * pika_color_profile_get_model (PikaColorProfile *profile);
|
||||
const gchar * pika_color_profile_get_copyright (PikaColorProfile *profile);
|
||||
|
||||
const gchar * pika_color_profile_get_label (PikaColorProfile *profile);
|
||||
const gchar * pika_color_profile_get_summary (PikaColorProfile *profile);
|
||||
|
||||
gboolean pika_color_profile_is_equal (PikaColorProfile *profile1,
|
||||
PikaColorProfile *profile2);
|
||||
|
||||
gboolean pika_color_profile_is_rgb (PikaColorProfile *profile);
|
||||
gboolean pika_color_profile_is_gray (PikaColorProfile *profile);
|
||||
gboolean pika_color_profile_is_cmyk (PikaColorProfile *profile);
|
||||
|
||||
gboolean pika_color_profile_is_linear (PikaColorProfile *profile);
|
||||
|
||||
const Babl * pika_color_profile_get_space (PikaColorProfile *profile,
|
||||
PikaColorRenderingIntent intent,
|
||||
GError **error);
|
||||
const Babl * pika_color_profile_get_format (PikaColorProfile *profile,
|
||||
const Babl *format,
|
||||
PikaColorRenderingIntent intent,
|
||||
GError **error);
|
||||
|
||||
const Babl * pika_color_profile_get_lcms_format (const Babl *format,
|
||||
guint32 *lcms_format);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_COLOR_PROFILE_H__ */
|
401
libpikacolor/pikacolorspace.c
Normal file
401
libpikacolor/pikacolorspace.c
Normal file
@ -0,0 +1,401 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <babl/babl.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikacolorspace.h"
|
||||
#include "pikargb.h"
|
||||
#include "pikahsv.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikacolorspace
|
||||
* @title: PikaColorSpace
|
||||
* @short_description: Utility functions which convert colors between
|
||||
* different color models.
|
||||
*
|
||||
* When programming pixel data manipulation functions you will often
|
||||
* use algorithms operating on a color model different from the one
|
||||
* PIKA uses. This file provides utility functions to convert colors
|
||||
* between different color spaces.
|
||||
**/
|
||||
|
||||
|
||||
#define PIKA_HSL_UNDEFINED -1.0
|
||||
|
||||
|
||||
/* PikaRGB functions */
|
||||
|
||||
|
||||
/**
|
||||
* pika_rgb_to_hsv:
|
||||
* @rgb: A color value in the RGB colorspace
|
||||
* @hsv: (out caller-allocates): The value converted to the HSV colorspace
|
||||
*
|
||||
* Does a conversion from RGB to HSV (Hue, Saturation,
|
||||
* Value) colorspace.
|
||||
**/
|
||||
void
|
||||
pika_rgb_to_hsv (const PikaRGB *rgb,
|
||||
PikaHSV *hsv)
|
||||
{
|
||||
gdouble max, min, delta;
|
||||
|
||||
g_return_if_fail (rgb != NULL);
|
||||
g_return_if_fail (hsv != NULL);
|
||||
|
||||
max = pika_rgb_max (rgb);
|
||||
min = pika_rgb_min (rgb);
|
||||
|
||||
hsv->v = max;
|
||||
delta = max - min;
|
||||
|
||||
if (delta > 0.0001)
|
||||
{
|
||||
hsv->s = delta / max;
|
||||
|
||||
if (rgb->r == max)
|
||||
{
|
||||
hsv->h = (rgb->g - rgb->b) / delta;
|
||||
if (hsv->h < 0.0)
|
||||
hsv->h += 6.0;
|
||||
}
|
||||
else if (rgb->g == max)
|
||||
{
|
||||
hsv->h = 2.0 + (rgb->b - rgb->r) / delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsv->h = 4.0 + (rgb->r - rgb->g) / delta;
|
||||
}
|
||||
|
||||
hsv->h /= 6.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsv->s = 0.0;
|
||||
hsv->h = 0.0;
|
||||
}
|
||||
|
||||
hsv->a = rgb->a;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_hsv_to_rgb:
|
||||
* @hsv: A color value in the HSV colorspace
|
||||
* @rgb: (out caller-allocates): The returned RGB value.
|
||||
*
|
||||
* Converts a color value from HSV to RGB colorspace
|
||||
**/
|
||||
void
|
||||
pika_hsv_to_rgb (const PikaHSV *hsv,
|
||||
PikaRGB *rgb)
|
||||
{
|
||||
gint i;
|
||||
gdouble f, w, q, t;
|
||||
|
||||
gdouble hue;
|
||||
|
||||
g_return_if_fail (rgb != NULL);
|
||||
g_return_if_fail (hsv != NULL);
|
||||
|
||||
if (hsv->s == 0.0)
|
||||
{
|
||||
rgb->r = hsv->v;
|
||||
rgb->g = hsv->v;
|
||||
rgb->b = hsv->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
hue = hsv->h;
|
||||
|
||||
if (hue == 1.0)
|
||||
hue = 0.0;
|
||||
|
||||
hue *= 6.0;
|
||||
|
||||
i = (gint) hue;
|
||||
f = hue - i;
|
||||
w = hsv->v * (1.0 - hsv->s);
|
||||
q = hsv->v * (1.0 - (hsv->s * f));
|
||||
t = hsv->v * (1.0 - (hsv->s * (1.0 - f)));
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
rgb->r = hsv->v;
|
||||
rgb->g = t;
|
||||
rgb->b = w;
|
||||
break;
|
||||
case 1:
|
||||
rgb->r = q;
|
||||
rgb->g = hsv->v;
|
||||
rgb->b = w;
|
||||
break;
|
||||
case 2:
|
||||
rgb->r = w;
|
||||
rgb->g = hsv->v;
|
||||
rgb->b = t;
|
||||
break;
|
||||
case 3:
|
||||
rgb->r = w;
|
||||
rgb->g = q;
|
||||
rgb->b = hsv->v;
|
||||
break;
|
||||
case 4:
|
||||
rgb->r = t;
|
||||
rgb->g = w;
|
||||
rgb->b = hsv->v;
|
||||
break;
|
||||
case 5:
|
||||
rgb->r = hsv->v;
|
||||
rgb->g = w;
|
||||
rgb->b = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rgb->a = hsv->a;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pika_rgb_to_hsl:
|
||||
* @rgb: A color value in the RGB colorspace
|
||||
* @hsl: (out caller-allocates): The value converted to HSL
|
||||
*
|
||||
* Convert an RGB color value to a HSL (Hue, Saturation, Lightness)
|
||||
* color value.
|
||||
**/
|
||||
void
|
||||
pika_rgb_to_hsl (const PikaRGB *rgb,
|
||||
PikaHSL *hsl)
|
||||
{
|
||||
gdouble max, min, delta;
|
||||
|
||||
g_return_if_fail (rgb != NULL);
|
||||
g_return_if_fail (hsl != NULL);
|
||||
|
||||
max = pika_rgb_max (rgb);
|
||||
min = pika_rgb_min (rgb);
|
||||
|
||||
hsl->l = (max + min) / 2.0;
|
||||
|
||||
if (max == min)
|
||||
{
|
||||
hsl->s = 0.0;
|
||||
hsl->h = PIKA_HSL_UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hsl->l <= 0.5)
|
||||
hsl->s = (max - min) / (max + min);
|
||||
else
|
||||
hsl->s = (max - min) / (2.0 - max - min);
|
||||
|
||||
delta = max - min;
|
||||
|
||||
if (delta == 0.0)
|
||||
delta = 1.0;
|
||||
|
||||
if (rgb->r == max)
|
||||
{
|
||||
hsl->h = (rgb->g - rgb->b) / delta;
|
||||
}
|
||||
else if (rgb->g == max)
|
||||
{
|
||||
hsl->h = 2.0 + (rgb->b - rgb->r) / delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsl->h = 4.0 + (rgb->r - rgb->g) / delta;
|
||||
}
|
||||
|
||||
hsl->h /= 6.0;
|
||||
|
||||
if (hsl->h < 0.0)
|
||||
hsl->h += 1.0;
|
||||
}
|
||||
|
||||
hsl->a = rgb->a;
|
||||
}
|
||||
|
||||
static inline gdouble
|
||||
pika_hsl_value (gdouble n1,
|
||||
gdouble n2,
|
||||
gdouble hue)
|
||||
{
|
||||
gdouble val;
|
||||
|
||||
if (hue > 6.0)
|
||||
hue -= 6.0;
|
||||
else if (hue < 0.0)
|
||||
hue += 6.0;
|
||||
|
||||
if (hue < 1.0)
|
||||
val = n1 + (n2 - n1) * hue;
|
||||
else if (hue < 3.0)
|
||||
val = n2;
|
||||
else if (hue < 4.0)
|
||||
val = n1 + (n2 - n1) * (4.0 - hue);
|
||||
else
|
||||
val = n1;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pika_hsl_to_rgb:
|
||||
* @hsl: A color value in the HSL colorspace
|
||||
* @rgb: (out caller-allocates): The value converted to a value
|
||||
* in the RGB colorspace
|
||||
*
|
||||
* Convert a HSL color value to an RGB color value.
|
||||
**/
|
||||
void
|
||||
pika_hsl_to_rgb (const PikaHSL *hsl,
|
||||
PikaRGB *rgb)
|
||||
{
|
||||
g_return_if_fail (hsl != NULL);
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
if (hsl->s == 0)
|
||||
{
|
||||
/* achromatic case */
|
||||
rgb->r = hsl->l;
|
||||
rgb->g = hsl->l;
|
||||
rgb->b = hsl->l;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble m1, m2;
|
||||
|
||||
if (hsl->l <= 0.5)
|
||||
m2 = hsl->l * (1.0 + hsl->s);
|
||||
else
|
||||
m2 = hsl->l + hsl->s - hsl->l * hsl->s;
|
||||
|
||||
m1 = 2.0 * hsl->l - m2;
|
||||
|
||||
rgb->r = pika_hsl_value (m1, m2, hsl->h * 6.0 + 2.0);
|
||||
rgb->g = pika_hsl_value (m1, m2, hsl->h * 6.0);
|
||||
rgb->b = pika_hsl_value (m1, m2, hsl->h * 6.0 - 2.0);
|
||||
}
|
||||
|
||||
rgb->a = hsl->a;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pika_rgb_to_cmyk:
|
||||
* @rgb: A value in the RGB colorspace
|
||||
* @pullout: A scaling value (0-1) indicating how much black should be
|
||||
* pulled out
|
||||
* @cmyk: (out caller-allocates): The input value naively converted
|
||||
* to the CMYK colorspace
|
||||
*
|
||||
* Does a naive conversion from RGB to CMYK colorspace. A simple
|
||||
* formula that doesn't take any color-profiles into account is used.
|
||||
* The amount of black pullout how can be controlled via the @pullout
|
||||
* parameter. A @pullout value of 0 makes this a conversion to CMY.
|
||||
* A value of 1 causes the maximum amount of black to be pulled out.
|
||||
**/
|
||||
void
|
||||
pika_rgb_to_cmyk (const PikaRGB *rgb,
|
||||
gdouble pullout,
|
||||
PikaCMYK *cmyk)
|
||||
{
|
||||
gdouble c, m, y, k;
|
||||
|
||||
g_return_if_fail (rgb != NULL);
|
||||
g_return_if_fail (cmyk != NULL);
|
||||
|
||||
c = 1.0 - rgb->r;
|
||||
m = 1.0 - rgb->g;
|
||||
y = 1.0 - rgb->b;
|
||||
|
||||
k = 1.0;
|
||||
if (c < k) k = c;
|
||||
if (m < k) k = m;
|
||||
if (y < k) k = y;
|
||||
|
||||
k *= pullout;
|
||||
|
||||
if (k < 1.0)
|
||||
{
|
||||
cmyk->c = (c - k) / (1.0 - k);
|
||||
cmyk->m = (m - k) / (1.0 - k);
|
||||
cmyk->y = (y - k) / (1.0 - k);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmyk->c = 0.0;
|
||||
cmyk->m = 0.0;
|
||||
cmyk->y = 0.0;
|
||||
}
|
||||
|
||||
cmyk->k = k;
|
||||
cmyk->a = rgb->a;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_cmyk_to_rgb:
|
||||
* @cmyk: A color value in the CMYK colorspace
|
||||
* @rgb: (out caller-allocates): The value converted to the RGB colorspace
|
||||
*
|
||||
* Does a simple transformation from the CMYK colorspace to the RGB
|
||||
* colorspace, without taking color profiles into account.
|
||||
**/
|
||||
void
|
||||
pika_cmyk_to_rgb (const PikaCMYK *cmyk,
|
||||
PikaRGB *rgb)
|
||||
{
|
||||
gdouble c, m, y, k;
|
||||
|
||||
g_return_if_fail (cmyk != NULL);
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
k = cmyk->k;
|
||||
|
||||
if (k < 1.0)
|
||||
{
|
||||
c = cmyk->c * (1.0 - k) + k;
|
||||
m = cmyk->m * (1.0 - k) + k;
|
||||
y = cmyk->y * (1.0 - k) + k;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = 1.0;
|
||||
m = 1.0;
|
||||
y = 1.0;
|
||||
}
|
||||
|
||||
rgb->r = 1.0 - c;
|
||||
rgb->g = 1.0 - m;
|
||||
rgb->b = 1.0 - y;
|
||||
rgb->a = cmyk->a;
|
||||
}
|
53
libpikacolor/pikacolorspace.h
Normal file
53
libpikacolor/pikacolorspace.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_COLOR_SPACE_H__
|
||||
#define __PIKA_COLOR_SPACE_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
/* Color conversion routines */
|
||||
|
||||
|
||||
/* PikaRGB function */
|
||||
|
||||
void pika_rgb_to_hsv (const PikaRGB *rgb,
|
||||
PikaHSV *hsv);
|
||||
void pika_rgb_to_hsl (const PikaRGB *rgb,
|
||||
PikaHSL *hsl);
|
||||
void pika_rgb_to_cmyk (const PikaRGB *rgb,
|
||||
gdouble pullout,
|
||||
PikaCMYK *cmyk);
|
||||
|
||||
void pika_hsv_to_rgb (const PikaHSV *hsv,
|
||||
PikaRGB *rgb);
|
||||
void pika_hsl_to_rgb (const PikaHSL *hsl,
|
||||
PikaRGB *rgb);
|
||||
void pika_cmyk_to_rgb (const PikaCMYK *cmyk,
|
||||
PikaRGB *rgb);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_COLOR_SPACE_H__ */
|
642
libpikacolor/pikacolortransform.c
Normal file
642
libpikacolor/pikacolortransform.c
Normal file
@ -0,0 +1,642 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikacolortransform.c
|
||||
* Copyright (C) 2014 Michael Natterer <mitch@gimp.org>
|
||||
* Elle Stone <ellestone@ninedegreesbelow.com>
|
||||
* Øyvind Kolås <pippin@gimp.org>
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <lcms2.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikacolorprofile.h"
|
||||
#include "pikacolortransform.h"
|
||||
|
||||
#include "libpika/libpika-intl.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikacolortransform
|
||||
* @title: PikaColorTransform
|
||||
* @short_description: Definitions and Functions relating to LCMS.
|
||||
*
|
||||
* Definitions and Functions relating to LCMS.
|
||||
**/
|
||||
|
||||
/**
|
||||
* PikaColorTransform:
|
||||
*
|
||||
* Simply a typedef to #gpointer, but actually is a cmsHTRANSFORM. It's
|
||||
* used in public PIKA APIs in order to avoid having to include LCMS
|
||||
* headers.
|
||||
**/
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROGRESS,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
||||
struct _PikaColorTransformPrivate
|
||||
{
|
||||
PikaColorProfile *src_profile;
|
||||
const Babl *src_format;
|
||||
|
||||
PikaColorProfile *dest_profile;
|
||||
const Babl *dest_format;
|
||||
|
||||
cmsHTRANSFORM transform;
|
||||
const Babl *fish;
|
||||
};
|
||||
|
||||
|
||||
static void pika_color_transform_finalize (GObject *object);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (PikaColorTransform, pika_color_transform,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
#define parent_class pika_color_transform_parent_class
|
||||
|
||||
static guint pika_color_transform_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static gchar *lcms_last_error = NULL;
|
||||
|
||||
|
||||
static void
|
||||
lcms_error_clear (void)
|
||||
{
|
||||
if (lcms_last_error)
|
||||
{
|
||||
g_free (lcms_last_error);
|
||||
lcms_last_error = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lcms_error_handler (cmsContext ContextID,
|
||||
cmsUInt32Number ErrorCode,
|
||||
const gchar *text)
|
||||
{
|
||||
lcms_error_clear ();
|
||||
|
||||
lcms_last_error = g_strdup_printf ("lcms2 error %d: %s", ErrorCode, text);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_transform_class_init (PikaColorTransformClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_color_transform_finalize;
|
||||
|
||||
pika_color_transform_signals[PROGRESS] =
|
||||
g_signal_new ("progress",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PikaColorTransformClass,
|
||||
progress),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_DOUBLE);
|
||||
|
||||
cmsSetLogErrorHandler (lcms_error_handler);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_transform_init (PikaColorTransform *transform)
|
||||
{
|
||||
transform->priv = pika_color_transform_get_instance_private (transform);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_transform_finalize (GObject *object)
|
||||
{
|
||||
PikaColorTransform *transform = PIKA_COLOR_TRANSFORM (object);
|
||||
|
||||
g_clear_object (&transform->priv->src_profile);
|
||||
g_clear_object (&transform->priv->dest_profile);
|
||||
|
||||
g_clear_pointer (&transform->priv->transform, cmsDeleteTransform);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pika_color_transform_new:
|
||||
* @src_profile: the source #PikaColorProfile
|
||||
* @src_format: the source #Babl format
|
||||
* @dest_profile: the destination #PikaColorProfile
|
||||
* @dest_format: the destination #Babl format
|
||||
* @rendering_intent: the rendering intent
|
||||
* @flags: transform flags
|
||||
*
|
||||
* This function creates an color transform.
|
||||
*
|
||||
* The color transform is determined exclusively by @src_profile and
|
||||
* @dest_profile. The color spaces of @src_format and @dest_format are
|
||||
* ignored, the formats are only used to decide between what pixel
|
||||
* encodings to transform.
|
||||
*
|
||||
* Note: this function used to return %NULL if
|
||||
* pika_color_transform_can_gegl_copy() returned %TRUE for
|
||||
* @src_profile and @dest_profile. This is no longer the case because
|
||||
* special care has to be taken not to perform multiple implicit color
|
||||
* transforms caused by babl formats with color spaces. Now, it always
|
||||
* returns a non-%NULL transform and the code takes care of doing only
|
||||
* exactly the requested color transform.
|
||||
*
|
||||
* Returns: (nullable): the #PikaColorTransform, or %NULL if there was an error.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
PikaColorTransform *
|
||||
pika_color_transform_new (PikaColorProfile *src_profile,
|
||||
const Babl *src_format,
|
||||
PikaColorProfile *dest_profile,
|
||||
const Babl *dest_format,
|
||||
PikaColorRenderingIntent rendering_intent,
|
||||
PikaColorTransformFlags flags)
|
||||
{
|
||||
PikaColorTransform *transform;
|
||||
PikaColorTransformPrivate *priv;
|
||||
cmsHPROFILE src_lcms;
|
||||
cmsHPROFILE dest_lcms;
|
||||
cmsUInt32Number lcms_src_format;
|
||||
cmsUInt32Number lcms_dest_format;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_PROFILE (src_profile), NULL);
|
||||
g_return_val_if_fail (src_format != NULL, NULL);
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_PROFILE (dest_profile), NULL);
|
||||
g_return_val_if_fail (dest_format != NULL, NULL);
|
||||
|
||||
transform = g_object_new (PIKA_TYPE_COLOR_TRANSFORM, NULL);
|
||||
|
||||
priv = transform->priv;
|
||||
|
||||
/* only src_profile and dest_profile must determine the transform's
|
||||
* color spaces, create formats with src_format's and dest_format's
|
||||
* encoding, and the profiles' color spaces; see process_pixels()
|
||||
* and process_buffer().
|
||||
*/
|
||||
|
||||
priv->src_format = pika_color_profile_get_format (src_profile,
|
||||
src_format,
|
||||
PIKA_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
|
||||
&error);
|
||||
if (! priv->src_format)
|
||||
{
|
||||
g_printerr ("%s: error making src format: %s\n",
|
||||
G_STRFUNC, error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
priv->dest_format = pika_color_profile_get_format (dest_profile,
|
||||
dest_format,
|
||||
rendering_intent,
|
||||
&error);
|
||||
if (! priv->dest_format)
|
||||
{
|
||||
g_printerr ("%s: error making dest format: %s\n",
|
||||
G_STRFUNC, error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
if (! g_getenv ("PIKA_COLOR_TRANSFORM_DISABLE_BABL") &&
|
||||
priv->src_format && priv->dest_format)
|
||||
{
|
||||
priv->fish = babl_fish (priv->src_format,
|
||||
priv->dest_format);
|
||||
|
||||
g_debug ("%s: using babl for '%s' -> '%s'",
|
||||
G_STRFUNC,
|
||||
pika_color_profile_get_label (src_profile),
|
||||
pika_color_profile_get_label (dest_profile));
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
/* see above: when using lcms, don't mess with formats with color
|
||||
* spaces, pika_color_profile_get_lcms_format() might return the
|
||||
* same format and it must be without space
|
||||
*/
|
||||
src_format = babl_format_with_space ((const gchar *) src_format, NULL);
|
||||
dest_format = babl_format_with_space ((const gchar *) dest_format, NULL);
|
||||
|
||||
priv->src_format = pika_color_profile_get_lcms_format (src_format,
|
||||
&lcms_src_format);
|
||||
priv->dest_format = pika_color_profile_get_lcms_format (dest_format,
|
||||
&lcms_dest_format);
|
||||
|
||||
src_lcms = pika_color_profile_get_lcms_profile (src_profile);
|
||||
dest_lcms = pika_color_profile_get_lcms_profile (dest_profile);
|
||||
|
||||
lcms_error_clear ();
|
||||
|
||||
priv->transform = cmsCreateTransform (src_lcms, lcms_src_format,
|
||||
dest_lcms, lcms_dest_format,
|
||||
rendering_intent,
|
||||
flags |
|
||||
cmsFLAGS_COPY_ALPHA);
|
||||
|
||||
if (lcms_last_error)
|
||||
{
|
||||
if (priv->transform)
|
||||
{
|
||||
cmsDeleteTransform (priv->transform);
|
||||
priv->transform = NULL;
|
||||
}
|
||||
|
||||
g_printerr ("%s: %s\n", G_STRFUNC, lcms_last_error);
|
||||
}
|
||||
|
||||
if (! priv->transform)
|
||||
{
|
||||
g_object_unref (transform);
|
||||
transform = NULL;
|
||||
}
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_transform_new_proofing:
|
||||
* @src_profile: the source #PikaColorProfile
|
||||
* @src_format: the source #Babl format
|
||||
* @dest_profile: the destination #PikaColorProfile
|
||||
* @dest_format: the destination #Babl format
|
||||
* @proof_profile: the proof #PikaColorProfile
|
||||
* @proof_intent: the proof intent
|
||||
* @display_intent: the display intent
|
||||
* @flags: transform flags
|
||||
*
|
||||
* This function creates a simulation / proofing color transform.
|
||||
*
|
||||
* See pika_color_transform_new() about the color spaces to transform
|
||||
* between.
|
||||
*
|
||||
* Returns: (nullable): the #PikaColorTransform, or %NULL if there was an error.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
PikaColorTransform *
|
||||
pika_color_transform_new_proofing (PikaColorProfile *src_profile,
|
||||
const Babl *src_format,
|
||||
PikaColorProfile *dest_profile,
|
||||
const Babl *dest_format,
|
||||
PikaColorProfile *proof_profile,
|
||||
PikaColorRenderingIntent proof_intent,
|
||||
PikaColorRenderingIntent display_intent,
|
||||
PikaColorTransformFlags flags)
|
||||
{
|
||||
PikaColorTransform *transform;
|
||||
PikaColorTransformPrivate *priv;
|
||||
cmsHPROFILE src_lcms;
|
||||
cmsHPROFILE dest_lcms;
|
||||
cmsHPROFILE proof_lcms;
|
||||
cmsUInt32Number lcms_src_format;
|
||||
cmsUInt32Number lcms_dest_format;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_PROFILE (src_profile), NULL);
|
||||
g_return_val_if_fail (src_format != NULL, NULL);
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_PROFILE (dest_profile), NULL);
|
||||
g_return_val_if_fail (dest_format != NULL, NULL);
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_PROFILE (proof_profile), NULL);
|
||||
|
||||
transform = g_object_new (PIKA_TYPE_COLOR_TRANSFORM, NULL);
|
||||
|
||||
priv = transform->priv;
|
||||
|
||||
src_lcms = pika_color_profile_get_lcms_profile (src_profile);
|
||||
dest_lcms = pika_color_profile_get_lcms_profile (dest_profile);
|
||||
proof_lcms = pika_color_profile_get_lcms_profile (proof_profile);
|
||||
|
||||
/* see pika_color_transform_new(), we can't have color spaces
|
||||
* on the formats
|
||||
*/
|
||||
src_format = babl_format_with_space ((const gchar *) src_format, NULL);
|
||||
dest_format = babl_format_with_space ((const gchar *) dest_format, NULL);
|
||||
|
||||
priv->src_format = pika_color_profile_get_lcms_format (src_format,
|
||||
&lcms_src_format);
|
||||
priv->dest_format = pika_color_profile_get_lcms_format (dest_format,
|
||||
&lcms_dest_format);
|
||||
|
||||
lcms_error_clear ();
|
||||
|
||||
priv->transform = cmsCreateProofingTransform (src_lcms, lcms_src_format,
|
||||
dest_lcms, lcms_dest_format,
|
||||
proof_lcms,
|
||||
display_intent,
|
||||
proof_intent,
|
||||
flags |
|
||||
cmsFLAGS_SOFTPROOFING |
|
||||
cmsFLAGS_COPY_ALPHA);
|
||||
|
||||
if (lcms_last_error)
|
||||
{
|
||||
if (priv->transform)
|
||||
{
|
||||
cmsDeleteTransform (priv->transform);
|
||||
priv->transform = NULL;
|
||||
}
|
||||
|
||||
g_printerr ("%s: %s\n", G_STRFUNC, lcms_last_error);
|
||||
}
|
||||
|
||||
if (! priv->transform)
|
||||
{
|
||||
g_object_unref (transform);
|
||||
transform = NULL;
|
||||
}
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_transform_process_pixels:
|
||||
* @transform: a #PikaColorTransform
|
||||
* @src_format: #Babl format of @src_pixels
|
||||
* @src_pixels: pointer to the source pixels
|
||||
* @dest_format: #Babl format of @dest_pixels
|
||||
* @dest_pixels: pointer to the destination pixels
|
||||
* @length: number of pixels to process
|
||||
*
|
||||
* This function transforms a contiguous line of pixels.
|
||||
*
|
||||
* See pika_color_transform_new(): only the pixel encoding of
|
||||
* @src_format and @dest_format is honored, their color spaces are
|
||||
* ignored. The transform always takes place between the color spaces
|
||||
* determined by @transform's color profiles.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
void
|
||||
pika_color_transform_process_pixels (PikaColorTransform *transform,
|
||||
const Babl *src_format,
|
||||
gconstpointer src_pixels,
|
||||
const Babl *dest_format,
|
||||
gpointer dest_pixels,
|
||||
gsize length)
|
||||
{
|
||||
PikaColorTransformPrivate *priv;
|
||||
gpointer *src;
|
||||
gpointer *dest;
|
||||
|
||||
g_return_if_fail (PIKA_IS_COLOR_TRANSFORM (transform));
|
||||
g_return_if_fail (src_format != NULL);
|
||||
g_return_if_fail (src_pixels != NULL);
|
||||
g_return_if_fail (dest_format != NULL);
|
||||
g_return_if_fail (dest_pixels != NULL);
|
||||
|
||||
priv = transform->priv;
|
||||
|
||||
/* we must not do any babl color transforms when reading from
|
||||
* src_pixels or writing to dest_pixels, so construct formats with
|
||||
* src_format's and dest_format's encoding, and the transform's
|
||||
* input and output color spaces.
|
||||
*/
|
||||
src_format =
|
||||
babl_format_with_space ((const gchar *) src_format,
|
||||
babl_format_get_space (priv->src_format));
|
||||
dest_format =
|
||||
babl_format_with_space ((const gchar *) dest_format,
|
||||
babl_format_get_space (priv->dest_format));
|
||||
|
||||
if (src_format != priv->src_format)
|
||||
{
|
||||
src = g_malloc (length * babl_format_get_bytes_per_pixel (priv->src_format));
|
||||
|
||||
babl_process (babl_fish (src_format,
|
||||
priv->src_format),
|
||||
src_pixels, src, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
src = (gpointer) src_pixels;
|
||||
}
|
||||
|
||||
if (dest_format != priv->dest_format)
|
||||
{
|
||||
dest = g_malloc (length * babl_format_get_bytes_per_pixel (priv->dest_format));
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = dest_pixels;
|
||||
}
|
||||
|
||||
if (priv->transform)
|
||||
{
|
||||
cmsDoTransform (priv->transform, src, dest, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
babl_process (priv->fish, src, dest, length);
|
||||
}
|
||||
|
||||
if (src_format != priv->src_format)
|
||||
{
|
||||
g_free (src);
|
||||
}
|
||||
|
||||
if (dest_format != priv->dest_format)
|
||||
{
|
||||
babl_process (babl_fish (priv->dest_format,
|
||||
dest_format),
|
||||
dest, dest_pixels, length);
|
||||
|
||||
g_free (dest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_transform_process_buffer:
|
||||
* @transform: a #PikaColorTransform
|
||||
* @src_buffer: source #GeglBuffer
|
||||
* @src_rect: rectangle in @src_buffer
|
||||
* @dest_buffer: destination #GeglBuffer
|
||||
* @dest_rect: rectangle in @dest_buffer
|
||||
*
|
||||
* This function transforms buffer into another buffer.
|
||||
*
|
||||
* See pika_color_transform_new(): only the pixel encoding of
|
||||
* @src_buffer's and @dest_buffer's formats honored, their color
|
||||
* spaces are ignored. The transform always takes place between the
|
||||
* color spaces determined by @transform's color profiles.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
void
|
||||
pika_color_transform_process_buffer (PikaColorTransform *transform,
|
||||
GeglBuffer *src_buffer,
|
||||
const GeglRectangle *src_rect,
|
||||
GeglBuffer *dest_buffer,
|
||||
const GeglRectangle *dest_rect)
|
||||
{
|
||||
PikaColorTransformPrivate *priv;
|
||||
const Babl *src_format;
|
||||
const Babl *dest_format;
|
||||
GeglBufferIterator *iter;
|
||||
gint total_pixels;
|
||||
gint done_pixels = 0;
|
||||
|
||||
g_return_if_fail (PIKA_IS_COLOR_TRANSFORM (transform));
|
||||
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
|
||||
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
|
||||
|
||||
priv = transform->priv;
|
||||
|
||||
if (src_rect)
|
||||
{
|
||||
total_pixels = src_rect->width * src_rect->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
total_pixels = (gegl_buffer_get_width (src_buffer) *
|
||||
gegl_buffer_get_height (src_buffer));
|
||||
}
|
||||
|
||||
/* we must not do any babl color transforms when reading from
|
||||
* src_buffer or writing to dest_buffer, so construct formats with
|
||||
* the transform's expected input and output encoding and
|
||||
* src_buffer's and dest_buffers's color spaces.
|
||||
*/
|
||||
src_format = gegl_buffer_get_format (src_buffer);
|
||||
dest_format = gegl_buffer_get_format (dest_buffer);
|
||||
|
||||
src_format =
|
||||
babl_format_with_space ((const gchar *) priv->src_format,
|
||||
babl_format_get_space (src_format));
|
||||
dest_format =
|
||||
babl_format_with_space ((const gchar *) priv->dest_format,
|
||||
babl_format_get_space (dest_format));
|
||||
|
||||
if (src_buffer != dest_buffer)
|
||||
{
|
||||
iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0,
|
||||
src_format,
|
||||
GEGL_ACCESS_READ,
|
||||
GEGL_ABYSS_NONE, 2);
|
||||
|
||||
gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0,
|
||||
dest_format,
|
||||
GEGL_ACCESS_WRITE,
|
||||
GEGL_ABYSS_NONE);
|
||||
|
||||
while (gegl_buffer_iterator_next (iter))
|
||||
{
|
||||
if (priv->transform)
|
||||
{
|
||||
cmsDoTransform (priv->transform,
|
||||
iter->items[0].data, iter->items[1].data, iter->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
babl_process (priv->fish,
|
||||
iter->items[0].data, iter->items[1].data, iter->length);
|
||||
}
|
||||
|
||||
done_pixels += iter->items[0].roi.width * iter->items[0].roi.height;
|
||||
|
||||
g_signal_emit (transform, pika_color_transform_signals[PROGRESS], 0,
|
||||
(gdouble) done_pixels /
|
||||
(gdouble) total_pixels);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0,
|
||||
src_format,
|
||||
GEGL_ACCESS_READWRITE,
|
||||
GEGL_ABYSS_NONE, 1);
|
||||
|
||||
while (gegl_buffer_iterator_next (iter))
|
||||
{
|
||||
if (priv->transform)
|
||||
{
|
||||
cmsDoTransform (priv->transform,
|
||||
iter->items[0].data, iter->items[0].data, iter->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
babl_process (priv->fish,
|
||||
iter->items[0].data, iter->items[0].data, iter->length);
|
||||
}
|
||||
|
||||
done_pixels += iter->items[0].roi.width * iter->items[0].roi.height;
|
||||
|
||||
g_signal_emit (transform, pika_color_transform_signals[PROGRESS], 0,
|
||||
(gdouble) done_pixels /
|
||||
(gdouble) total_pixels);
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_emit (transform, pika_color_transform_signals[PROGRESS], 0,
|
||||
1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_color_transform_can_gegl_copy:
|
||||
* @src_profile: source #PikaColorProfile
|
||||
* @dest_profile: destination #PikaColorProfile
|
||||
*
|
||||
* This function checks if a PikaColorTransform is needed at all.
|
||||
*
|
||||
* Returns: %TRUE if pixels can be correctly converted between
|
||||
* @src_profile and @dest_profile by simply using
|
||||
* gegl_buffer_copy(), babl_process() or similar.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
gboolean
|
||||
pika_color_transform_can_gegl_copy (PikaColorProfile *src_profile,
|
||||
PikaColorProfile *dest_profile)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_PROFILE (src_profile), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_COLOR_PROFILE (dest_profile), FALSE);
|
||||
|
||||
if (pika_color_profile_is_equal (src_profile, dest_profile))
|
||||
return TRUE;
|
||||
|
||||
if (pika_color_profile_get_space (src_profile,
|
||||
PIKA_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
|
||||
NULL) &&
|
||||
pika_color_profile_get_space (dest_profile,
|
||||
PIKA_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
|
||||
NULL))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
131
libpikacolor/pikacolortransform.h
Normal file
131
libpikacolor/pikacolortransform.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikacolortransform.h
|
||||
* Copyright (C) 2014 Michael Natterer <mitch@gimp.org>
|
||||
* Elle Stone <ellestone@ninedegreesbelow.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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_COLOR_TRANSFORM_H__
|
||||
#define __PIKA_COLOR_TRANSFORM_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
/**
|
||||
* PikaColorTransformFlags:
|
||||
* @PIKA_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE: optimize for accuracy rather
|
||||
* than for speed
|
||||
* @PIKA_COLOR_TRANSFORM_FLAGS_GAMUT_CHECK: mark out of gamut colors in the
|
||||
* transform result
|
||||
* @PIKA_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION: do black point
|
||||
* compensation
|
||||
*
|
||||
* Flags for modifying #PikaColorTransform's behavior.
|
||||
**/
|
||||
typedef enum
|
||||
{
|
||||
PIKA_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE = 0x0100,
|
||||
PIKA_COLOR_TRANSFORM_FLAGS_GAMUT_CHECK = 0x1000,
|
||||
PIKA_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION = 0x2000,
|
||||
} PikaColorTransformFlags;
|
||||
|
||||
|
||||
#define PIKA_TYPE_COLOR_TRANSFORM (pika_color_transform_get_type ())
|
||||
#define PIKA_COLOR_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_COLOR_TRANSFORM, PikaColorTransform))
|
||||
#define PIKA_COLOR_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_COLOR_TRANSFORM, PikaColorTransformClass))
|
||||
#define PIKA_IS_COLOR_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_COLOR_TRANSFORM))
|
||||
#define PIKA_IS_COLOR_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_COLOR_TRANSFORM))
|
||||
#define PIKA_COLOR_TRANSFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_COLOR_TRANSFORM, PikaColorTransformClass))
|
||||
|
||||
|
||||
typedef struct _PikaColorTransformPrivate PikaColorTransformPrivate;
|
||||
typedef struct _PikaColorTransformClass PikaColorTransformClass;
|
||||
|
||||
struct _PikaColorTransform
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
PikaColorTransformPrivate *priv;
|
||||
};
|
||||
|
||||
struct _PikaColorTransformClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (* progress) (PikaColorTransform *transform,
|
||||
gdouble fraction);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (* _pika_reserved1) (void);
|
||||
void (* _pika_reserved2) (void);
|
||||
void (* _pika_reserved3) (void);
|
||||
void (* _pika_reserved4) (void);
|
||||
void (* _pika_reserved5) (void);
|
||||
void (* _pika_reserved6) (void);
|
||||
void (* _pika_reserved7) (void);
|
||||
void (* _pika_reserved8) (void);
|
||||
};
|
||||
|
||||
|
||||
GType pika_color_transform_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaColorTransform *
|
||||
pika_color_transform_new (PikaColorProfile *src_profile,
|
||||
const Babl *src_format,
|
||||
PikaColorProfile *dest_profile,
|
||||
const Babl *dest_format,
|
||||
PikaColorRenderingIntent rendering_intent,
|
||||
PikaColorTransformFlags flags);
|
||||
|
||||
PikaColorTransform *
|
||||
pika_color_transform_new_proofing (PikaColorProfile *src_profile,
|
||||
const Babl *src_format,
|
||||
PikaColorProfile *dest_profile,
|
||||
const Babl *dest_format,
|
||||
PikaColorProfile *proof_profile,
|
||||
PikaColorRenderingIntent proof_intent,
|
||||
PikaColorRenderingIntent display_intent,
|
||||
PikaColorTransformFlags flags);
|
||||
|
||||
void pika_color_transform_process_pixels (PikaColorTransform *transform,
|
||||
const Babl *src_format,
|
||||
gconstpointer src_pixels,
|
||||
const Babl *dest_format,
|
||||
gpointer dest_pixels,
|
||||
gsize length);
|
||||
|
||||
void pika_color_transform_process_buffer (PikaColorTransform *transform,
|
||||
GeglBuffer *src_buffer,
|
||||
const GeglRectangle *src_rect,
|
||||
GeglBuffer *dest_buffer,
|
||||
const GeglRectangle *dest_rect);
|
||||
|
||||
gboolean pika_color_transform_can_gegl_copy (PikaColorProfile *src_profile,
|
||||
PikaColorProfile *dest_profile);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_COLOR_TRANSFORM_H__ */
|
112
libpikacolor/pikacolortypes.h
Normal file
112
libpikacolor/pikacolortypes.h
Normal file
@ -0,0 +1,112 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_COLOR_TYPES_H__
|
||||
#define __PIKA_COLOR_TYPES_H__
|
||||
|
||||
|
||||
#include <libpikabase/pikabasetypes.h>
|
||||
#include <libpikaconfig/pikaconfigtypes.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
typedef struct _PikaColorManaged PikaColorManaged; /* dummy typedef */
|
||||
typedef struct _PikaColorProfile PikaColorProfile;
|
||||
typedef struct _PikaColorTransform PikaColorTransform;
|
||||
|
||||
|
||||
/* usually we don't keep the structure definitions in the types file
|
||||
* but PikaRGB appears in too many header files...
|
||||
*/
|
||||
|
||||
typedef struct _PikaRGB PikaRGB;
|
||||
typedef struct _PikaHSV PikaHSV;
|
||||
typedef struct _PikaHSL PikaHSL;
|
||||
typedef struct _PikaCMYK PikaCMYK;
|
||||
|
||||
/**
|
||||
* PikaRGB:
|
||||
* @r: the red component
|
||||
* @g: the green component
|
||||
* @b: the blue component
|
||||
* @a: the alpha component
|
||||
*
|
||||
* Used to keep RGB and RGBA colors. All components are in a range of
|
||||
* [0.0..1.0].
|
||||
**/
|
||||
struct _PikaRGB
|
||||
{
|
||||
gdouble r, g, b, a;
|
||||
};
|
||||
|
||||
/**
|
||||
* PikaHSV:
|
||||
* @h: the hue component
|
||||
* @s: the saturation component
|
||||
* @v: the value component
|
||||
* @a: the alpha component
|
||||
*
|
||||
* Used to keep HSV and HSVA colors. All components are in a range of
|
||||
* [0.0..1.0].
|
||||
**/
|
||||
struct _PikaHSV
|
||||
{
|
||||
gdouble h, s, v, a;
|
||||
};
|
||||
|
||||
/**
|
||||
* PikaHSL:
|
||||
* @h: the hue component
|
||||
* @s: the saturation component
|
||||
* @l: the lightness component
|
||||
* @a: the alpha component
|
||||
*
|
||||
* Used to keep HSL and HSLA colors. All components are in a range of
|
||||
* [0.0..1.0].
|
||||
**/
|
||||
struct _PikaHSL
|
||||
{
|
||||
gdouble h, s, l, a;
|
||||
};
|
||||
|
||||
/**
|
||||
* PikaCMYK:
|
||||
* @c: the cyan component
|
||||
* @m: the magenta component
|
||||
* @y: the yellow component
|
||||
* @k: the black component
|
||||
* @a: the alpha component
|
||||
*
|
||||
* Used to keep CMYK and CMYKA colors. All components are in a range
|
||||
* of [0.0..1.0]. An alpha value is somewhat useless in the CMYK
|
||||
* colorspace, but we keep one around anyway so color conversions
|
||||
* going to CMYK and back can preserve alpha.
|
||||
**/
|
||||
struct _PikaCMYK
|
||||
{
|
||||
gdouble c, m, y, k, a;
|
||||
};
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_COLOR_TYPES_H__ */
|
82
libpikacolor/pikahsl.c
Normal file
82
libpikacolor/pikahsl.c
Normal file
@ -0,0 +1,82 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikahsl.h"
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_HSL
|
||||
*/
|
||||
|
||||
static PikaHSL * pika_hsl_copy (const PikaHSL *hsl);
|
||||
|
||||
|
||||
G_DEFINE_BOXED_TYPE (PikaHSL, pika_hsl, pika_hsl_copy, g_free)
|
||||
|
||||
static PikaHSL *
|
||||
pika_hsl_copy (const PikaHSL *hsl)
|
||||
{
|
||||
return g_memdup2 (hsl, sizeof (PikaHSL));
|
||||
}
|
||||
|
||||
|
||||
/* HSL functions */
|
||||
|
||||
/**
|
||||
* pika_hsl_set:
|
||||
* @hsl:
|
||||
* @h:
|
||||
* @s:
|
||||
* @l:
|
||||
*
|
||||
* Since: 2.8
|
||||
**/
|
||||
void
|
||||
pika_hsl_set (PikaHSL *hsl,
|
||||
gdouble h,
|
||||
gdouble s,
|
||||
gdouble l)
|
||||
{
|
||||
g_return_if_fail (hsl != NULL);
|
||||
|
||||
hsl->h = h;
|
||||
hsl->s = s;
|
||||
hsl->l = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_hsl_set_alpha:
|
||||
* @hsl:
|
||||
* @a:
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
void
|
||||
pika_hsl_set_alpha (PikaHSL *hsl,
|
||||
gdouble a)
|
||||
{
|
||||
g_return_if_fail (hsl != NULL);
|
||||
|
||||
hsl->a = a;
|
||||
}
|
49
libpikacolor/pikahsl.h
Normal file
49
libpikacolor/pikahsl.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_HSL_H__
|
||||
#define __PIKA_HSL_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_HSL
|
||||
*/
|
||||
|
||||
#define PIKA_TYPE_HSL (pika_hsl_get_type ())
|
||||
|
||||
GType pika_hsl_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_hsl_set (PikaHSL *hsl,
|
||||
gdouble h,
|
||||
gdouble s,
|
||||
gdouble l);
|
||||
void pika_hsl_set_alpha (PikaHSL *hsl,
|
||||
gdouble a);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_HSL_H__ */
|
96
libpikacolor/pikahsv.c
Normal file
96
libpikacolor/pikahsv.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikahsv.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikahsv
|
||||
* @title: PikaHSV
|
||||
* @short_description: Definitions and Functions relating to HSV colors.
|
||||
*
|
||||
* Definitions and Functions relating to HSV colors.
|
||||
**/
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_HSV
|
||||
*/
|
||||
|
||||
static PikaHSV * pika_hsv_copy (const PikaHSV *hsv);
|
||||
|
||||
|
||||
G_DEFINE_BOXED_TYPE (PikaHSV, pika_hsv, pika_hsv_copy, g_free)
|
||||
|
||||
static PikaHSV *
|
||||
pika_hsv_copy (const PikaHSV *hsv)
|
||||
{
|
||||
return g_memdup2 (hsv, sizeof (PikaHSV));
|
||||
}
|
||||
|
||||
|
||||
/* HSV functions */
|
||||
|
||||
void
|
||||
pika_hsv_set (PikaHSV *hsv,
|
||||
gdouble h,
|
||||
gdouble s,
|
||||
gdouble v)
|
||||
{
|
||||
g_return_if_fail (hsv != NULL);
|
||||
|
||||
hsv->h = h;
|
||||
hsv->s = s;
|
||||
hsv->v = v;
|
||||
}
|
||||
|
||||
void
|
||||
pika_hsv_clamp (PikaHSV *hsv)
|
||||
{
|
||||
g_return_if_fail (hsv != NULL);
|
||||
|
||||
hsv->h -= (gint) hsv->h;
|
||||
|
||||
if (hsv->h < 0)
|
||||
hsv->h += 1.0;
|
||||
|
||||
hsv->s = CLAMP (hsv->s, 0.0, 1.0);
|
||||
hsv->v = CLAMP (hsv->v, 0.0, 1.0);
|
||||
hsv->a = CLAMP (hsv->a, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
pika_hsva_set (PikaHSV *hsva,
|
||||
gdouble h,
|
||||
gdouble s,
|
||||
gdouble v,
|
||||
gdouble a)
|
||||
{
|
||||
g_return_if_fail (hsva != NULL);
|
||||
|
||||
hsva->h = h;
|
||||
hsva->s = s;
|
||||
hsva->v = v;
|
||||
hsva->a = a;
|
||||
}
|
54
libpikacolor/pikahsv.h
Normal file
54
libpikacolor/pikahsv.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_HSV_H__
|
||||
#define __PIKA_HSV_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_HSV
|
||||
*/
|
||||
|
||||
#define PIKA_TYPE_HSV (pika_hsv_get_type ())
|
||||
|
||||
GType pika_hsv_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_hsv_set (PikaHSV *hsv,
|
||||
gdouble hue,
|
||||
gdouble saturation,
|
||||
gdouble value);
|
||||
void pika_hsv_clamp (PikaHSV *hsv);
|
||||
|
||||
void pika_hsva_set (PikaHSV *hsva,
|
||||
gdouble hue,
|
||||
gdouble saturation,
|
||||
gdouble value,
|
||||
gdouble alpha);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_HSV_H__ */
|
152
libpikacolor/pikapixbuf.c
Normal file
152
libpikacolor/pikapixbuf.c
Normal file
@ -0,0 +1,152 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapixbuf.c
|
||||
* Copyright (C) 2012 Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikapixbuf.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikapixbuf
|
||||
* @title: PikaPixbuf
|
||||
* @short_description: Definitions and Functions relating to GdkPixbuf.
|
||||
*
|
||||
* Definitions and Functions relating to GdkPixbuf.
|
||||
**/
|
||||
|
||||
/**
|
||||
* pika_pixbuf_get_format:
|
||||
* @pixbuf: a #GdkPixbuf
|
||||
*
|
||||
* Returns the Babl format that corresponds to the @pixbuf's pixel format.
|
||||
*
|
||||
* Returns: the @pixbuf's pixel format
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
const Babl *
|
||||
pika_pixbuf_get_format (GdkPixbuf *pixbuf)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
||||
|
||||
switch (gdk_pixbuf_get_n_channels (pixbuf))
|
||||
{
|
||||
case 3: return babl_format ("R'G'B' u8");
|
||||
case 4: return babl_format ("R'G'B'A u8");
|
||||
}
|
||||
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_pixbuf_create_buffer:
|
||||
* @pixbuf: a #GdkPixbuf
|
||||
*
|
||||
* Returns a #GeglBuffer that's either backed by the @pixbuf's pixels,
|
||||
* or a copy of them. This function tries to not copy the @pixbuf's
|
||||
* pixels. If the pixbuf's rowstride is a multiple of its bpp, a
|
||||
* simple reference to the @pixbuf's pixels is made and @pixbuf will
|
||||
* be kept around for as long as the buffer exists; otherwise the
|
||||
* pixels are copied.
|
||||
*
|
||||
* Returns: (transfer full): a new #GeglBuffer.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
GeglBuffer *
|
||||
pika_pixbuf_create_buffer (GdkPixbuf *pixbuf)
|
||||
{
|
||||
gint width;
|
||||
gint height;
|
||||
gint rowstride;
|
||||
gint bpp;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
||||
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
bpp = gdk_pixbuf_get_n_channels (pixbuf);
|
||||
|
||||
if ((rowstride % bpp) == 0)
|
||||
{
|
||||
return gegl_buffer_linear_new_from_data (gdk_pixbuf_get_pixels (pixbuf),
|
||||
pika_pixbuf_get_format (pixbuf),
|
||||
GEGL_RECTANGLE (0, 0,
|
||||
width, height),
|
||||
rowstride,
|
||||
(GDestroyNotify) g_object_unref,
|
||||
g_object_ref (pixbuf));
|
||||
}
|
||||
else
|
||||
{
|
||||
GeglBuffer *buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
|
||||
width, height),
|
||||
pika_pixbuf_get_format (pixbuf));
|
||||
|
||||
gegl_buffer_set (buffer, NULL, 0, NULL,
|
||||
gdk_pixbuf_get_pixels (pixbuf),
|
||||
gdk_pixbuf_get_rowstride (pixbuf));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_pixbuf_get_icc_profile:
|
||||
* @pixbuf: a #GdkPixbuf
|
||||
* @length: (out): return location for the ICC profile's length
|
||||
*
|
||||
* Returns the ICC profile attached to the @pixbuf, or %NULL if there
|
||||
* is none.
|
||||
*
|
||||
* Returns: (array length=length) (nullable): The ICC profile data, or %NULL.
|
||||
* The value should be freed with g_free().
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
guint8 *
|
||||
pika_pixbuf_get_icc_profile (GdkPixbuf *pixbuf,
|
||||
gsize *length)
|
||||
{
|
||||
const gchar *icc_base64;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
||||
g_return_val_if_fail (length != NULL, NULL);
|
||||
|
||||
icc_base64 = gdk_pixbuf_get_option (pixbuf, "icc-profile");
|
||||
|
||||
if (icc_base64)
|
||||
{
|
||||
guint8 *icc_data;
|
||||
|
||||
icc_data = g_base64_decode (icc_base64, length);
|
||||
|
||||
return icc_data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
43
libpikacolor/pikapixbuf.h
Normal file
43
libpikacolor/pikapixbuf.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapixbuf.h
|
||||
* Copyright (C) 2012 Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_PIXBUF_H__
|
||||
#define __PIKA_PIXBUF_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
const Babl * pika_pixbuf_get_format (GdkPixbuf *pixbuf);
|
||||
GeglBuffer * pika_pixbuf_create_buffer (GdkPixbuf *pixbuf);
|
||||
|
||||
guint8 * pika_pixbuf_get_icc_profile (GdkPixbuf *pixbuf,
|
||||
gsize *length);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_PIXBUF_H__ */
|
649
libpikacolor/pikargb-parse.c
Normal file
649
libpikacolor/pikargb-parse.c
Normal file
@ -0,0 +1,649 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* pikargb-parse.c
|
||||
* Copyright (C) 2004 Sven Neumann <sven@gimp.org>
|
||||
*
|
||||
* Some of the code in here was inspired and partly copied from pango
|
||||
* and librsvg.
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <babl/babl.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
|
||||
#include "pikacolorspace.h"
|
||||
#include "pikargb.h"
|
||||
|
||||
|
||||
static gchar * pika_rgb_parse_strip (const gchar *str,
|
||||
gint len);
|
||||
|
||||
static gboolean pika_rgb_parse_name_internal (PikaRGB *rgb,
|
||||
const gchar *name);
|
||||
static gboolean pika_rgb_parse_hex_internal (PikaRGB *rgb,
|
||||
const gchar *hex);
|
||||
static gboolean pika_rgb_parse_css_internal (PikaRGB *rgb,
|
||||
const gchar *css);
|
||||
static gboolean pika_rgba_parse_css_internal (PikaRGB *rgb,
|
||||
const gchar *css);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar *name;
|
||||
const guchar red;
|
||||
const guchar green;
|
||||
const guchar blue;
|
||||
} ColorEntry;
|
||||
|
||||
static const ColorEntry named_colors[] =
|
||||
{
|
||||
{ "aliceblue", 240, 248, 255 },
|
||||
{ "antiquewhite", 250, 235, 215 },
|
||||
{ "aqua", 0, 255, 255 },
|
||||
{ "aquamarine", 127, 255, 212 },
|
||||
{ "azure", 240, 255, 255 },
|
||||
{ "beige", 245, 245, 220 },
|
||||
{ "bisque", 255, 228, 196 },
|
||||
{ "black", 0, 0, 0 },
|
||||
{ "blanchedalmond", 255, 235, 205 },
|
||||
{ "blue", 0, 0, 255 },
|
||||
{ "blueviolet", 138, 43, 226 },
|
||||
{ "brown", 165, 42, 42 },
|
||||
{ "burlywood", 222, 184, 135 },
|
||||
{ "cadetblue", 95, 158, 160 },
|
||||
{ "chartreuse", 127, 255, 0 },
|
||||
{ "chocolate", 210, 105, 30 },
|
||||
{ "coral", 255, 127, 80 },
|
||||
{ "cornflowerblue", 100, 149, 237 },
|
||||
{ "cornsilk", 255, 248, 220 },
|
||||
{ "crimson", 220, 20, 60 },
|
||||
{ "cyan", 0, 255, 255 },
|
||||
{ "darkblue", 0, 0, 139 },
|
||||
{ "darkcyan", 0, 139, 139 },
|
||||
{ "darkgoldenrod", 184, 134, 11 },
|
||||
{ "darkgray", 169, 169, 169 },
|
||||
{ "darkgreen", 0, 100, 0 },
|
||||
{ "darkgrey", 169, 169, 169 },
|
||||
{ "darkkhaki", 189, 183, 107 },
|
||||
{ "darkmagenta", 139, 0, 139 },
|
||||
{ "darkolivegreen", 85, 107, 47 },
|
||||
{ "darkorange", 255, 140, 0 },
|
||||
{ "darkorchid", 153, 50, 204 },
|
||||
{ "darkred", 139, 0, 0 },
|
||||
{ "darksalmon", 233, 150, 122 },
|
||||
{ "darkseagreen", 143, 188, 143 },
|
||||
{ "darkslateblue", 72, 61, 139 },
|
||||
{ "darkslategray", 47, 79, 79 },
|
||||
{ "darkslategrey", 47, 79, 79 },
|
||||
{ "darkturquoise", 0, 206, 209 },
|
||||
{ "darkviolet", 148, 0, 211 },
|
||||
{ "deeppink", 255, 20, 147 },
|
||||
{ "deepskyblue", 0, 191, 255 },
|
||||
{ "dimgray", 105, 105, 105 },
|
||||
{ "dimgrey", 105, 105, 105 },
|
||||
{ "dodgerblue", 30, 144, 255 },
|
||||
{ "firebrick", 178, 34, 34 },
|
||||
{ "floralwhite" , 255, 250, 240 },
|
||||
{ "forestgreen", 34, 139, 34 },
|
||||
{ "fuchsia", 255, 0, 255 },
|
||||
{ "gainsboro", 220, 220, 220 },
|
||||
{ "ghostwhite", 248, 248, 255 },
|
||||
{ "gold", 255, 215, 0 },
|
||||
{ "goldenrod", 218, 165, 32 },
|
||||
{ "gray", 128, 128, 128 },
|
||||
{ "green", 0, 128, 0 },
|
||||
{ "greenyellow", 173, 255, 47 },
|
||||
{ "grey", 128, 128, 128 },
|
||||
{ "honeydew", 240, 255, 240 },
|
||||
{ "hotpink", 255, 105, 180 },
|
||||
{ "indianred", 205, 92, 92 },
|
||||
{ "indigo", 75, 0, 130 },
|
||||
{ "ivory", 255, 255, 240 },
|
||||
{ "khaki", 240, 230, 140 },
|
||||
{ "lavender", 230, 230, 250 },
|
||||
{ "lavenderblush", 255, 240, 245 },
|
||||
{ "lawngreen", 124, 252, 0 },
|
||||
{ "lemonchiffon", 255, 250, 205 },
|
||||
{ "lightblue", 173, 216, 230 },
|
||||
{ "lightcoral", 240, 128, 128 },
|
||||
{ "lightcyan", 224, 255, 255 },
|
||||
{ "lightgoldenrodyellow", 250, 250, 210 },
|
||||
{ "lightgray", 211, 211, 211 },
|
||||
{ "lightgreen", 144, 238, 144 },
|
||||
{ "lightgrey", 211, 211, 211 },
|
||||
{ "lightpink", 255, 182, 193 },
|
||||
{ "lightsalmon", 255, 160, 122 },
|
||||
{ "lightseagreen", 32, 178, 170 },
|
||||
{ "lightskyblue", 135, 206, 250 },
|
||||
{ "lightslategray", 119, 136, 153 },
|
||||
{ "lightslategrey", 119, 136, 153 },
|
||||
{ "lightsteelblue", 176, 196, 222 },
|
||||
{ "lightyellow", 255, 255, 224 },
|
||||
{ "lime", 0, 255, 0 },
|
||||
{ "limegreen", 50, 205, 50 },
|
||||
{ "linen", 250, 240, 230 },
|
||||
{ "magenta", 255, 0, 255 },
|
||||
{ "maroon", 128, 0, 0 },
|
||||
{ "mediumaquamarine", 102, 205, 170 },
|
||||
{ "mediumblue", 0, 0, 205 },
|
||||
{ "mediumorchid", 186, 85, 211 },
|
||||
{ "mediumpurple", 147, 112, 219 },
|
||||
{ "mediumseagreen", 60, 179, 113 },
|
||||
{ "mediumslateblue", 123, 104, 238 },
|
||||
{ "mediumspringgreen", 0, 250, 154 },
|
||||
{ "mediumturquoise", 72, 209, 204 },
|
||||
{ "mediumvioletred", 199, 21, 133 },
|
||||
{ "midnightblue", 25, 25, 112 },
|
||||
{ "mintcream", 245, 255, 250 },
|
||||
{ "mistyrose", 255, 228, 225 },
|
||||
{ "moccasin", 255, 228, 181 },
|
||||
{ "navajowhite", 255, 222, 173 },
|
||||
{ "navy", 0, 0, 128 },
|
||||
{ "oldlace", 253, 245, 230 },
|
||||
{ "olive", 128, 128, 0 },
|
||||
{ "olivedrab", 107, 142, 35 },
|
||||
{ "orange", 255, 165, 0 },
|
||||
{ "orangered", 255, 69, 0 },
|
||||
{ "orchid", 218, 112, 214 },
|
||||
{ "palegoldenrod", 238, 232, 170 },
|
||||
{ "palegreen", 152, 251, 152 },
|
||||
{ "paleturquoise", 175, 238, 238 },
|
||||
{ "palevioletred", 219, 112, 147 },
|
||||
{ "papayawhip", 255, 239, 213 },
|
||||
{ "peachpuff", 255, 218, 185 },
|
||||
{ "peru", 205, 133, 63 },
|
||||
{ "pink", 255, 192, 203 },
|
||||
{ "plum", 221, 160, 221 },
|
||||
{ "powderblue", 176, 224, 230 },
|
||||
{ "purple", 128, 0, 128 },
|
||||
{ "red", 255, 0, 0 },
|
||||
{ "rosybrown", 188, 143, 143 },
|
||||
{ "royalblue", 65, 105, 225 },
|
||||
{ "saddlebrown", 139, 69, 19 },
|
||||
{ "salmon", 250, 128, 114 },
|
||||
{ "sandybrown", 244, 164, 96 },
|
||||
{ "seagreen", 46, 139, 87 },
|
||||
{ "seashell", 255, 245, 238 },
|
||||
{ "sienna", 160, 82, 45 },
|
||||
{ "silver", 192, 192, 192 },
|
||||
{ "skyblue", 135, 206, 235 },
|
||||
{ "slateblue", 106, 90, 205 },
|
||||
{ "slategray", 112, 128, 144 },
|
||||
{ "slategrey", 112, 128, 144 },
|
||||
{ "snow", 255, 250, 250 },
|
||||
{ "springgreen", 0, 255, 127 },
|
||||
{ "steelblue", 70, 130, 180 },
|
||||
{ "tan", 210, 180, 140 },
|
||||
{ "teal", 0, 128, 128 },
|
||||
{ "thistle", 216, 191, 216 },
|
||||
{ "tomato", 255, 99, 71 },
|
||||
{ "turquoise", 64, 224, 208 },
|
||||
{ "violet", 238, 130, 238 },
|
||||
{ "wheat", 245, 222, 179 },
|
||||
{ "white", 255, 255, 255 },
|
||||
{ "whitesmoke", 245, 245, 245 },
|
||||
{ "yellow", 255, 255, 0 },
|
||||
{ "yellowgreen", 154, 205, 50 }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* pika_rgb_parse_name:
|
||||
* @rgb: a #PikaRGB struct used to return the parsed color
|
||||
* @name: (array length=len): a color name (in UTF-8 encoding)
|
||||
* @len: the length of @name, in bytes. or -1 if @name is nul-terminated
|
||||
*
|
||||
* Attempts to parse a color name. This function accepts <ulink
|
||||
* url="https://www.w3.org/TR/SVG/types.html#ColorKeywords">SVG 1.0
|
||||
* color keywords</ulink>.
|
||||
*
|
||||
* This function does not touch the alpha component of @rgb.
|
||||
*
|
||||
* Returns: %TRUE if @name was parsed successfully and @rgb has
|
||||
* been set, %FALSE otherwise
|
||||
*
|
||||
* Since: 2.2
|
||||
**/
|
||||
gboolean
|
||||
pika_rgb_parse_name (PikaRGB *rgb,
|
||||
const gchar *name,
|
||||
gint len)
|
||||
{
|
||||
gchar *tmp;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (rgb != NULL, FALSE);
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
||||
tmp = pika_rgb_parse_strip (name, len);
|
||||
|
||||
result = pika_rgb_parse_name_internal (rgb, tmp);
|
||||
|
||||
g_free (tmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_parse_hex:
|
||||
* @rgb: a #PikaRGB struct used to return the parsed color
|
||||
* @hex: (array length=len): a string describing a color in hexadecimal notation
|
||||
* @len: the length of @hex, in bytes. or -1 if @hex is nul-terminated
|
||||
*
|
||||
* Attempts to parse a string describing an RGB color in hexadecimal
|
||||
* notation (optionally prefixed with a '#').
|
||||
*
|
||||
* This function does not touch the alpha component of @rgb.
|
||||
*
|
||||
* Returns: %TRUE if @hex was parsed successfully and @rgb has
|
||||
* been set, %FALSE otherwise
|
||||
*
|
||||
* Since: 2.2
|
||||
**/
|
||||
gboolean
|
||||
pika_rgb_parse_hex (PikaRGB *rgb,
|
||||
const gchar *hex,
|
||||
gint len)
|
||||
{
|
||||
gchar *tmp;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (rgb != NULL, FALSE);
|
||||
g_return_val_if_fail (hex != NULL, FALSE);
|
||||
|
||||
tmp = pika_rgb_parse_strip (hex, len);
|
||||
|
||||
result = pika_rgb_parse_hex_internal (rgb, tmp);
|
||||
|
||||
g_free (tmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_parse_css:
|
||||
* @rgb: a #PikaRGB struct used to return the parsed color
|
||||
* @css: (array length=len): a string describing a color in CSS notation
|
||||
* @len: the length of @css, in bytes. or -1 if @css is nul-terminated
|
||||
*
|
||||
* Attempts to parse a string describing an RGB color in CSS
|
||||
* notation. This can be either a numerical representation
|
||||
* (<code>rgb(255,0,0)</code> or <code>rgb(100%,0%,0%)</code>)
|
||||
* or a hexadecimal notation as parsed by pika_rgb_parse_hex()
|
||||
* (<code>##ff0000</code>) or a color name as parsed by
|
||||
* pika_rgb_parse_name() (<code>red</code>).
|
||||
*
|
||||
* This function does not touch the alpha component of @rgb.
|
||||
*
|
||||
* Returns: %TRUE if @css was parsed successfully and @rgb has been
|
||||
* set, %FALSE otherwise
|
||||
*
|
||||
* Since: 2.2
|
||||
**/
|
||||
gboolean
|
||||
pika_rgb_parse_css (PikaRGB *rgb,
|
||||
const gchar *css,
|
||||
gint len)
|
||||
{
|
||||
gchar *tmp;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (rgb != NULL, FALSE);
|
||||
g_return_val_if_fail (css != NULL, FALSE);
|
||||
|
||||
tmp = pika_rgb_parse_strip (css, len);
|
||||
|
||||
result = pika_rgb_parse_css_internal (rgb, tmp);
|
||||
|
||||
g_free (tmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgba_parse_css:
|
||||
* @rgba: a #PikaRGB struct used to return the parsed color
|
||||
* @css: (array length=len): a string describing a color in CSS notation
|
||||
* @len: the length of @css, in bytes. or -1 if @css is nul-terminated
|
||||
*
|
||||
* Similar to pika_rgb_parse_css() but handles RGB colors with alpha
|
||||
* channel in the numerical CSS notation (<code>rgba(255,0,0,255)</code>
|
||||
* or <code>rgba(100%,0%,0%,1000%)</code>).
|
||||
*
|
||||
* It doesn't handle the hexadecimal notation or color names because
|
||||
* they leave the alpha channel unspecified.
|
||||
*
|
||||
* Returns: %TRUE if @css was parsed successfully and @rgb has been
|
||||
* set, %FALSE otherwise
|
||||
*
|
||||
* Since: 2.2
|
||||
**/
|
||||
gboolean
|
||||
pika_rgba_parse_css (PikaRGB *rgba,
|
||||
const gchar *css,
|
||||
gint len)
|
||||
{
|
||||
gchar *tmp;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (rgba != NULL, FALSE);
|
||||
g_return_val_if_fail (css != NULL, FALSE);
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (css);
|
||||
|
||||
tmp = pika_rgb_parse_strip (css, len);
|
||||
|
||||
if (strcmp (tmp, "transparent") == 0)
|
||||
{
|
||||
pika_rgba_set (rgba, 0.0, 0.0, 0.0, 0.0);
|
||||
result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = pika_rgba_parse_css_internal (rgba, tmp);
|
||||
}
|
||||
|
||||
g_free (tmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pika_rgb_list_names:
|
||||
* @names: (out) (array length=n_colors) (transfer container): return location for an array of color names
|
||||
* @colors: (out) (array length=n_colors) (transfer container): return location for an array of PikaRGB structs
|
||||
* @n_colors: (out): The number of named colors
|
||||
*
|
||||
* Returns the list of <ulink
|
||||
* url="https://www.w3.org/TR/SVG/types.html">SVG 1.0 color
|
||||
* keywords</ulink> that is used by pika_rgb_parse_name().
|
||||
*
|
||||
* The returned strings are const and must not be freed. Only the two
|
||||
* arrays are allocated dynamically. You must call g_free() on the
|
||||
* @names and @colors arrays when they are not any longer needed.
|
||||
*
|
||||
* Since: 2.2
|
||||
**/
|
||||
void
|
||||
pika_rgb_list_names (const gchar ***names,
|
||||
PikaRGB **colors,
|
||||
gint *n_colors)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (names != NULL);
|
||||
g_return_if_fail (colors != NULL);
|
||||
g_return_if_fail (n_colors != NULL);
|
||||
|
||||
*names = g_new (const gchar *, G_N_ELEMENTS (named_colors));
|
||||
*colors = g_new (PikaRGB, G_N_ELEMENTS (named_colors));
|
||||
*n_colors = G_N_ELEMENTS (named_colors);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (named_colors); i++)
|
||||
{
|
||||
(*names)[i] = named_colors[i].name;
|
||||
|
||||
pika_rgba_set_uchar ((*colors) + i,
|
||||
named_colors[i].red,
|
||||
named_colors[i].green,
|
||||
named_colors[i].blue,
|
||||
0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
pika_rgb_parse_strip (const gchar *str,
|
||||
gint len)
|
||||
{
|
||||
gchar *result;
|
||||
|
||||
while (len > 0 && g_ascii_isspace (*str))
|
||||
{
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
while (g_ascii_isspace (*str))
|
||||
str++;
|
||||
|
||||
len = strlen (str);
|
||||
}
|
||||
|
||||
while (len > 0 && g_ascii_isspace (str[len - 1]))
|
||||
len--;
|
||||
|
||||
result = g_malloc (len + 1);
|
||||
|
||||
memcpy (result, str, len);
|
||||
result[len] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gint
|
||||
pika_rgb_color_entry_compare (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const gchar *name = a;
|
||||
const ColorEntry *entry = b;
|
||||
|
||||
return g_ascii_strcasecmp (name, entry->name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_rgb_parse_name_internal (PikaRGB *rgb,
|
||||
const gchar *name)
|
||||
{
|
||||
ColorEntry *entry = bsearch (name, named_colors,
|
||||
G_N_ELEMENTS (named_colors), sizeof (ColorEntry),
|
||||
pika_rgb_color_entry_compare);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
pika_rgb_set_uchar (rgb, entry->red, entry->green, entry->blue);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
pika_rgb_parse_hex_component (const gchar *hex,
|
||||
gint len,
|
||||
gdouble *value)
|
||||
{
|
||||
gint i;
|
||||
guint c = 0;
|
||||
|
||||
for (i = 0; i < len; i++, hex++)
|
||||
{
|
||||
if (!*hex || !g_ascii_isxdigit (*hex))
|
||||
return FALSE;
|
||||
|
||||
c = (c << 4) | g_ascii_xdigit_value (*hex);
|
||||
}
|
||||
|
||||
switch (len)
|
||||
{
|
||||
case 1: *value = (gdouble) c / 15.0; break;
|
||||
case 2: *value = (gdouble) c / 255.0; break;
|
||||
case 3: *value = (gdouble) c / 4095.0; break;
|
||||
case 4: *value = (gdouble) c / 65535.0; break;
|
||||
default:
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_rgb_parse_hex_internal (PikaRGB *rgb,
|
||||
const gchar *hex)
|
||||
{
|
||||
gint i;
|
||||
gsize len;
|
||||
gdouble val[3];
|
||||
|
||||
if (hex[0] == '#')
|
||||
hex++;
|
||||
|
||||
len = strlen (hex);
|
||||
if (len % 3 || len < 3 || len > 12)
|
||||
return FALSE;
|
||||
|
||||
len /= 3;
|
||||
|
||||
for (i = 0; i < 3; i++, hex += len)
|
||||
{
|
||||
if (! pika_rgb_parse_hex_component (hex, len, val + i))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_rgb_set (rgb, val[0], val[1], val[2]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
pika_rgb_parse_css_numeric (PikaRGB *rgb,
|
||||
const gchar *css)
|
||||
{
|
||||
gdouble values[4];
|
||||
gboolean alpha;
|
||||
gboolean hsl;
|
||||
gint i;
|
||||
|
||||
if (css[0] == 'r' && css[1] == 'g' && css[2] == 'b')
|
||||
hsl = FALSE;
|
||||
else if (css[0] == 'h' && css[1] == 's' && css[2] == 'l')
|
||||
hsl = TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
if (css[3] == 'a' && css[4] == '(')
|
||||
alpha = TRUE;
|
||||
else if (css[3] == '(')
|
||||
alpha = FALSE;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
css += (alpha ? 5 : 4);
|
||||
|
||||
for (i = 0; i < (alpha ? 4 : 3); i++)
|
||||
{
|
||||
const gchar *end = css;
|
||||
|
||||
while (*end && *end != ',' && *end != '%' && *end != ')')
|
||||
end++;
|
||||
|
||||
if (i == 3 || *end == '%')
|
||||
{
|
||||
values[i] = g_ascii_strtod (css, (gchar **) &end);
|
||||
|
||||
if (errno == ERANGE)
|
||||
return FALSE;
|
||||
|
||||
if (*end == '%')
|
||||
{
|
||||
end++;
|
||||
values[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glong value = strtol (css, (gchar **) &end, 10);
|
||||
|
||||
if (errno == ERANGE)
|
||||
return FALSE;
|
||||
|
||||
if (hsl)
|
||||
values[i] = value / (i == 0 ? 360.0 : 100.0);
|
||||
else
|
||||
values[i] = value / 255.0;
|
||||
}
|
||||
|
||||
while (*end == ',' || g_ascii_isspace (*end))
|
||||
end++;
|
||||
|
||||
css = end;
|
||||
}
|
||||
|
||||
if (*css != ')')
|
||||
return FALSE;
|
||||
|
||||
if (alpha)
|
||||
pika_rgba_set (rgb, values[0], values[1], values[2], values[3]);
|
||||
else
|
||||
pika_rgb_set (rgb, values[0], values[1], values[2]);
|
||||
|
||||
pika_rgb_clamp (rgb);
|
||||
|
||||
if (hsl)
|
||||
{
|
||||
PikaHSL tmp = (*((PikaHSL *) rgb));
|
||||
|
||||
pika_hsl_to_rgb (&tmp, rgb);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_rgb_parse_css_internal (PikaRGB *rgb,
|
||||
const gchar *css)
|
||||
{
|
||||
if (css[0] == '#')
|
||||
{
|
||||
return pika_rgb_parse_hex_internal (rgb, css);
|
||||
}
|
||||
else if (strncmp (css, "rgb(", 4) == 0 ||
|
||||
strncmp (css, "hsl(", 4) == 0)
|
||||
{
|
||||
return pika_rgb_parse_css_numeric (rgb, css);
|
||||
}
|
||||
else
|
||||
{
|
||||
return pika_rgb_parse_name_internal (rgb, css);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_rgba_parse_css_internal (PikaRGB *rgba,
|
||||
const gchar *css)
|
||||
{
|
||||
if (strncmp (css, "rgba(", 5) != 0 &&
|
||||
strncmp (css, "hsla(", 5) != 0)
|
||||
return FALSE;
|
||||
|
||||
return pika_rgb_parse_css_numeric (rgba, css);
|
||||
}
|
814
libpikacolor/pikargb.c
Normal file
814
libpikacolor/pikargb.c
Normal file
@ -0,0 +1,814 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <babl/babl.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
|
||||
#include "pikacolortypes.h"
|
||||
#include "pikargb.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikargb
|
||||
* @title: PikaRGB
|
||||
* @short_description: Definitions and Functions relating to RGB colors.
|
||||
*
|
||||
* Definitions and Functions relating to RGB colors.
|
||||
**/
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_RGB
|
||||
*/
|
||||
|
||||
static PikaRGB * pika_rgb_copy (const PikaRGB *rgb);
|
||||
|
||||
|
||||
G_DEFINE_BOXED_TYPE (PikaRGB, pika_rgb, pika_rgb_copy, g_free)
|
||||
|
||||
void
|
||||
pika_value_get_rgb (const GValue *value,
|
||||
PikaRGB *rgb)
|
||||
{
|
||||
g_return_if_fail (PIKA_VALUE_HOLDS_RGB (value));
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
if (value->data[0].v_pointer)
|
||||
*rgb = *((PikaRGB *) value->data[0].v_pointer);
|
||||
else
|
||||
pika_rgba_set (rgb, 0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
pika_value_set_rgb (GValue *value,
|
||||
const PikaRGB *rgb)
|
||||
{
|
||||
g_return_if_fail (PIKA_VALUE_HOLDS_RGB (value));
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
g_value_set_boxed (value, rgb);
|
||||
}
|
||||
|
||||
static PikaRGB *
|
||||
pika_rgb_copy (const PikaRGB *rgb)
|
||||
{
|
||||
return g_memdup2 (rgb, sizeof (PikaRGB));
|
||||
}
|
||||
|
||||
|
||||
/* RGB functions */
|
||||
|
||||
/**
|
||||
* pika_rgb_set:
|
||||
* @rgb: a #PikaRGB struct
|
||||
* @red: the red component
|
||||
* @green: the green component
|
||||
* @blue: the blue component
|
||||
*
|
||||
* Sets the red, green and blue components of @rgb and leaves the
|
||||
* alpha component unchanged. The color values should be between 0.0
|
||||
* and 1.0 but there is no check to enforce this and the values are
|
||||
* set exactly as they are passed in.
|
||||
**/
|
||||
void
|
||||
pika_rgb_set (PikaRGB *rgb,
|
||||
gdouble r,
|
||||
gdouble g,
|
||||
gdouble b)
|
||||
{
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
rgb->r = r;
|
||||
rgb->g = g;
|
||||
rgb->b = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_set_alpha:
|
||||
* @rgb: a #PikaRGB struct
|
||||
* @alpha: the alpha component
|
||||
*
|
||||
* Sets the alpha component of @rgb and leaves the RGB components unchanged.
|
||||
**/
|
||||
void
|
||||
pika_rgb_set_alpha (PikaRGB *rgb,
|
||||
gdouble a)
|
||||
{
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
rgb->a = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_set_pixel:
|
||||
* @rgb: a #PikaRGB struct
|
||||
* @format: a Babl format
|
||||
* @pixel: pointer to the source pixel
|
||||
*
|
||||
* Sets the red, green and blue components of @rgb from the color
|
||||
* stored in @pixel. The pixel format of @pixel is determined by
|
||||
* @format.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
void
|
||||
pika_rgb_set_pixel (PikaRGB *rgb,
|
||||
const Babl *format,
|
||||
gconstpointer pixel)
|
||||
{
|
||||
g_return_if_fail (rgb != NULL);
|
||||
g_return_if_fail (format != NULL);
|
||||
g_return_if_fail (pixel != NULL);
|
||||
|
||||
babl_process (babl_fish (format,
|
||||
babl_format ("R'G'B' double")),
|
||||
pixel, rgb, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_get_pixel:
|
||||
* @rgb: a #PikaRGB struct
|
||||
* @format: a Babl format
|
||||
* @pixel: (out caller-allocates): pointer to the destination pixel
|
||||
*
|
||||
* Writes the red, green, blue and alpha components of @rgb to the
|
||||
* color stored in @pixel. The pixel format of @pixel is determined by
|
||||
* @format.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
void
|
||||
pika_rgb_get_pixel (const PikaRGB *rgb,
|
||||
const Babl *format,
|
||||
gpointer pixel)
|
||||
{
|
||||
g_return_if_fail (rgb != NULL);
|
||||
g_return_if_fail (format != NULL);
|
||||
g_return_if_fail (pixel != NULL);
|
||||
|
||||
babl_process (babl_fish (babl_format ("R'G'B' double"),
|
||||
format),
|
||||
rgb, pixel, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_set_uchar:
|
||||
* @rgb: a #PikaRGB struct
|
||||
* @red: the red component
|
||||
* @green: the green component
|
||||
* @blue: the blue component
|
||||
*
|
||||
* Sets the red, green and blue components of @rgb from 8bit values
|
||||
* (0 to 255) and leaves the alpha component unchanged.
|
||||
**/
|
||||
void
|
||||
pika_rgb_set_uchar (PikaRGB *rgb,
|
||||
guchar r,
|
||||
guchar g,
|
||||
guchar b)
|
||||
{
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
rgb->r = (gdouble) r / 255.0;
|
||||
rgb->g = (gdouble) g / 255.0;
|
||||
rgb->b = (gdouble) b / 255.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_get_uchar:
|
||||
* @rgb: a #PikaRGB struct
|
||||
* @red: (out) (optional): Location for red component, or %NULL
|
||||
* @green: (out) (optional): Location for green component, or %NULL
|
||||
* @blue: (out) (optional): Location for blue component, or %NULL
|
||||
*
|
||||
* Writes the red, green, blue and alpha components of @rgb to the
|
||||
* color components @red, @green and @blue.
|
||||
*/
|
||||
void
|
||||
pika_rgb_get_uchar (const PikaRGB *rgb,
|
||||
guchar *red,
|
||||
guchar *green,
|
||||
guchar *blue)
|
||||
{
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
if (red) *red = ROUND (CLAMP (rgb->r, 0.0, 1.0) * 255.0);
|
||||
if (green) *green = ROUND (CLAMP (rgb->g, 0.0, 1.0) * 255.0);
|
||||
if (blue) *blue = ROUND (CLAMP (rgb->b, 0.0, 1.0) * 255.0);
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgb_add (PikaRGB *rgb1,
|
||||
const PikaRGB *rgb2)
|
||||
{
|
||||
g_return_if_fail (rgb1 != NULL);
|
||||
g_return_if_fail (rgb2 != NULL);
|
||||
|
||||
rgb1->r += rgb2->r;
|
||||
rgb1->g += rgb2->g;
|
||||
rgb1->b += rgb2->b;
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgb_subtract (PikaRGB *rgb1,
|
||||
const PikaRGB *rgb2)
|
||||
{
|
||||
g_return_if_fail (rgb1 != NULL);
|
||||
g_return_if_fail (rgb2 != NULL);
|
||||
|
||||
rgb1->r -= rgb2->r;
|
||||
rgb1->g -= rgb2->g;
|
||||
rgb1->b -= rgb2->b;
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgb_multiply (PikaRGB *rgb,
|
||||
gdouble factor)
|
||||
{
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
rgb->r *= factor;
|
||||
rgb->g *= factor;
|
||||
rgb->b *= factor;
|
||||
}
|
||||
|
||||
gdouble
|
||||
pika_rgb_distance (const PikaRGB *rgb1,
|
||||
const PikaRGB *rgb2)
|
||||
{
|
||||
g_return_val_if_fail (rgb1 != NULL, 0.0);
|
||||
g_return_val_if_fail (rgb2 != NULL, 0.0);
|
||||
|
||||
return (fabs (rgb1->r - rgb2->r) +
|
||||
fabs (rgb1->g - rgb2->g) +
|
||||
fabs (rgb1->b - rgb2->b));
|
||||
}
|
||||
|
||||
gdouble
|
||||
pika_rgb_max (const PikaRGB *rgb)
|
||||
{
|
||||
g_return_val_if_fail (rgb != NULL, 0.0);
|
||||
|
||||
if (rgb->r > rgb->g)
|
||||
return (rgb->r > rgb->b) ? rgb->r : rgb->b;
|
||||
else
|
||||
return (rgb->g > rgb->b) ? rgb->g : rgb->b;
|
||||
}
|
||||
|
||||
gdouble
|
||||
pika_rgb_min (const PikaRGB *rgb)
|
||||
{
|
||||
g_return_val_if_fail (rgb != NULL, 0.0);
|
||||
|
||||
if (rgb->r < rgb->g)
|
||||
return (rgb->r < rgb->b) ? rgb->r : rgb->b;
|
||||
else
|
||||
return (rgb->g < rgb->b) ? rgb->g : rgb->b;
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgb_clamp (PikaRGB *rgb)
|
||||
{
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
rgb->r = CLAMP (rgb->r, 0.0, 1.0);
|
||||
rgb->g = CLAMP (rgb->g, 0.0, 1.0);
|
||||
rgb->b = CLAMP (rgb->b, 0.0, 1.0);
|
||||
rgb->a = CLAMP (rgb->a, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgb_gamma (PikaRGB *rgb,
|
||||
gdouble gamma)
|
||||
{
|
||||
gdouble ig;
|
||||
|
||||
g_return_if_fail (rgb != NULL);
|
||||
|
||||
if (gamma != 0.0)
|
||||
ig = 1.0 / gamma;
|
||||
else
|
||||
ig = 0.0;
|
||||
|
||||
rgb->r = pow (rgb->r, ig);
|
||||
rgb->g = pow (rgb->g, ig);
|
||||
rgb->b = pow (rgb->b, ig);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_luminance:
|
||||
* @rgb: a #PikaRGB struct
|
||||
*
|
||||
* Returns: the luminous intensity of the range from 0.0 to 1.0.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gdouble
|
||||
pika_rgb_luminance (const PikaRGB *rgb)
|
||||
{
|
||||
gdouble luminance;
|
||||
|
||||
g_return_val_if_fail (rgb != NULL, 0.0);
|
||||
|
||||
luminance = PIKA_RGB_LUMINANCE (rgb->r, rgb->g, rgb->b);
|
||||
|
||||
return CLAMP (luminance, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgb_luminance_uchar:
|
||||
* @rgb: a #PikaRGB struct
|
||||
*
|
||||
* Returns: the luminous intensity in the range from 0 to 255.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
guchar
|
||||
pika_rgb_luminance_uchar (const PikaRGB *rgb)
|
||||
{
|
||||
g_return_val_if_fail (rgb != NULL, 0);
|
||||
|
||||
return ROUND (pika_rgb_luminance (rgb) * 255.0);
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgb_composite (PikaRGB *color1,
|
||||
const PikaRGB *color2,
|
||||
PikaRGBCompositeMode mode)
|
||||
{
|
||||
g_return_if_fail (color1 != NULL);
|
||||
g_return_if_fail (color2 != NULL);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case PIKA_RGB_COMPOSITE_NONE:
|
||||
break;
|
||||
|
||||
case PIKA_RGB_COMPOSITE_NORMAL:
|
||||
/* put color2 on top of color1 */
|
||||
if (color2->a == 1.0)
|
||||
{
|
||||
*color1 = *color2;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble factor = color1->a * (1.0 - color2->a);
|
||||
|
||||
color1->r = color1->r * factor + color2->r * color2->a;
|
||||
color1->g = color1->g * factor + color2->g * color2->a;
|
||||
color1->b = color1->b * factor + color2->b * color2->a;
|
||||
color1->a = factor + color2->a;
|
||||
}
|
||||
break;
|
||||
|
||||
case PIKA_RGB_COMPOSITE_BEHIND:
|
||||
/* put color2 below color1 */
|
||||
if (color1->a < 1.0)
|
||||
{
|
||||
gdouble factor = color2->a * (1.0 - color1->a);
|
||||
|
||||
color1->r = color2->r * factor + color1->r * color1->a;
|
||||
color1->g = color2->g * factor + color1->g * color1->a;
|
||||
color1->b = color2->b * factor + color1->b * color1->a;
|
||||
color1->a = factor + color1->a;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* RGBA functions */
|
||||
|
||||
/**
|
||||
* pika_rgba_set_pixel:
|
||||
* @rgba: a #PikaRGB struct
|
||||
* @format: a Babl format
|
||||
* @pixel: pointer to the source pixel
|
||||
*
|
||||
* Sets the red, green, blue and alpha components of @rgba from the
|
||||
* color stored in @pixel. The pixel format of @pixel is determined
|
||||
* by @format.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
void
|
||||
pika_rgba_set_pixel (PikaRGB *rgba,
|
||||
const Babl *format,
|
||||
gconstpointer pixel)
|
||||
{
|
||||
g_return_if_fail (rgba != NULL);
|
||||
g_return_if_fail (format != NULL);
|
||||
g_return_if_fail (pixel != NULL);
|
||||
|
||||
babl_process (babl_fish (format,
|
||||
babl_format ("R'G'B'A double")),
|
||||
pixel, rgba, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgba_get_pixel:
|
||||
* @rgba: a #PikaRGB struct
|
||||
* @format: a Babl format
|
||||
* @pixel: (out caller-allocates): pointer to the destination pixel
|
||||
*
|
||||
* Writes the red, green, blue and alpha components of @rgba to the
|
||||
* color stored in @pixel. The pixel format of @pixel is determined by
|
||||
* @format.
|
||||
*
|
||||
* Since: 2.10
|
||||
**/
|
||||
void
|
||||
pika_rgba_get_pixel (const PikaRGB *rgba,
|
||||
const Babl *format,
|
||||
gpointer pixel)
|
||||
{
|
||||
g_return_if_fail (rgba != NULL);
|
||||
g_return_if_fail (format != NULL);
|
||||
g_return_if_fail (pixel != NULL);
|
||||
|
||||
babl_process (babl_fish (babl_format ("R'G'B'A double"),
|
||||
format),
|
||||
rgba, pixel, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgba_set:
|
||||
* @rgba: a #PikaRGB struct
|
||||
* @red: the red component
|
||||
* @green: the green component
|
||||
* @blue: the blue component
|
||||
* @alpha: the alpha component
|
||||
*
|
||||
* Sets the red, green, blue and alpha components of @rgb. The values
|
||||
* should be between 0.0 and 1.0 but there is no check to enforce this
|
||||
* and the values are set exactly as they are passed in.
|
||||
**/
|
||||
void
|
||||
pika_rgba_set (PikaRGB *rgba,
|
||||
gdouble r,
|
||||
gdouble g,
|
||||
gdouble b,
|
||||
gdouble a)
|
||||
{
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
rgba->r = r;
|
||||
rgba->g = g;
|
||||
rgba->b = b;
|
||||
rgba->a = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgba_set_uchar:
|
||||
* @rgba: a #PikaRGB struct
|
||||
* @red: the red component
|
||||
* @green: the green component
|
||||
* @blue: the blue component
|
||||
* @alpha: the alpha component
|
||||
*
|
||||
* Sets the red, green, blue and alpha components of @rgba from 8bit
|
||||
* values (0 to 255).
|
||||
**/
|
||||
void
|
||||
pika_rgba_set_uchar (PikaRGB *rgba,
|
||||
guchar r,
|
||||
guchar g,
|
||||
guchar b,
|
||||
guchar a)
|
||||
{
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
rgba->r = (gdouble) r / 255.0;
|
||||
rgba->g = (gdouble) g / 255.0;
|
||||
rgba->b = (gdouble) b / 255.0;
|
||||
rgba->a = (gdouble) a / 255.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_rgba_get_uchar:
|
||||
* @rgba: a #PikaRGB struct
|
||||
* @red: (out) (optional): Location for the red component
|
||||
* @green: (out) (optional): Location for the green component
|
||||
* @blue: (out) (optional): Location for the blue component
|
||||
* @alpha: (out) (optional): Location for the alpha component
|
||||
*
|
||||
* Gets the 8bit red, green, blue and alpha components of @rgba.
|
||||
**/
|
||||
void
|
||||
pika_rgba_get_uchar (const PikaRGB *rgba,
|
||||
guchar *r,
|
||||
guchar *g,
|
||||
guchar *b,
|
||||
guchar *a)
|
||||
{
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
if (r) *r = ROUND (CLAMP (rgba->r, 0.0, 1.0) * 255.0);
|
||||
if (g) *g = ROUND (CLAMP (rgba->g, 0.0, 1.0) * 255.0);
|
||||
if (b) *b = ROUND (CLAMP (rgba->b, 0.0, 1.0) * 255.0);
|
||||
if (a) *a = ROUND (CLAMP (rgba->a, 0.0, 1.0) * 255.0);
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgba_add (PikaRGB *rgba1,
|
||||
const PikaRGB *rgba2)
|
||||
{
|
||||
g_return_if_fail (rgba1 != NULL);
|
||||
g_return_if_fail (rgba2 != NULL);
|
||||
|
||||
rgba1->r += rgba2->r;
|
||||
rgba1->g += rgba2->g;
|
||||
rgba1->b += rgba2->b;
|
||||
rgba1->a += rgba2->a;
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgba_subtract (PikaRGB *rgba1,
|
||||
const PikaRGB *rgba2)
|
||||
{
|
||||
g_return_if_fail (rgba1 != NULL);
|
||||
g_return_if_fail (rgba2 != NULL);
|
||||
|
||||
rgba1->r -= rgba2->r;
|
||||
rgba1->g -= rgba2->g;
|
||||
rgba1->b -= rgba2->b;
|
||||
rgba1->a -= rgba2->a;
|
||||
}
|
||||
|
||||
void
|
||||
pika_rgba_multiply (PikaRGB *rgba,
|
||||
gdouble factor)
|
||||
{
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
rgba->r *= factor;
|
||||
rgba->g *= factor;
|
||||
rgba->b *= factor;
|
||||
rgba->a *= factor;
|
||||
}
|
||||
|
||||
gdouble
|
||||
pika_rgba_distance (const PikaRGB *rgba1,
|
||||
const PikaRGB *rgba2)
|
||||
{
|
||||
g_return_val_if_fail (rgba1 != NULL, 0.0);
|
||||
g_return_val_if_fail (rgba2 != NULL, 0.0);
|
||||
|
||||
return (fabs (rgba1->r - rgba2->r) +
|
||||
fabs (rgba1->g - rgba2->g) +
|
||||
fabs (rgba1->b - rgba2->b) +
|
||||
fabs (rgba1->a - rgba2->a));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_PARAM_RGB
|
||||
*/
|
||||
|
||||
#define PIKA_PARAM_SPEC_RGB(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), PIKA_TYPE_PARAM_RGB, PikaParamSpecRGB))
|
||||
|
||||
struct _PikaParamSpecRGB
|
||||
{
|
||||
GParamSpecBoxed parent_instance;
|
||||
|
||||
gboolean has_alpha;
|
||||
gboolean validate; /* change this to enable [0.0...1.0] */
|
||||
PikaRGB default_value;
|
||||
};
|
||||
|
||||
static void pika_param_rgb_class_init (GParamSpecClass *class);
|
||||
static void pika_param_rgb_init (GParamSpec *pspec);
|
||||
static void pika_param_rgb_set_default (GParamSpec *pspec,
|
||||
GValue *value);
|
||||
static gboolean pika_param_rgb_validate (GParamSpec *pspec,
|
||||
GValue *value);
|
||||
static gint pika_param_rgb_values_cmp (GParamSpec *pspec,
|
||||
const GValue *value1,
|
||||
const GValue *value2);
|
||||
|
||||
/**
|
||||
* pika_param_rgb_get_type:
|
||||
*
|
||||
* Reveals the object type
|
||||
*
|
||||
* Returns: the #GType for a PikaParamRGB object
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
GType
|
||||
pika_param_rgb_get_type (void)
|
||||
{
|
||||
static GType spec_type = 0;
|
||||
|
||||
if (! spec_type)
|
||||
{
|
||||
const GTypeInfo type_info =
|
||||
{
|
||||
sizeof (GParamSpecClass),
|
||||
NULL, NULL,
|
||||
(GClassInitFunc) pika_param_rgb_class_init,
|
||||
NULL, NULL,
|
||||
sizeof (PikaParamSpecRGB),
|
||||
0,
|
||||
(GInstanceInitFunc) pika_param_rgb_init
|
||||
};
|
||||
|
||||
spec_type = g_type_register_static (G_TYPE_PARAM_BOXED,
|
||||
"PikaParamRGB",
|
||||
&type_info, 0);
|
||||
}
|
||||
|
||||
return spec_type;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_param_rgb_class_init (GParamSpecClass *class)
|
||||
{
|
||||
class->value_type = PIKA_TYPE_RGB;
|
||||
class->value_set_default = pika_param_rgb_set_default;
|
||||
class->value_validate = pika_param_rgb_validate;
|
||||
class->values_cmp = pika_param_rgb_values_cmp;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_param_rgb_init (GParamSpec *pspec)
|
||||
{
|
||||
PikaParamSpecRGB *cspec = PIKA_PARAM_SPEC_RGB (pspec);
|
||||
|
||||
pika_rgba_set (&cspec->default_value, 0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_param_rgb_set_default (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
PikaParamSpecRGB *cspec = PIKA_PARAM_SPEC_RGB (pspec);
|
||||
|
||||
g_value_set_static_boxed (value, &cspec->default_value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_param_rgb_validate (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
PikaParamSpecRGB *rgb_spec = PIKA_PARAM_SPEC_RGB (pspec);
|
||||
PikaRGB *rgb = value->data[0].v_pointer;
|
||||
|
||||
if (rgb_spec->validate && rgb)
|
||||
{
|
||||
PikaRGB oval = *rgb;
|
||||
|
||||
pika_rgb_clamp (rgb);
|
||||
|
||||
return (oval.r != rgb->r ||
|
||||
oval.g != rgb->g ||
|
||||
oval.b != rgb->b ||
|
||||
(rgb_spec->has_alpha && oval.a != rgb->a));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
pika_param_rgb_values_cmp (GParamSpec *pspec,
|
||||
const GValue *value1,
|
||||
const GValue *value2)
|
||||
{
|
||||
PikaRGB *rgb1 = value1->data[0].v_pointer;
|
||||
PikaRGB *rgb2 = value2->data[0].v_pointer;
|
||||
|
||||
/* try to return at least *something*, it's useless anyway... */
|
||||
|
||||
if (! rgb1)
|
||||
{
|
||||
return rgb2 != NULL ? -1 : 0;
|
||||
}
|
||||
else if (! rgb2)
|
||||
{
|
||||
return rgb1 != NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
guint32 int1 = 0;
|
||||
guint32 int2 = 0;
|
||||
|
||||
if (PIKA_PARAM_SPEC_RGB (pspec)->has_alpha)
|
||||
{
|
||||
pika_rgba_get_uchar (rgb1,
|
||||
((guchar *) &int1) + 0,
|
||||
((guchar *) &int1) + 1,
|
||||
((guchar *) &int1) + 2,
|
||||
((guchar *) &int1) + 3);
|
||||
pika_rgba_get_uchar (rgb2,
|
||||
((guchar *) &int2) + 0,
|
||||
((guchar *) &int2) + 1,
|
||||
((guchar *) &int2) + 2,
|
||||
((guchar *) &int2) + 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_rgb_get_uchar (rgb1,
|
||||
((guchar *) &int1) + 0,
|
||||
((guchar *) &int1) + 1,
|
||||
((guchar *) &int1) + 2);
|
||||
pika_rgb_get_uchar (rgb2,
|
||||
((guchar *) &int2) + 0,
|
||||
((guchar *) &int2) + 1,
|
||||
((guchar *) &int2) + 2);
|
||||
}
|
||||
|
||||
return int1 - int2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_param_spec_rgb:
|
||||
* @name: Canonical name of the param
|
||||
* @nick: Nickname of the param
|
||||
* @blurb: Brief description of param.
|
||||
* @has_alpha: %TRUE if the alpha channel has relevance.
|
||||
* @default_value: Value to use if none is assigned.
|
||||
* @flags: a combination of #GParamFlags
|
||||
*
|
||||
* Creates a param spec to hold an #PikaRGB value.
|
||||
* See g_param_spec_internal() for more information.
|
||||
*
|
||||
* Returns: (transfer full): a newly allocated #GParamSpec instance
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
GParamSpec *
|
||||
pika_param_spec_rgb (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
gboolean has_alpha,
|
||||
const PikaRGB *default_value,
|
||||
GParamFlags flags)
|
||||
{
|
||||
PikaParamSpecRGB *cspec;
|
||||
|
||||
cspec = g_param_spec_internal (PIKA_TYPE_PARAM_RGB,
|
||||
name, nick, blurb, flags);
|
||||
|
||||
cspec->has_alpha = has_alpha;
|
||||
|
||||
if (default_value)
|
||||
cspec->default_value = *default_value;
|
||||
else
|
||||
pika_rgba_set (&cspec->default_value, 0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
return G_PARAM_SPEC (cspec);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_param_spec_rgb_get_default:
|
||||
* @pspec: a #PikaParamSpecRGB.
|
||||
* @default_value: return location for @pspec's default value
|
||||
*
|
||||
* Returns the @pspec's default color value.
|
||||
*
|
||||
* Since: 2.10.14
|
||||
**/
|
||||
void
|
||||
pika_param_spec_rgb_get_default (GParamSpec *pspec,
|
||||
PikaRGB *default_value)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PARAM_SPEC_RGB (pspec));
|
||||
g_return_if_fail (default_value != NULL);
|
||||
|
||||
*default_value = PIKA_PARAM_SPEC_RGB (pspec)->default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_param_spec_rgb_has_alpha:
|
||||
* @pspec: a #GParamSpec to hold an #PikaRGB value.
|
||||
*
|
||||
* Returns: %TRUE if the alpha channel is relevant.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gboolean
|
||||
pika_param_spec_rgb_has_alpha (GParamSpec *pspec)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PARAM_SPEC_RGB (pspec), FALSE);
|
||||
|
||||
return PIKA_PARAM_SPEC_RGB (pspec)->has_alpha;
|
||||
}
|
208
libpikacolor/pikargb.h
Normal file
208
libpikacolor/pikargb.h
Normal file
@ -0,0 +1,208 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* 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 3 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
|
||||
* Library 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
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_COLOR_H_INSIDE__) && !defined (PIKA_COLOR_COMPILATION)
|
||||
#error "Only <libpikacolor/pikacolor.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_RGB_H__
|
||||
#define __PIKA_RGB_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_RGB
|
||||
*/
|
||||
|
||||
#define PIKA_TYPE_RGB (pika_rgb_get_type ())
|
||||
#define PIKA_VALUE_HOLDS_RGB(value) (G_TYPE_CHECK_VALUE_TYPE ((value), PIKA_TYPE_RGB))
|
||||
|
||||
GType pika_rgb_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_value_get_rgb (const GValue *value,
|
||||
PikaRGB *rgb);
|
||||
void pika_value_set_rgb (GValue *value,
|
||||
const PikaRGB *rgb);
|
||||
|
||||
|
||||
/*
|
||||
* PIKA_TYPE_PARAM_RGB
|
||||
*/
|
||||
|
||||
#define PIKA_TYPE_PARAM_RGB (pika_param_rgb_get_type ())
|
||||
#define PIKA_IS_PARAM_SPEC_RGB(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), PIKA_TYPE_PARAM_RGB))
|
||||
|
||||
typedef struct _PikaParamSpecRGB PikaParamSpecRGB;
|
||||
|
||||
GType pika_param_rgb_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GParamSpec * pika_param_spec_rgb (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
gboolean has_alpha,
|
||||
const PikaRGB *default_value,
|
||||
GParamFlags flags);
|
||||
|
||||
void pika_param_spec_rgb_get_default (GParamSpec *pspec,
|
||||
PikaRGB *default_value);
|
||||
gboolean pika_param_spec_rgb_has_alpha (GParamSpec *pspec);
|
||||
|
||||
|
||||
/* RGB and RGBA color types and operations taken from LibGCK */
|
||||
|
||||
/**
|
||||
* PikaRGBCompositeMode:
|
||||
* @PIKA_RGB_COMPOSITE_NONE: don't do compositing
|
||||
* @PIKA_RGB_COMPOSITE_NORMAL: composite on top
|
||||
* @PIKA_RGB_COMPOSITE_BEHIND: composite behind
|
||||
**/
|
||||
typedef enum
|
||||
{
|
||||
PIKA_RGB_COMPOSITE_NONE = 0,
|
||||
PIKA_RGB_COMPOSITE_NORMAL,
|
||||
PIKA_RGB_COMPOSITE_BEHIND
|
||||
} PikaRGBCompositeMode;
|
||||
|
||||
|
||||
void pika_rgb_set (PikaRGB *rgb,
|
||||
gdouble red,
|
||||
gdouble green,
|
||||
gdouble blue);
|
||||
void pika_rgb_set_alpha (PikaRGB *rgb,
|
||||
gdouble alpha);
|
||||
|
||||
void pika_rgb_set_pixel (PikaRGB *rgb,
|
||||
const Babl *format,
|
||||
gconstpointer pixel);
|
||||
void pika_rgb_get_pixel (const PikaRGB *rgb,
|
||||
const Babl *format,
|
||||
gpointer pixel);
|
||||
|
||||
void pika_rgb_set_uchar (PikaRGB *rgb,
|
||||
guchar red,
|
||||
guchar green,
|
||||
guchar blue);
|
||||
void pika_rgb_get_uchar (const PikaRGB *rgb,
|
||||
guchar *red,
|
||||
guchar *green,
|
||||
guchar *blue);
|
||||
|
||||
gboolean pika_rgb_parse_name (PikaRGB *rgb,
|
||||
const gchar *name,
|
||||
gint len);
|
||||
gboolean pika_rgb_parse_hex (PikaRGB *rgb,
|
||||
const gchar *hex,
|
||||
gint len);
|
||||
gboolean pika_rgb_parse_css (PikaRGB *rgb,
|
||||
const gchar *css,
|
||||
gint len);
|
||||
|
||||
void pika_rgb_add (PikaRGB *rgb1,
|
||||
const PikaRGB *rgb2);
|
||||
void pika_rgb_subtract (PikaRGB *rgb1,
|
||||
const PikaRGB *rgb2);
|
||||
void pika_rgb_multiply (PikaRGB *rgb1,
|
||||
gdouble factor);
|
||||
gdouble pika_rgb_distance (const PikaRGB *rgb1,
|
||||
const PikaRGB *rgb2);
|
||||
|
||||
gdouble pika_rgb_max (const PikaRGB *rgb);
|
||||
gdouble pika_rgb_min (const PikaRGB *rgb);
|
||||
void pika_rgb_clamp (PikaRGB *rgb);
|
||||
|
||||
void pika_rgb_gamma (PikaRGB *rgb,
|
||||
gdouble gamma);
|
||||
|
||||
gdouble pika_rgb_luminance (const PikaRGB *rgb);
|
||||
guchar pika_rgb_luminance_uchar (const PikaRGB *rgb);
|
||||
|
||||
void pika_rgb_composite (PikaRGB *color1,
|
||||
const PikaRGB *color2,
|
||||
PikaRGBCompositeMode mode);
|
||||
|
||||
/* access to the list of color names */
|
||||
void pika_rgb_list_names (const gchar ***names,
|
||||
PikaRGB **colors,
|
||||
gint *n_colors);
|
||||
|
||||
|
||||
void pika_rgba_set (PikaRGB *rgba,
|
||||
gdouble red,
|
||||
gdouble green,
|
||||
gdouble blue,
|
||||
gdouble alpha);
|
||||
|
||||
void pika_rgba_set_pixel (PikaRGB *rgba,
|
||||
const Babl *format,
|
||||
gconstpointer pixel);
|
||||
void pika_rgba_get_pixel (const PikaRGB *rgba,
|
||||
const Babl *format,
|
||||
gpointer pixel);
|
||||
|
||||
void pika_rgba_set_uchar (PikaRGB *rgba,
|
||||
guchar red,
|
||||
guchar green,
|
||||
guchar blue,
|
||||
guchar alpha);
|
||||
void pika_rgba_get_uchar (const PikaRGB *rgba,
|
||||
guchar *red,
|
||||
guchar *green,
|
||||
guchar *blue,
|
||||
guchar *alpha);
|
||||
|
||||
gboolean pika_rgba_parse_css (PikaRGB *rgba,
|
||||
const gchar *css,
|
||||
gint len);
|
||||
|
||||
void pika_rgba_add (PikaRGB *rgba1,
|
||||
const PikaRGB *rgba2);
|
||||
void pika_rgba_subtract (PikaRGB *rgba1,
|
||||
const PikaRGB *rgba2);
|
||||
void pika_rgba_multiply (PikaRGB *rgba,
|
||||
gdouble factor);
|
||||
|
||||
gdouble pika_rgba_distance (const PikaRGB *rgba1,
|
||||
const PikaRGB *rgba2);
|
||||
|
||||
|
||||
|
||||
/* Map D50-adapted sRGB to luminance */
|
||||
|
||||
/*
|
||||
* The weights to compute true CIE luminance from linear red, green
|
||||
* and blue as defined by the sRGB color space specs in an ICC profile
|
||||
* color managed application. The weights below have been chromatically
|
||||
* adapted from D65 (as specified by the sRGB color space specs)
|
||||
* to D50 (as specified by D50 illuminant values in the ICC V4 specs).
|
||||
*/
|
||||
|
||||
#define PIKA_RGB_LUMINANCE_RED (0.22248840)
|
||||
#define PIKA_RGB_LUMINANCE_GREEN (0.71690369)
|
||||
#define PIKA_RGB_LUMINANCE_BLUE (0.06060791)
|
||||
|
||||
#define PIKA_RGB_LUMINANCE(r,g,b) ((r) * PIKA_RGB_LUMINANCE_RED + \
|
||||
(g) * PIKA_RGB_LUMINANCE_GREEN + \
|
||||
(b) * PIKA_RGB_LUMINANCE_BLUE)
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_RGB_H__ */
|
119
libpikacolor/test-color-parser.c
Normal file
119
libpikacolor/test-color-parser.c
Normal file
@ -0,0 +1,119 @@
|
||||
/* unit tests for the color parsing routines in pikargb-parse.c
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <babl/babl.h>
|
||||
#include <gegl.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#include "pikacolor.h"
|
||||
|
||||
|
||||
#define DBL(c) ((gdouble)(c) / 255.0)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar *str;
|
||||
gboolean alpha;
|
||||
gboolean fail;
|
||||
const gdouble r;
|
||||
const gdouble g;
|
||||
const gdouble b;
|
||||
const gdouble a;
|
||||
} ColorSample;
|
||||
|
||||
static const ColorSample samples[] =
|
||||
{
|
||||
/* sample alpha fail red green blue alpha */
|
||||
|
||||
{ "#000000", FALSE, FALSE, 0.0, 0.0, 0.0, 0.0 },
|
||||
{ "#FFff00", FALSE, FALSE, 1.0, 1.0, 0.0, 0.0 },
|
||||
{ "#6495ed", FALSE, FALSE, DBL(100), DBL(149), DBL(237), 0.0 },
|
||||
{ "#fff", FALSE, FALSE, 1.0, 1.0, 1.0, 0.0 },
|
||||
{ "#64649595eded", FALSE, FALSE, 1.0, 1.0, 0.0, 0.0 },
|
||||
{ "rgb(0,0,0)", FALSE, FALSE, 0.0, 0.0, 0.0, 0.0 },
|
||||
{ "rgb(100,149,237)", FALSE, FALSE, DBL(100), DBL(149), DBL(237), 0.0 },
|
||||
{ "rgba(100%,0,100%,0.5)", TRUE, FALSE, 255.0, 0.0, 255.0, 0.5 },
|
||||
{ "rgba(100%,0,100%,0.5)", FALSE, TRUE, 255.0, 0.0, 255.0, 0.5 },
|
||||
{ "rgb(100%,149,20%)", FALSE, FALSE, 1.0, DBL(149), 0.2, 0.0 },
|
||||
{ "rgb(100%,149,20%)", TRUE, TRUE, 1.0, DBL(149), 0.2, 0.0 },
|
||||
{ "rgb(foobar)", FALSE, TRUE, 0.0, 0.0, 0.0, 0.0 },
|
||||
{ "rgb(100,149,237", FALSE, TRUE, 0.0, 0.0, 0.0, 0.0 },
|
||||
{ "rED", FALSE, FALSE, 1.0, 0.0, 0.0, 0.0 },
|
||||
{ "cornflowerblue", FALSE, FALSE, DBL(100), DBL(149), DBL(237), 0.0 },
|
||||
{ " red", FALSE, FALSE, 1.0, 0.0, 0.0, 0.0 },
|
||||
{ "red ", FALSE, FALSE, 1.0, 0.0, 0.0, 0.0 },
|
||||
{ "red", TRUE, TRUE, 1.0, 0.0, 0.0, 0.0 },
|
||||
{ "red blue", FALSE, TRUE, 0.0, 0.0, 0.0, 0.0 },
|
||||
{ "transparent", FALSE, TRUE, 0.0, 0.0, 0.0, 0.0 },
|
||||
{ "transparent", TRUE, FALSE, 0.0, 0.0, 0.0, 0.0 },
|
||||
{ "23foobar", FALSE, TRUE, 0.0, 0.0, 0.0, 0.0 },
|
||||
{ "", FALSE, TRUE, 0.0, 0.0, 0.0, 0.0 }
|
||||
};
|
||||
|
||||
|
||||
static gint
|
||||
check_failure (const ColorSample *sample,
|
||||
gboolean success,
|
||||
PikaRGB *rgb)
|
||||
{
|
||||
if (success && sample->fail)
|
||||
{
|
||||
g_print ("Parser succeeded for sample \"%s\" but should have failed!\n"
|
||||
" parsed color: (%g, %g, %g, %g)\n",
|
||||
sample->str, rgb->r, rgb->g, rgb->b, rgb->a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!success && !sample->fail)
|
||||
{
|
||||
g_print ("Parser failed for sample \"%s\" but should have succeeded!\n"
|
||||
" parsed color: (%g, %g, %g, %g)\n",
|
||||
sample->str, rgb->r, rgb->g, rgb->b, rgb->a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
gint failures = 0;
|
||||
gint i;
|
||||
|
||||
g_print ("\nTesting the PIKA color parser ...\n");
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (samples); i++)
|
||||
{
|
||||
PikaRGB rgb = { 0.0, 0.0, 0.0, 0.0 };
|
||||
gboolean success;
|
||||
|
||||
if (samples[i].alpha)
|
||||
success = pika_rgba_parse_css (&rgb, samples[i].str, -1);
|
||||
else
|
||||
success = pika_rgb_parse_css (&rgb, samples[i].str, -1);
|
||||
|
||||
failures += check_failure (samples + i, success, &rgb);
|
||||
}
|
||||
|
||||
if (failures)
|
||||
{
|
||||
g_print ("%d out of %d samples failed!\n\n",
|
||||
failures, (int)G_N_ELEMENTS (samples));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("All %d samples passed.\n\n", (int)G_N_ELEMENTS (samples));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user