gegl-utils.c 14 KB
Newer Older
1
/* This file is part of GEGL
2
 *
3 4 5
 * GEGL 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
6
 * version 3 of the License, or (at your option) any later version.
7
 *
8 9 10 11
 * GEGL 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.
12
 *
13
 * You should have received a copy of the GNU Lesser General Public
14
 * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
15
 *
16
 * Copyright 2003-2007 Calvin Williamson, Øyvind Kolås.
17 18
 */

Michael Natterer's avatar
Michael Natterer committed
19 20
#include "config.h"

21
#include <string.h>
22 23
#include <glib-object.h>

24
#include "gegl.h"
25
#include "gegl-types-internal.h"
26
#include "gegl-utils.h"
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

void
gegl_buffer_set_color (GeglBuffer          *dst,
                       const GeglRectangle *dst_rect,
                       GeglColor           *color)
{
  guchar pixel[128];
  const Babl *format;
  g_return_if_fail (GEGL_IS_BUFFER (dst));
  g_return_if_fail (color);
  format = gegl_buffer_get_format (dst);

  gegl_color_get_pixel (color, format, pixel);
  gegl_buffer_set_color_from_pixel (dst, dst_rect, &pixel[0], format);
}

44

45 46
static const Babl *
gegl_babl_format_linear_float (const Babl *format)
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
{
  const Babl *space = babl_format_get_space (format);
  const Babl *model = NULL;
  if (!format)
    return babl_format ("RGBA float");

  model = babl_format_get_model (format);

  if (babl_model_is (model, "Y") ||
      babl_model_is (model, "Y'") ||
      babl_model_is (model, "Y~"))
  {
    format = babl_format_with_space ("Y float", space);
  }
  else if (babl_model_is (model, "YA") ||
           babl_model_is (model, "Y'A") ||
           babl_model_is (model, "Y~A") ||
64
           babl_model_is (model, "Y~aA") ||
65 66 67 68 69
           babl_model_is (model, "YaA") ||
           babl_model_is (model, "Y'aA"))
  {
    format = babl_format_with_space ("YA float", space);
  }
70 71 72 73 74 75 76 77 78
  else if (babl_model_is (model, "cmyk") ||
           babl_model_is (model, "cmykA") ||
           babl_model_is (model, "camayakaA") ||
           babl_model_is (model, "CMYK") ||
           babl_model_is (model, "CMYKA") ||
           babl_model_is (model, "CaMaYaKaA"))
  {
    format  = babl_format_with_space ("cmykA float", space);
  }
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
  else if (babl_model_is (model, "RGB") ||
           babl_model_is (model, "R'G'B'") ||
           babl_model_is (model, "R~G~B~"))
  {
    format = babl_format_with_space ("RGB float", space);
  }
#if 0 // just treat as else
           babl_model_is (model, "RGBA")    ||
           babl_model_is (model, "R'G'B'A") ||
           babl_model_is (model, "R'G'B'")  ||
           babl_model_is (model, "R~G~B~A") ||
           babl_model_is (model, "R~G~B~")  ||
           babl_model_is (model, "RaGaBaA") ||
           babl_model_is (model, "R'aG'aB'aA"))
  {
    format  = babl_format_with_space (use_srgb?"R~aG~aB~aA float":"RaGaBaA float", space);
  }
#endif
  else
  {
    format  = babl_format_with_space ("RGBA float", space);
  }
  return format;
}

104 105
static const Babl *
gegl_babl_format_perceptual_float (const Babl *format)
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
{
  const Babl *space = babl_format_get_space (format);
  const Babl *model = NULL;
  if (!format)
    return babl_format ("R~G~B~A float");

  model = babl_format_get_model (format);

  if (babl_model_is (model, "Y") ||
      babl_model_is (model, "Y'") ||
      babl_model_is (model, "Y~"))
  {
    format = babl_format_with_space ("Y~ float", space);
  }
  else if (babl_model_is (model, "YA") ||
           babl_model_is (model, "Y'A") ||
           babl_model_is (model, "Y~A") ||
123
           babl_model_is (model, "Y~aA") ||
124 125 126 127 128
           babl_model_is (model, "YaA") ||
           babl_model_is (model, "Y'aA"))
  {
    format = babl_format_with_space ("Y~A float", space);
  }
129 130 131 132 133 134 135 136 137
  else if (babl_model_is (model, "cmyk") ||
           babl_model_is (model, "cmykA") ||
           babl_model_is (model, "camayakaA") ||
           babl_model_is (model, "CMYK") ||
           babl_model_is (model, "CMYKA") ||
           babl_model_is (model, "CaMaYaKaA"))
  {
    format  = babl_format_with_space ("cmykA float", space);
  }
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
  else if (babl_model_is (model, "RGB") ||
           babl_model_is (model, "R'G'B'") ||
           babl_model_is (model, "R~G~B~"))
  {
    format = babl_format_with_space ("R~G~B~ float", space);
  }
#if 0 // just treat as else
           babl_model_is (model, "RGBA")    ||
           babl_model_is (model, "R'G'B'A") ||
           babl_model_is (model, "R'G'B'")  ||
           babl_model_is (model, "R~G~B~A") ||
           babl_model_is (model, "R~G~B~")  ||
           babl_model_is (model, "RaGaBaA") ||
           babl_model_is (model, "R'aG'aB'aA"))
  {
    format  = babl_format_with_space (use_srgb?"R~aG~aB~aA float":"RaGaBaA float", space);
  }
#endif
  else
  {
    format  = babl_format_with_space ("R~G~B~A float", space);
  }
  return format;
}

163 164
static const Babl *
gegl_babl_format_nonlinear_float (const Babl *format)
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
{
  const Babl *space = babl_format_get_space (format);
  const Babl *model = NULL;
  if (!format)
    return babl_format ("R'G'B'A float");

  model = babl_format_get_model (format);

  if (babl_model_is (model, "Y") ||
      babl_model_is (model, "Y'") ||
      babl_model_is (model, "Y~"))
  {
    format = babl_format_with_space ("Y' float", space);
  }
  else if (babl_model_is (model, "YA") ||
           babl_model_is (model, "Y'A") ||
           babl_model_is (model, "Y~A") ||
182
           babl_model_is (model, "Y~aA") ||
183 184 185 186 187
           babl_model_is (model, "YaA") ||
           babl_model_is (model, "Y'aA"))
  {
    format = babl_format_with_space ("Y'A float", space);
  }
188 189 190 191 192 193 194 195 196
  else if (babl_model_is (model, "cmyk") ||
           babl_model_is (model, "cmykA") ||
           babl_model_is (model, "camayakaA") ||
           babl_model_is (model, "CMYK") ||
           babl_model_is (model, "CMYKA") ||
           babl_model_is (model, "CaMaYaKaA"))
  {
    format  = babl_format_with_space ("cmykA float", space);
  }
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
  else if (babl_model_is (model, "RGB") ||
           babl_model_is (model, "R'G'B'") ||
           babl_model_is (model, "R~G~B~"))
  {
    format = babl_format_with_space ("R'G'B' float", space);
  }
#if 0 // just treat as else
           babl_model_is (model, "RGBA")    ||
           babl_model_is (model, "R'G'B'A") ||
           babl_model_is (model, "R'G'B'")  ||
           babl_model_is (model, "R~G~B~A") ||
           babl_model_is (model, "R~G~B~")  ||
           babl_model_is (model, "RaGaBaA") ||
           babl_model_is (model, "R'aG'aB'aA"))
  {
    format  = babl_format_with_space (use_srgb?"R~aG~aB~aA float":"RaGaBaA float", space);
  }
#endif
  else
  {
    format  = babl_format_with_space ("R'G'B'A float", space);
  }
  return format;
}

222 223
static const Babl *
gegl_babl_format_premultiplied_linear_float (const Babl *format)
224 225 226 227 228 229 230 231 232 233 234 235 236 237
{
  const Babl *space = babl_format_get_space (format);
  const Babl *model = NULL;
  if (!format)
    return babl_format ("RaGaBaA float");

  model = babl_format_get_model (format);

  if (babl_model_is (model, "Y") ||
      babl_model_is (model, "Y'") ||
      babl_model_is (model, "Y~") ||
      babl_model_is (model, "YA") ||
      babl_model_is (model, "Y'A") ||
      babl_model_is (model, "Y~A") ||
238
      babl_model_is (model, "Y~aA") ||
239 240 241 242 243
      babl_model_is (model, "YaA") ||
      babl_model_is (model, "Y'aA"))
  {
    format = babl_format_with_space ("YaA float", space);
  }
244 245 246 247 248 249 250 251 252
  else if (babl_model_is (model, "cmyk") ||
           babl_model_is (model, "cmykA") ||
           babl_model_is (model, "camayakaA") ||
           babl_model_is (model, "CMYK") ||
           babl_model_is (model, "CMYKA") ||
           babl_model_is (model, "CaMaYaKaA"))
  {
    format  = babl_format_with_space ("camayakaA float", space);
  }
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
#if 0 // just treat as else
  else if (babl_model_is (model, "RGB") ||
           babl_model_is (model, "R'G'B'") ||
           babl_model_is (model, "R~G~B~") ||
           babl_model_is (model, "RGBA")    ||
           babl_model_is (model, "RGB")     ||
           babl_model_is (model, "R'G'B'A") ||
           babl_model_is (model, "R'G'B'")  ||
           babl_model_is (model, "R~G~B~A") ||
           babl_model_is (model, "R~G~B~")  ||
           babl_model_is (model, "RaGaBaA") ||
           babl_model_is (model, "R'aG'aB'aA"))
  {
    format  = babl_format_with_space (use_srgb?"R~aG~aB~aA float":"RaGaBaA float", space);
  }
#endif
  else
  {
    format  = babl_format_with_space ("RaGaBaA float", space);
  }
  return format;
}

276 277
static const Babl *
gegl_babl_format_premultiplied_perceptual_float (const Babl *format)
278 279 280 281 282 283 284 285 286 287 288 289 290 291
{
  const Babl *space = babl_format_get_space (format);
  const Babl *model = NULL;
  if (!format)
    return babl_format ("R~aG~aB~aA float");

  model = babl_format_get_model (format);

  if (babl_model_is (model, "Y") ||
      babl_model_is (model, "Y'") ||
      babl_model_is (model, "Y~") ||
      babl_model_is (model, "YA") ||
      babl_model_is (model, "Y'A") ||
      babl_model_is (model, "Y~A") ||
292
      babl_model_is (model, "Y~aA") ||
293 294 295 296 297
      babl_model_is (model, "YaA") ||
      babl_model_is (model, "Y'aA"))
  {
    format = babl_format_with_space ("Y~aA float", space);
  }
298 299 300 301 302 303 304 305 306
  else if (babl_model_is (model, "cmyk") ||
      babl_model_is (model, "cmykA") ||
      babl_model_is (model, "camayakaA") ||
      babl_model_is (model, "CMYK") ||
      babl_model_is (model, "CMYKA") ||
      babl_model_is (model, "CaMaYaKaA"))
  {
    format  = babl_format_with_space ("camayakaA float", space);
  }
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
#if 0 // just treat as else
  else if (babl_model_is (model, "RGB") ||
           babl_model_is (model, "R'G'B'") ||
           babl_model_is (model, "R~G~B~") ||
           babl_model_is (model, "RGBA")    ||
           babl_model_is (model, "RGB")     ||
           babl_model_is (model, "R'G'B'A") ||
           babl_model_is (model, "R'G'B'")  ||
           babl_model_is (model, "R~G~B~A") ||
           babl_model_is (model, "R~G~B~")  ||
           babl_model_is (model, "RaGaBaA") ||
           babl_model_is (model, "R'aG'aB'aA"))
  {
    format  = babl_format_with_space (use_srgb?"R~aG~aB~aA float":"RaGaBaA float", space);
  }
#endif
  else
  {
    format  = babl_format_with_space ("R~aG~aB~aA float", space);
  }
  return format;
}

330 331
static const Babl *
gegl_babl_format_float (const Babl *format)
332 333 334 335 336 337 338 339
{
  const Babl *space;
  const char *encoding;
  if (!format)
    return NULL;
  space = babl_format_get_space (format);
  encoding  = babl_format_get_encoding (format);

340
  {
341 342 343 344 345 346 347 348 349
  char *encdup = g_strdup (encoding);
  char *newenc;
  char *s = strrchr (encdup, ' ');
  if (s) *s = 0;
  newenc = g_strdup_printf ("%s float", encdup);
  format = babl_format_with_space (newenc, space);

  g_free (encdup);
  g_free (newenc);
350
  }
351 352 353
  return format;
}

354 355
static const Babl *
gegl_babl_format_alpha (const Babl *format)
356 357
{
  const Babl *model = babl_format_get_model (format);
358 359
  BablModelFlag model_flags = babl_get_model_flags (model);
  if (model_flags & BABL_MODEL_FLAG_ALPHA)
360 361 362 363 364 365 366 367 368 369 370 371 372 373
  {
    const Babl *type = babl_format_get_type (format, 0);
    if (type == babl_type ("float"))
      return format;
  }

  if (babl_model_is (model, "Y'"))
  {
    return babl_format_with_space ("Y'A float", format);
  }
  else if (babl_model_is (model, "Y"))
  {
    return babl_format_with_space ("YA float", format);
  }
374 375
  else if (babl_model_is (model, "RGB")||
           babl_model_is (model, "RGBA"))
376 377 378
  {
    return babl_format_with_space ("RGBA float", format);
  }
379 380 381 382 383 384 385 386 387 388
  else if (babl_model_is (model, "RaGaBaA"))
  {
    return babl_format_with_space ("RaGaBaA float", format);
  }
  else if (babl_model_is (model, "R'aG'aB'aA"))
  {
    return babl_format_with_space ("R'aG'aB'aA float", format);
  }
  else if (babl_model_is (model, "R'G'B'")||
           babl_model_is (model, "R'G'B'A"))
389 390 391 392
  {
    return babl_format_with_space ("R'G'B'A float", format);
  }
  else if (babl_model_is (model, "cmyk") ||
393
           babl_model_is (model, "cmykA"))
394 395 396
  {
    return babl_format_with_space ("cmykA float", format);
  }
397 398 399 400 401 402 403 404 405 406 407 408 409
  else if (babl_model_is (model, "CMYK") ||
           babl_model_is (model, "CMYKA"))
  {
    return babl_format_with_space ("cmykA float", format);
  }
  else if (babl_model_is (model, "CaMaYaKaA"))
  {
    return babl_format_with_space ("CaMaYaKaA float", format);
  }
  else if (babl_model_is (model, "camayakaA"))
  {
    return babl_format_with_space ("camayakaA float", format);
  }
410 411 412 413 414

  return babl_format_with_space ("RGBA float", format);
}


415 416
static const Babl *
gegl_babl_format_float_premultiplied_linear_if_alpha (const Babl *format)
417 418 419 420 421 422 423 424
{
  if (!format)
    return NULL;
  if (babl_format_has_alpha (format))
    return gegl_babl_format_premultiplied_linear_float (format);
  return gegl_babl_format_float (format);
}

425 426
static const Babl *
gegl_babl_format_float_premultiplied_perceptual_if_alpha (const Babl *format)
427 428 429 430 431 432 433 434
{
  if (!format)
    return NULL;
  if (babl_format_has_alpha (format))
    return gegl_babl_format_premultiplied_perceptual_float (format);
  return gegl_babl_format_float (format);
}

435 436
const Babl *
gegl_babl_variant (const Babl *format, GeglBablVariant variant)
437 438 439 440 441
{
  if (!format)
    return NULL;
  switch (variant)
  {
442 443
    case GEGL_BABL_VARIANT_ALPHA:
      return gegl_babl_format_alpha (format);
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
    case GEGL_BABL_VARIANT_FLOAT:
      return gegl_babl_format_float (format);
    case GEGL_BABL_VARIANT_LINEAR:
      return gegl_babl_format_linear_float (format);
    case GEGL_BABL_VARIANT_NONLINEAR:
      return gegl_babl_format_nonlinear_float (format);
    case GEGL_BABL_VARIANT_PERCEPTUAL:
      return gegl_babl_format_perceptual_float (format);
    case GEGL_BABL_VARIANT_LINEAR_PREMULTIPLIED:
      return gegl_babl_format_premultiplied_linear_float (format);
    case GEGL_BABL_VARIANT_PERCEPTUAL_PREMULTIPLIED:
      return gegl_babl_format_premultiplied_perceptual_float (format);
    case GEGL_BABL_VARIANT_LINEAR_PREMULTIPLIED_IF_ALPHA:
      return gegl_babl_format_float_premultiplied_linear_if_alpha (format);
    case GEGL_BABL_VARIANT_PERCEPTUAL_PREMULTIPLIED_IF_ALPHA:
      return gegl_babl_format_float_premultiplied_perceptual_if_alpha (format);
  }
  return format;
}