about summary refs log tree commit diff
path: root/lib/ppm.h
blob: 9fa547fe978e3acf75f5c35cf078ba3ccd5d6e72 (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
135
136
137
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
/* Interface header file for PPM-related functions in libnetpbm */

#ifndef _PPM_H_
#define _PPM_H_

#include <netpbm/pm_config.h>
#include <netpbm/pm.h>
#include <netpbm/pgm.h>

#ifdef __cplusplus
extern "C" {
#endif
#if 0
} /* to fake out automatic code indenters */
#endif

typedef gray pixval;

/* These are just for use in this header file */
#define PPM_MAX(a,b) ((a) > (b) ? (a) : (b))
#define PPM_MIN(a,b) ((a) < (b) ? (a) : (b))


#define PPM_OVERALLMAXVAL PGM_OVERALLMAXVAL
#define PPM_MAXMAXVAL PGM_MAXMAXVAL

#define ppm_unnormalize pgm_unnormalize

typedef struct {
    pixval r, g, b;
} pixel;
#define PPM_GETR(p) ((p).r)
#define PPM_GETG(p) ((p).g)
#define PPM_GETB(p) ((p).b)

/************* added definitions *****************/
#define PPM_PUTR(p,red) ((p).r = (red))
#define PPM_PUTG(p,grn) ((p).g = (grn))
#define PPM_PUTB(p,blu) ((p).b = (blu))
/**************************************************/

#define PPM_ASSIGN(p,red,grn,blu) \
  do { (p).r = (red); (p).g = (grn); (p).b = (blu); } while (0)
#define PPM_EQUAL(p,q) \
  ( (p).r == (q).r && (p).g == (q).g && (p).b == (q).b )


/* Magic constants. */

#define PPM_MAGIC1 'P'
#define PPM_MAGIC2 '3'
#define RPPM_MAGIC2 '6'
#define PPM_FORMAT (PPM_MAGIC1 * 256 + PPM_MAGIC2)
#define RPPM_FORMAT (PPM_MAGIC1 * 256 + RPPM_MAGIC2)
#define PPM_TYPE PPM_FORMAT


#include <netpbm/ppmcmap.h>

/* Macro for turning a format number into a type number. */

#define PPM_FORMAT_TYPE(f) \
  ((f) == PPM_FORMAT || (f) == RPPM_FORMAT ? PPM_TYPE : PGM_FORMAT_TYPE(f))


static __inline__ pixel
ppm_whitepixel(pixval maxval) {

    pixel retval;
    PPM_ASSIGN(retval, maxval, maxval, maxval);

    return retval;
}

static __inline__ pixel
ppm_blackpixel(void) {

    pixel const retval = {0, 0, 0};

    return retval;
}

void ppm_init(int * const argcP, char ** const argv);

#define ppm_allocarray(cols, rows) \
  ((pixel**) pm_allocarray(cols, rows, sizeof(pixel)))

pixel *
ppm_allocrow(unsigned int const cols);

#define ppm_freearray(pixels, rows) pm_freearray((char**) pixels, rows)

#define ppm_freerow(pixelrow) pm_freerow(pixelrow);

pixel**
ppm_readppm(FILE *   const fileP,
            int *    const colsP,
            int *    const rowsP,
            pixval * const maxvalP);

void
ppm_readppminit(FILE *   const fileP,
                int *    const colsP,
                int *    const rowsP,
                pixval * const maxvalP,
                int *    const formatP);

void
ppm_readppmrow(FILE*  const fileP,
               pixel* const pixelrow,
               int    const cols,
               pixval const maxval,
               int    const format);

void
ppm_writeppm(FILE *  const fileP,
             pixel** const pixels,
             int     const cols,
             int     const rows,
             pixval  const maxval,
             int     const forceplain);

void
ppm_writeppminit(FILE*  const fileP,
                 int    const cols,
                 int    const rows,
                 pixval const maxval,
                 int    const forceplain);

void
ppm_writeppmrow(FILE *        const fileP,
                const pixel * const pixelrow,
                int           const cols,
                pixval        const maxval,
                int           const forceplain);

void
ppm_check(FILE *               const fileP,
          enum pm_check_type   const check_type,
          int                  const format,
          int                  const cols,
          int                  const rows,
          pixval               const maxval,
          enum pm_check_code * const retval_p);

void
ppm_nextimage(FILE * const fileP,
              int *  const eofP);

pixel
ppm_parsecolor(const char * const colorname,
               pixval       const maxval);

pixel
ppm_parsecolor2(const char * const colorname,
                pixval       const maxval,
                int          const closeOk);

char*
ppm_colorname(const pixel* const colorP,
              pixval       const maxval,
              int          const hexok);

typedef struct {
    unsigned int version;
    const char ** name;
        /* malloced, and each entry malloced.  Has space for at least 'size'
           entries.  May be null if size == 0
        */
    pixel * color;       /* malloced */
        /* malloced.  Has space for at least 'size' entries.  May be null if
           size == 0
        */
    unsigned int size;
        /* allocated size of 'name' and 'color'.  At least 'count' */
    unsigned int count;
        /* number of entries used.*/
    colorhash_table cht;
        /* Hash table mapping name[] to color[] */
} ppm_ColorDict;

ppm_ColorDict *
ppm_colorDict_new(const char * const fileName,
                  int          const mustOpen);

void
ppm_colorDict_destroy(ppm_ColorDict * colorDictP);

void
ppm_readcolordict2(const char *     const fileName,
                   int              const mustOpen,
                   ppm_ColorDict ** const colorDictP);

void
ppm_readcolordict(const char *      const fileName,
                  int               const mustOpen,
                  unsigned int *    const nColorsP,
                  const char ***    const colornamesP,
                  pixel **          const colorsP,
                  colorhash_table * const chtP);

void
ppm_readcolornamefile(const char *      const fileName,
                      int               const mustOpen,
                      colorhash_table * const chtP,
                      const char ***    const colornamesP);

void
ppm_freecolornames(const char ** const colornames);

#define PPM_ISGRAY(pixel) \
    (PPM_GETR(pixel) == PPM_GETG(pixel) && PPM_GETR(pixel) == PPM_GETB(pixel))

/* Color scaling macro -- to make writing ppmtowhatever easier. */

#define PPM_DEPTH(newp,p,oldmaxval,newmaxval) \
    PPM_ASSIGN( (newp), \
        ( (int) PPM_GETR(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \
        ( (int) PPM_GETG(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \
        ( (int) PPM_GETB(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval) )

#define PPM_SQR(x) (x)*(x)

static __inline__ unsigned int
PPM_DISTANCE(pixel const p1,
             pixel const p2) {
    return (
        PPM_SQR(PPM_GETR(p1)-PPM_GETR(p2)) +
        PPM_SQR(PPM_GETG(p1)-PPM_GETG(p2)) +
        PPM_SQR(PPM_GETB(p1)-PPM_GETB(p2)) );
}
#undef PPM_SQR

/* Note that because a sample can be at most 1 << 16 - 1, PPM_DISTANCE
   is less than UINT_MAX.  That means you can use UINT_MAX as an infinite
   distance in some applications.
*/

/* Luminance, Chrominance macros. */

/* The following are weights of the red, green, and blue components
   respectively in the luminance of a color.  Actually, it's "luma,"
   not luminance, the difference being that luminance would be a linear
   combination of intensities, whereas luma is a linear combination of
   gamma-adjusted intensities, as you would find in a Netpbm image.

   These are from ITU-R BT.601.5.
*/
#define PPM_LUMINR (0.2989)
#define PPM_LUMING (0.5866)
#define PPM_LUMINB (0.1145)

#define PPM_LUMIN(p) ( PPM_LUMINR * PPM_GETR(p) \
                       + PPM_LUMING * PPM_GETG(p) \
                       + PPM_LUMINB * PPM_GETB(p) )

/* The coefficients in the following formulae are functions of
   PPM_LUMIN{R,G,B} and nothing else.
*/
#define PPM_CHROM_B(p) ( -0.168736 * PPM_GETR(p) \
                         - 0.331264 * PPM_GETG(p) \
                         + 0.5 * PPM_GETB(p) )
#define PPM_CHROM_R(p) ( 0.5 * PPM_GETR(p) \
                         - 0.418688 * PPM_GETG(p) \
                         - 0.081312 * PPM_GETB(p) )

pixel
ppm_color_from_ycbcr(unsigned int const y,
                     int          const cb,
                     int          const cr);

/* Hue/Saturation/Value calculations */

struct hsv {
    double h;  /* hue (degrees)  0..360 */
    double s;  /* saturation (0-1) */
    double v;  /* value (0-1) */
};

pixel
ppm_color_from_hsv(struct hsv const hsv,
                   pixval     const maxval);

struct hsv
ppm_hsv_from_color(pixel  const color,
                   pixval const maxval);

static __inline__ pixval
ppm_luminosity(pixel const p) {

    return (pixval)(PPM_LUMIN(p) + 0.5);
}

static __inline__ pixval
ppm_colorvalue(pixel const p) {
/*----------------------------------------------------------------------------
  The color value (V is HSV) as a pixval
-----------------------------------------------------------------------------*/
    return PPM_MAX(PPM_GETR(p), PPM_MAX(PPM_GETG(p), PPM_GETB(p)));
}

static __inline__ pixval
ppm_saturation(pixel const p,
               pixval const maxval) {
/*----------------------------------------------------------------------------
  The saturation, as a pixval (i.e. if saturation is 50% and maxval
  is 100, this is 50).
-----------------------------------------------------------------------------*/
    pixval const maxIntensity =
        PPM_MAX(PPM_GETR(p), PPM_MAX(PPM_GETG(p), PPM_GETB(p)));
    pixval const minIntensity =
        PPM_MIN(PPM_GETR(p), PPM_MIN(PPM_GETG(p), PPM_GETB(p)));
    pixval const range = maxIntensity - minIntensity;

    return (pixval)((unsigned long)range * maxval / maxIntensity);
}

typedef enum {
    /* A color from the set of universally understood colors developed
       by Brent Berlin and Paul Kay.

       Algorithms in libnetpbm depend on the numerical representations
       of these values being as follows.
    */
    BKCOLOR_GRAY = 0,
    BKCOLOR_BROWN,
    BKCOLOR_ORANGE,
    BKCOLOR_RED,
    BKCOLOR_YELLOW,
    BKCOLOR_GREEN,
    BKCOLOR_BLUE,
    BKCOLOR_VIOLET,
    BKCOLOR_PURPLE,
    BKCOLOR_WHITE,
    BKCOLOR_BLACK
} bk_color;

#define BKCOLOR_COUNT (BKCOLOR_BLACK+1)

bk_color
ppm_bk_color_from_color(pixel  const color,
                        pixval const maxval);

pixel
ppm_color_from_bk_color(bk_color const bkColor,
                        pixval   const maxval);

bk_color
ppm_bk_color_from_name(const char * const name);

const char *
ppm_name_from_bk_color(bk_color const bkColor);

#ifdef __cplusplus
}
#endif

#undef PPM_MIN
#undef PPM_MAX

#endif /*_PPM_H_*/