about summary refs log tree commit diff
path: root/lib/libpamcolor.c
blob: ef8546b30892af334de77106f5ba1856c682561d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*----------------------------------------------------------------------------
                                  libpamcolor.c
------------------------------------------------------------------------------
   These are the library functions, which belong in the libnetpbm library,
   that deal with colors in the PAM image format.
-----------------------------------------------------------------------------*/

/* See libpbm.c for the complicated explanation of this 32/64 bit file
   offset stuff.
*/
#define _FILE_OFFSET_BITS 64
#define _LARGE_FILES  

#define _BSD_SOURCE 1      /* Make sure strdup() is in string.h */
#define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */

#include <string.h>
#include <limits.h>

#include "pm_c_util.h"
#include "pam.h"
#include "ppm.h"


tuple
pnm_parsecolor(const char * const colorname,
               sample       const maxval) {

    tuple retval;
    pixel color;
    struct pam pam;

    pam.len = PAM_STRUCT_SIZE(bytes_per_sample);
    pam.depth = 3;
    pam.maxval = maxval;
    pam.bytes_per_sample = pnm_bytespersample(maxval);

    retval = pnm_allocpamtuple(&pam);

    color = ppm_parsecolor(colorname, maxval);

    retval[PAM_RED_PLANE] = PPM_GETR(color);
    retval[PAM_GRN_PLANE] = PPM_GETG(color);
    retval[PAM_BLU_PLANE] = PPM_GETB(color);

    return retval;
}



const char *
pnm_colorname(struct pam * const pamP,
              tuple        const color,
              int          const hexok) {

    const char * retval;
    pixel colorp;
    char * colorname;

    if (pamP->depth < 3)
        PPM_ASSIGN(colorp, color[0], color[0], color[0]);
    else 
        PPM_ASSIGN(colorp,
                   color[PAM_RED_PLANE],
                   color[PAM_GRN_PLANE],
                   color[PAM_BLU_PLANE]);

    colorname = ppm_colorname(&colorp, pamP->maxval, hexok);

    retval = strdup(colorname);
    if (retval == NULL)
        pm_error("Couldn't get memory for color name string");

    return retval;
}



double pnm_lumin_factor[3] = {PPM_LUMINR, PPM_LUMING, PPM_LUMINB};

void
pnm_YCbCrtuple(tuple    const tuple, 
               double * const YP, 
               double * const CbP, 
               double * const CrP) {
/*----------------------------------------------------------------------------
   Assuming that the tuple 'tuple' is of tupletype RGB, return the 
   Y/Cb/Cr representation of the color represented by the tuple.
-----------------------------------------------------------------------------*/
    int const red = (int)tuple[PAM_RED_PLANE];
    int const grn = (int)tuple[PAM_GRN_PLANE];
    int const blu = (int)tuple[PAM_BLU_PLANE];
    
    *YP  = (+ PPM_LUMINR * red + PPM_LUMING * grn + PPM_LUMINB * blu);
    *CbP = (- 0.16874 * red - 0.33126 * grn + 0.50000 * blu);
    *CrP = (+ 0.50000 * red - 0.41869 * grn - 0.08131 * blu);
}



void 
pnm_YCbCr_to_rgbtuple(const struct pam * const pamP,
                      tuple              const tuple,
                      double             const Y,
                      double             const Cb, 
                      double             const Cr,
                      int *              const overflowP) {

    double rgb[3];
    unsigned int plane;
    bool overflow;

    rgb[PAM_RED_PLANE] = Y + 1.4022 * Cr + .5;
    rgb[PAM_GRN_PLANE] = Y - 0.7145 * Cr - 0.3456 * Cb + .5;
    rgb[PAM_BLU_PLANE] = Y + 1.7710 * Cb + .5;

    overflow = FALSE;  /* initial assumption */

    for (plane = 0; plane < 3; ++plane) {
        if (rgb[plane] > pamP->maxval) {
            overflow = TRUE;
            tuple[plane] = pamP->maxval;
        } else if (rgb[plane] < 0.0) {
            overflow = TRUE;
            tuple[plane] = 0;
        } else 
            tuple[plane] = (sample)rgb[plane];
    }
    if (overflowP)
        *overflowP = overflow;
}