1 /* 2 Copyright (C) 2017-2021, Dirk Krause 3 SPDX-License-Identifier: BSD-3-Clause 4 */ 5 6 /* 7 WARNING: This file was generated by the dkct program (see 8 http://dktools.sourceforge.net/ for details). 9 Changes you make here will be lost if dkct is run again! 10 You should modify the original source and run dkct on it. 11 Original source: dk4cs.ctr 12 */ 13 14 #ifndef DK4CS_H_INCLUDED 15 /** Avoid multiple inclusions. */ 16 #define DK4CS_H_INCLUDED 1 17 18 19 /** @file dk4cs.h Color spaces, especially for bitmap images. 20 21 This module provides color space conversion functions. 22 23 Note: You should not use this module for conversion from other color spaces 24 to CMYK or vice versa. Conversion to CMYK should be done by professional 25 programs, as the conversion depends on the production process, the used 26 inks, and the used paper. Professional conversion programs use color profiles 27 and let you choose a number of settings. This module uses just simple 28 formulas. 29 30 The following symbols are used in formulas below: 31 32 Symbol | Meaning 33 :----: | :-----: 34 d | Bit depth (integer), number of bits per component (sample) 35 M | Maximum component value (integer), 2^d-1 36 r | Red component for a pixel (integer), 0<=r<=M 37 g | Green component for a pixel (integer), 0<=r<=M 38 b | Blue component for a pixel (integer), 0<=b<=M 39 e | Gray value for a pixel (integer), 0<=e<=M 40 c | Cyan component for a pixel (integer), 0<=c<=M 41 m | Magenta component for a pixel (integer), 0<=m<=M 42 y | Yellow component for pixel (integer), 0<=y<=M 43 k | Black or key component for a pixel (integer), 0<=k<=M 44 maxrgb | Maximum value of r, g, and b (integer), 0<=maxrgb<=M 45 mincmy | Minimum value of c, m, and y (integer), 0<=mincmy<=M 46 r' | Normalized red component (floating point), 0.0<=r'<=1.0 47 g' | Normalized green component (floating point), 0.0<=g'<=1.0 48 b' | Normalized blue component (floating point), 0.0<=b'<=1.0 49 e' | Normalized gray component (floating point), 0.0<=e'<=1.0 50 c' | Normalized cyan component (floating point), 0.0<=c'<=1.0 51 m' | Normalized magenta component (floating point), 0.0<=m'<=1.0 52 y' | Normalized yellow component (floating point), 0.0<=y'<=1.0 53 k' | Normalized black component (floating point), 0.0<=k'<=1.0 54 maxrgb' | Normalized red component (floating point), 0.0<=maxrgb'<=1.0 55 mincmy' | Normalized red component (floating point), 0.0<=mincmy'<=1.0 56 ucr(x) | Undercolour removal function, maps [0,1] to [0,1] 57 bg(x) | Black generation function, maps [0,1] to [0,1] 58 59 To switch from default algorithms to other algorithms, open a 60 conversion context, set up the conversion context, pass the context to 61 the conversion functions and close the context when no longer needed. 62 */ 63 64 #ifndef DK4CONF_H_INCLUDED 65 #if DK4_BUILDING_DKTOOLS4 66 #include "dk4conf.h" 67 #else 68 #include <dktools-4/dk4conf.h> 69 #endif 70 #endif 71 72 #ifndef DK4TYPES_H_INCLUDED 73 #if DK4_BUILDING_DKTOOLS4 74 #include <libdk4base/dk4types.h> 75 #else 76 #include <dktools-4/dk4types.h> 77 #endif 78 #endif 79 80 #ifndef DK4ERROR_H_INCLUDED 81 #if DK4_BUILDING_DKTOOLS4 82 #include <libdk4base/dk4error.h> 83 #else 84 #include <dktools-4/dk4error.h> 85 #endif 86 #endif 87 88 #ifndef DK4PX_H_INCLUDED 89 #if DK4_BUILDING_DKTOOLS4 90 #include <libdk4bif/dk4px.h> 91 #else 92 #include <dktools-4/dk4px.h> 93 #endif 94 #endif 95 96 97 /** Color spaces used by the images we want to process. 98 */ 99 enum { 100 DK4_CS_GRAY = 0 , /**< Gray. */ 101 DK4_CS_GRAY_ALPHA , /**< Gray, opacity. */ 102 DK4_CS_RGB , /**< Red, green, blue. */ 103 DK4_CS_RGB_ALPHA , /**< Red, green, blue, opacity. */ 104 DK4_CS_CMYK , /**< Cyan, magentam, yellow, black (key). */ 105 106 DK4_CS_MIN = DK4_CS_GRAY , /**< Minimum value. */ 107 DK4_CS_MAX = DK4_CS_CMYK /**< Maximum value. */ 108 }; 109 110 111 /** Choose algorithm to convert RGB to CMYK. 112 */ 113 typedef enum { 114 115 DK4_CS_CONV_RGB_TO_CMYK_NOT_PS_PDF = 0 , 116 117 /**< Algorithm differing from PS/PDF standard. 118 Most web pages about color 119 conversion recommend the algorithm 120 like this (default): 121 @code 122 c' = 1 - r' 123 m' = 1 - g' 124 y' = 1 - b' 125 mincmy' = min{c',m',y'} 126 if 1 = mincmy' 127 then 128 k' = 1 129 c' = m' = y' = 0 130 else 131 k' = mincmy' 132 c' = (c' - k') / (1 - k') 133 m' = (m' - k') / (1 - k') 134 y' = (y' - k') / (1 - k') 135 endif 136 @endcode 137 Substitution results in: 138 @code 139 maxrgb' = max{r',g',b'} 140 if 0 = maxrgb' 141 then 142 k' = 1 143 c' = m' = y' = 0 144 else 145 c' = (maxrgb' - r') / maxrgb' 146 m' = (maxrgb' - g') / maxrgb' 147 y' = (maxrgb' - b') / maxrgb' 148 k' = 1 - maxrgb' 149 endif 150 @endcode 151 The result for pixel components is: 152 @code 153 maxrgb = max{r,g,b} 154 if 0 = maxrgb 155 then 156 k = M 157 c = m = y = 0 158 else 159 c = (M * (maxrgb - r)) / maxrgb 160 m = (M * (maxrgb - g)) / maxrgb 161 y = (M * (maxrgb - b)) / maxrgb 162 k = M - maxrgb 163 endif 164 @endcode 165 */ 166 167 168 169 DK4_CS_CONV_RGB_TO_CMYK_PS_PDF 170 171 /**< Algorithm as described in the PS and PDF standards. 172 @code 173 c' = 1 - r' 174 m' = 1 - g' 175 y' = 1 - b' 176 mincmy' = min{c',m',y'} 177 c' = c' - ucr(mincmy') 178 m' = m' - ucr(mincmy') 179 y' = y' - ucr(mincmy') 180 k' = bg(mincmy') 181 @endcode 182 Substitution and use of simplified 183 functions ucr(x)=x and bg(x)=x 184 results in: 185 @code 186 maxrgb' = max{r',g',b'} 187 c' = maxrgb' - r' 188 m' = maxrgb' - g' 189 y' = maxrgb' - b' 190 k' = 1 - maxrgb' 191 @endcode 192 The result for components values is: 193 @code 194 maxrgb = max{r,g,b} 195 c = maxrgb - r 196 m = maxrgb - g 197 y = maxrgb - b 198 k = M - maxrgb 199 @endcode 200 */ 201 202 } dk4_cs_conv_rgb_to_cmyk_t; 203 204 205 206 /** How to convert RGB to gray. 207 */ 208 typedef enum { 209 /** Reproduce luminance (default). 210 @code 211 e' = 0.299 * r' + 0.587 * g' + 0.114 * b' 212 e = (299 * r + 587 * g + 114 * b) / 1000 213 @endcode 214 */ 215 DK4_CS_CONV_RGB_TO_GRAY_ITU_BT601 = 0, 216 217 218 /** Reproduce luminance. 219 Same as above but reduced number of digits 220 in the coefficients. 221 @code 222 e' = 0.3 * r' + 0.59 * g' + 0.11 * b' 223 e = (30 * r + 59 * g + 11 * b) / 100 224 @endcode 225 */ 226 DK4_CS_CONV_RGB_TO_GRAY_LUMA , 227 228 /** Reproduce luminance, 229 use alternative coefficients. 230 @code 231 e' = 0.2126 * r' + 0.7152 * g' + 0.0722 * b' 232 e = (2126 * r + 7152 * g + 722 * b) / 10000 233 @endcode 234 */ 235 DK4_CS_CONV_RGB_TO_GRAY_ITU_BT709 , 236 237 238 /** Faster approximation for pixel values. 239 @code 240 e = (77 * r + 151 * g + 28 * b) >> 8 241 @endcode 242 For normalized colors use 243 @code 244 e' = 0.299 * r' + 0.587 * g' + 0.114 * b' 245 @endcode 246 */ 247 DK4_CS_CONV_RGB_TO_GRAY_FAST , 248 249 250 /** Still faster - and more inaccurate - 251 approximation for pixel values. 252 @code 253 e = ((r << 1) + ((g << 2) + g) + b) >> 3 254 @endcode 255 is a fast implementation of 256 @code 257 e = (2 * r + 5 * g + b) / 8 258 @endcode 259 For normalized colors use 260 @code 261 e' = 0.299 * r' + 0.587 * g' + 0.114 * b' 262 @endcode 263 */ 264 DK4_CS_CONV_RGB_TO_GRAY_VERY_FAST , 265 266 /** Use average. 267 @code 268 e' = (r' + g' + b') / 3 269 e = (r + g + b) / 3 270 @endcode 271 */ 272 DK4_CS_CONV_RGB_TO_GRAY_AVERAGE , 273 274 275 /** Desaturation. 276 Flatter than luminance, less contrast. 277 @code 278 e' = (max{r',g',b'} + min{r',g',b'}) / 2 279 e = (max{r,b,b} + min{r,g,b}) / 2 280 @endcode 281 */ 282 DK4_CS_CONV_RGB_TO_GRAY_DESATURATION , 283 284 285 /** Minimum decomposition. 286 Produces dark images. 287 @code 288 e' = min{r',g',b'} 289 e = min{r,g,b} 290 @endcode 291 */ 292 DK4_CS_CONV_RGB_TO_GRAY_MIN_DECOMPOSITION , 293 294 /** Medium value decomposition 295 (not minimum, not maximum). 296 */ 297 DK4_CS_CONV_RGB_TO_GRAY_MEDIUM_DECOMPOSITION , 298 299 300 /** Maximum decomposition. 301 Produces bright images. 302 @code 303 e' = max{r',g',b'} 304 e = max{r,g,b} 305 @endcode 306 */ 307 DK4_CS_CONV_RGB_TO_GRAY_MAX_DECOMPOSITION , 308 309 310 /** Use just red channel. 311 @code 312 e' = r' 313 e = r 314 @endcode 315 */ 316 DK4_CS_CONV_RGB_TO_GRAY_CHANNEL_RED , 317 318 319 /** Use just green channel. 320 @code 321 e' = g' 322 e = g 323 @endcode 324 */ 325 DK4_CS_CONV_RGB_TO_GRAY_CHANNEL_GREEN , 326 327 328 /** Use just blue channel. 329 @code 330 e' = b' 331 e = b 332 @endcode 333 */ 334 DK4_CS_CONV_RGB_TO_GRAY_CHANNEL_BLUE , 335 336 /** Minimum value. 337 */ 338 DK4_CS_CONV_RGB_TO_GRAY_MIN = DK4_CS_CONV_RGB_TO_GRAY_ITU_BT601 , 339 340 /** Maximum value. 341 */ 342 DK4_CS_CONV_RGB_TO_GRAY_MAX = DK4_CS_CONV_RGB_TO_GRAY_CHANNEL_BLUE 343 344 } dk4_cs_conv_rgb_to_gray_t; 345 346 347 348 /** How to handle alpha channel. 349 Only used when converting from a color space containing alpha data 350 to a color space not containing alpha data. 351 */ 352 typedef enum { 353 /** Mix against specified background. 354 */ 355 DK4_CS_CONV_ALPHA_MIX = 0, 356 357 /** Ignore alpha value, just return foreground. 358 */ 359 DK4_CS_CONV_ALPHA_FOREGROUND 360 361 } dk4_cs_conv_alpha_t; 362 363 364 365 /** Conversion context containing setup details for conversions. 366 */ 367 368 typedef struct { 369 dk4_cs_conv_rgb_to_cmyk_t rgb_to_cmyk; /**< RGB to CMYK. */ 370 dk4_cs_conv_rgb_to_gray_t rgb_to_gray; /**< RGB to gray. */ 371 dk4_cs_conv_alpha_t alpha; /**< Alpha channel handling. */ 372 } dk4_cs_conv_ctx_t; 373 374 375 376 #ifdef __cplusplus 377 extern "C" { 378 #endif 379 380 381 /** Create new conversion context and initialize it. 382 @param erp Error report, may be NULL. 383 @return Valid pointer on success, NULL on error. 384 385 Error codes: 386 - DK4_E_MEMORY_ALLOCATION_FAILED<br> 387 with mem.elsize and mem.nelem 388 set if there is not enough memory available. 389 */ 390 391 dk4_cs_conv_ctx_t * 392 dk4cs_context_open( 393 dk4_er_t *erp 394 ); 395 396 397 /** Initialize a conversion context. 398 @param pctx Context to set up. 399 @param erp Error report, may be NULL. 400 @return 1 on success, 0 on error. 401 402 Error codes: 403 - DK4_E_INVALID_ARGUMENTS<br> 404 if pctx is NULL. 405 */ 406 407 int 408 dk4cs_context_init( 409 dk4_cs_conv_ctx_t *pctx, 410 dk4_er_t *erp 411 ); 412 413 414 /** Set RGB to CMYK handling in a conversion context. 415 @param pctx Context to set up. 416 @param rgb_to_cmyk Details for RGB to CMYK conversion. 417 @param erp Error report, may be NULL. 418 @return 1 on success, 0 on error. 419 420 Error codes: 421 - DK4_E_INVALID_ARGUMENTS<br> 422 if pctx is NULL. 423 */ 424 425 int 426 dk4cs_context_set_rgb_to_cmyk( 427 dk4_cs_conv_ctx_t *pctx, 428 dk4_cs_conv_rgb_to_cmyk_t rgb_to_cmyk, 429 dk4_er_t *erp 430 ); 431 432 433 /** Set RGB to gray handling in a conversion context. 434 @param pctx Context to set up. 435 @param rgb_to_gray Details or RGB to gray conversion. 436 @param erp Error report, may be NULL. 437 @return 1 on success, 0 on error. 438 439 Error codes: 440 - DK4_E_INVALID_ARGUMENTS<br> 441 if pctx is NULL. 442 */ 443 444 int 445 dk4cs_context_set_rgb_to_gray( 446 dk4_cs_conv_ctx_t *pctx, 447 dk4_cs_conv_rgb_to_gray_t rgb_to_gray, 448 dk4_er_t *erp 449 ); 450 451 452 /** Set alpha channel handling. 453 @param pctx Context to set up. 454 @param alpha Alpha channel handling method. 455 @param erp Error report, may be NULL. 456 @return 1 on success, 0 on error. 457 458 Error codes: 459 - DK4_E_INVALID_ARGUMENTS<br> 460 if pctx is NULL. 461 */ 462 463 int 464 dk4cs_context_set_alpha( 465 dk4_cs_conv_ctx_t *pctx, 466 dk4_cs_conv_alpha_t alpha, 467 dk4_er_t *erp 468 ); 469 470 /** Destroy conversion context, release resources. 471 @param pctx Conversion context to close. 472 */ 473 474 void 475 dk4cs_context_close( 476 dk4_cs_conv_ctx_t *pctx 477 ); 478 479 480 /** Convert pixel data from one color space into another, samples are dk4_px_t. 481 @param dptr Address of destination array. 482 @param dcs Destination color space. 483 @param dsz Size of destination array (number of elements). 484 @param sptr Address of source array. 485 @param scs Source color space. 486 @param ssz Source array size (number of elements). 487 @param bptr Address of background array, may be NULL. 488 @param bsz Size of background array (number of elements), may be 0. 489 @param max Maximum value for a component. 490 @param pctx Conversion context, may be NULL. 491 @param erp Error report, may be NULL. 492 493 Error codes: 494 - DK4_E_INVALID_ARGUMENTS<br> 495 if anything is wrong with arguments, i.e.: 496 * dptr or sptr is NULL, 497 * dcs or scs is not a valid color space, 498 * dsz or ssz is too small for the color space, 499 * max is 0, 500 * one of the sptr components is larger than max 501 * a background is required but bptr is NULL, bsz is too small 502 for the colro space or one of the background components is larger 503 than max. 504 */ 505 506 void 507 dk4cs_px_convert( 508 dk4_px_t *dptr, 509 int dcs, 510 size_t dsz, 511 dk4_px_t const *sptr, 512 int scs, 513 size_t ssz, 514 dk4_px_t const *bptr, 515 size_t bsz, 516 dk4_px_t max, 517 dk4_cs_conv_ctx_t const *pctx, 518 dk4_er_t *erp 519 ); 520 521 522 /** Convert pixel data from one color space into another, samples are double. 523 @param dptr Address of destination array, values in interval [0;1]. 524 @param dcs Destination color space. 525 @param dsz Size of destination array (number of elements). 526 @param sptr Address of source array, values in interval [0;1]. 527 @param scs Source color space. 528 @param ssz Source array size (number of elements). 529 @param bptr Address of background array, values in [0;1], may be NULL. 530 @param bsz Size of background array (number of elements), may be 0. 531 @param pctx Conversion context, may be NULL. 532 @param erp Error report, may be NULL. 533 534 Error codes: 535 - DK4_E_INVALID_ARGUMENTS<br> 536 if anything is wrong with arguments, i.e.: 537 * dptr or sptr is NULL, 538 * dcs or scs is not a valid color space, 539 * dsz or ssz is too small for the color space, 540 * one of the sptr components is out of interval [0;1], 541 * a background is required but bptr is NULL, bsz is too small 542 for the colro space or one of the background components is 543 out of interval [0;1]. 544 */ 545 546 void 547 dk4cs_color_convert( 548 double *dptr, 549 int dcs, 550 size_t dsz, 551 double const *sptr, 552 int scs, 553 size_t ssz, 554 double const *bptr, 555 size_t bsz, 556 dk4_cs_conv_ctx_t const *pctx, 557 dk4_er_t *erp 558 ); 559 560 561 /** Mix pixel data foreground against background value. 562 @param value Foreground value. 563 @param alpha Foreground opacity. 564 @param bg Background value. 565 @param max Maximum for foreground, background, and alpha. 566 @return Mixing result. 567 */ 568 569 dk4_px_t 570 dk4cs_mix_alpha( 571 dk4_px_t value, 572 dk4_px_t alpha, 573 dk4_px_t bg, 574 dk4_px_t max 575 ); 576 577 578 /** Mix pixel data RGB to gray. 579 @param r Red. 580 @param g Green. 581 @param b Blue. 582 @param pctx Conversion context, may be NULL. 583 @return Gray value for RGB pixel. 584 */ 585 586 dk4_px_t 587 dk4cs_mix_rgb_to_gray( 588 unsigned long r, 589 unsigned long g, 590 unsigned long b, 591 dk4_cs_conv_ctx_t const *pctx 592 ); 593 594 595 /** Mix normalized color foreground against background using alpha value. 596 @param v Foreground value, normalized. 597 @param a Alpha value, normalized. 598 @param b Background value, normalized. 599 */ 600 601 double 602 dk4cs_color_mix_alpha( 603 double v, 604 double a, 605 double b 606 ); 607 608 609 /** Mix normalized color RGB to gray 610 @param r Normalized red component. 611 @param g Normalized green component. 612 @param b Normalized blue component. 613 @param pctx Conversion context, may be NULL. 614 @return Gray value. 615 */ 616 617 double 618 dk4cs_color_mix_rgb_to_gray( 619 double r, 620 double g, 621 double b, 622 dk4_cs_conv_ctx_t const *pctx 623 ); 624 625 626 /** Retrieve number of components for a color space. 627 @param cs Color space. 628 @return Number of components in color space cs. 629 */ 630 631 size_t 632 dk4cs_color_space_size(int cs); 633 634 635 /** Check whether an integer number represents a valid color space. 636 @param cs Number to check. 637 @return 1 on success (cs is a color space), 0 otherwise. 638 */ 639 640 int 641 dk4cs_check(int cs); 642 643 644 /** Set RGB to CMYK conversion method from text. 645 @param pctx Context to set up. 646 @param txt Text containing the method name. 647 @param erp Error report, may be NULL. 648 649 Error codes: 650 - DK4_E_INVALID_ARGUMENTS<br> 651 if pctx or txt is NULL, 652 - DK4_E_SYNTAX<br> 653 if txt does not cotain a valid method name. 654 */ 655 656 int 657 dk4cs_context_text_rgb_to_cmyk( 658 dk4_cs_conv_ctx_t *pctx, 659 dkChar const *txt, 660 dk4_er_t *erp 661 ); 662 663 664 /** Set RGB to GRAY conversion method from text. 665 @param pctx Context to set up. 666 @param txt Text containing the method name. 667 @param erp Error report, may be NULL. 668 669 Error codes: 670 - DK4_E_INVALID_ARGUMENTS<br> 671 if pctx or txt is NULL, 672 - DK4_E_SYNTAX<br> 673 if txt does not cotain a valid method name. 674 */ 675 676 int 677 dk4cs_context_text_rgb_to_gray( 678 dk4_cs_conv_ctx_t *pctx, 679 dkChar const *txt, 680 dk4_er_t *erp 681 ); 682 683 684 /** Set alpha channel handling method. 685 @param pctx Context to set up. 686 @param txt Text containing the method name. 687 @param erp Error report, may be NULL. 688 689 Error codes: 690 - DK4_E_INVALID_ARGUMENTS<br> 691 if pctx or txt is NULL, 692 - DK4_E_SYNTAX<br> 693 if txt does not cotain a valid method name. 694 */ 695 696 int 697 dk4cs_context_text_alpha( 698 dk4_cs_conv_ctx_t *pctx, 699 dkChar const *txt, 700 dk4_er_t *erp 701 ); 702 703 704 #ifdef __cplusplus 705 } 706 #endif 707 708 709 /* vim: set ai sw=4 ts=4 : */ 710 711 #endif 712