1 /*=============================================================================
2    These are declarations for use with the Portable Arbitrary Map (PAM)
3    format and the Netpbm library functions specific to them.
4 
5    This file was originally written by Bryan Henderson and is contributed
6    to the public domain by him and subsequent authors.
7 =============================================================================*/
8 #ifndef PAM_H
9 #define PAM_H
10 
11 #include <netpbm/pm_config.h>
12 #include <netpbm/pm.h>
13 #include <netpbm/pnm.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 #if 0
19 } /* to fake out automatic code indenters */
20 #endif
21 
22 typedef unsigned long sample;
23     /* Regardless of the capacity of "unsigned long", a sample is always
24        less than 1 << 16.  This is essential for some code to avoid
25        arithmetic overflows.
26     */
27 
28 struct pam {
29     /* This structure describes an open PAM image file.  It consists
30        entirely of information that belongs in the header of a PAM image
31        and filesystem information.  It does not contain any state
32        information about the processing of that image.
33 
34        This is not considered to be an opaque object.  The user of Netbpm
35        libraries is free to access and set any of these fields whenever
36        appropriate.  The structure exists to make coding of function calls
37        easy.
38     */
39 
40     /* 'size' and 'len' are necessary in order to provide forward and
41        backward compatibility between library functions and calling programs
42        as this structure grows.
43        */
44     unsigned int size;
45         /* The storage size of this entire structure, in bytes */
46     unsigned int len;
47         /* The length, in bytes, of the information in this structure.
48            The information starts in the first byte and is contiguous.
49            This cannot be greater than 'size'
50 
51            Use PAM_STRUCT_SIZE() to compute or interpret a value for this.
52         */
53     FILE * file;
54     int format;
55         /* The format code of the image.  This is PAM_FORMAT
56            unless the PAM image is really a view of a PBM, PGM, or PPM
57            image.  Then it's PBM_FORMAT, RPBM_FORMAT, etc.  For output,
58            only the format _type_ is significant, e.g. PBM_FORMAT
59            and RPBM_FORMAT have identical effect.  This is because on
60            output, 'plainformat' determines whether the output is the
61            raw or plain format of the type given by 'format'.
62            */
63     unsigned int plainformat;
64         /* Logical: On output, use plain version of the format type
65            indicated by 'format'.  Otherwise, use the raw version.
66            (i.e., on output, the plainness information in 'format' is
67            irrelevant).  Input functions set this to FALSE, for the
68            convenience of programs that copy an input pam structure for
69            use with output.
70 
71            Before Netpbm 10.32, this was rather different.  It simply
72            described for convenience the plainness of the format indicated
73            by 'format'.
74 
75            This is meaningless when 'format' is PAM_FORMAT, as PAM does not
76            have plain and raw variations.
77         */
78     int height;  /* Height of image in rows */
79     int width;
80         /* Width of image in number of columns (tuples per row) */
81     unsigned int depth;
82         /* Depth of image (number of samples in each tuple). */
83     sample maxval;  /* Maximum defined value for a sample */
84     unsigned int bytes_per_sample;
85         /* Number of bytes used to represent each sample in the image file.
86            Note that this is strictly a function of 'maxval'.  It is in a
87            a separate member for computational speed.
88         */
89     char tuple_type[256];
90         /* The tuple type string from the image header.  If the PAM image
91            is really a view of a PBM, PGM, or PPM image, the value is
92            PAM_PBM_TUPLETYPE, PAM_PGM_TUPLETYPE, or PAM_PPM_TUPLETYPE,
93            respectively.
94         */
95     unsigned int allocation_depth;
96         /* The number of samples for which memory is allocated for any
97            'tuple' type associated with this PAM structure.  This must
98            be at least as great as 'depth'.  Only the first 'depth' of
99            the samples of a tuple are meaningful.
100 
101            The purpose of this is to make it possible for a program to
102            change the type of a tuple to one with more or fewer
103            planes.
104 
105            0 means the allocation depth is the same as the image depth.
106         */
107     const char ** comment_p;
108         /* Pointer to a pointer to a NUL-terminated ASCII string of
109            comments.  When reading an image, this contains the
110            comments from the image's PAM header; when writing, the
111            image gets these as comments, right after the magic number
112            line.  The individual comments are delimited by newlines
113            and are in the same order as in the PAM header.
114 
115            On output, NULL means no comments.
116 
117            On input, libnetpbm mallocs storage for the comments and places
118            the pointer at *comment_p.  Caller must free it.  NULL means
119            libnetpbm does not return comments and does not allocate any
120            storage.
121         */
122     int visual;  /* boolean */
123         /* tuple_type is one of the PAM-defined tuple types for visual
124            images ("GRAYSCALE", "RGB_ALPHA", etc.).
125         */
126     unsigned int color_depth;
127         /* Number of color planes (i.e. 'depth', but without transparency).
128            The color planes are the lowest numbered ones.  Meaningless if
129            'visual' is false.
130         */
131     int have_opacity;   /* boolean */
132         /* The tuples have an opacity (transparency, alpha) plane.
133            Meaningless if 'visual' is false.
134         */
135     unsigned int opacity_plane;
136         /* The plane number of the opacity plane;  meaningless if
137            'haveOpacity' is false or 'visual' is false.
138         */
139 };
140 
141 #define PAM_HAVE_ALLOCATION_DEPTH 1
142 #define PAM_HAVE_COMMENT_P 1
143 
144 /* PAM_STRUCT_SIZE(x) tells you how big a struct pam is up through the
145    member named x.  This is useful in conjunction with the 'len' value
146    to determine which fields are present in the structure.
147 */
148 
149 /* Some compilers are really vigilant and recognize it as an error
150    to cast a 64 bit address to a 32 bit type.  Hence the roundabout
151    casting in PAM_MEMBER_OFFSET.
152 */
153 #define PAM_MEMBER_OFFSET(mbrname) \
154   ((size_t)(unsigned long)(char*)&((struct pam *)0)->mbrname)
155 #define PAM_MEMBER_SIZE(mbrname) \
156   sizeof(((struct pam *)0)->mbrname)
157 #define PAM_STRUCT_SIZE(mbrname) \
158   (PAM_MEMBER_OFFSET(mbrname) + PAM_MEMBER_SIZE(mbrname))
159 
160 #define PAM_BLACK 0
161 #define PAM_BW_WHITE 1
162 
163 #define PAM_PBM_TUPLETYPE "BLACKANDWHITE"
164 #define PAM_PGM_TUPLETYPE "GRAYSCALE"
165 #define PAM_PPM_TUPLETYPE "RGB"
166 #define PAM_PBM_ALPHA_TUPLETYPE "BLACKANDWHITE_ALPHA"
167 #define PAM_PGM_ALPHA_TUPLETYPE "GRAYSCALE_ALPHA"
168 #define PAM_PPM_ALPHA_TUPLETYPE "RGB_ALPHA"
169 
170 #define PAM_PBM_BLACK PAM_BLACK
171 #define PAM_PBM_WHITE PAM_BW_WHITE
172     /* These are values of samples in a PAM image that represents a black
173        and white bitmap image.  They are the values of black and white,
174        respectively.  For example, if you use pnm_readpamrow() to read a
175        row from a PBM file, the black pixels get returned as
176        PAM_PBM_BLACK.
177     */
178 
179 #define PAM_RED_PLANE 0
180 #define PAM_GRN_PLANE 1
181 #define PAM_BLU_PLANE 2
182     /* These are plane numbers for the 3 planes of a PAM image that
183        represents an RGB image (tuple type is "RGB").  So
184        if 'pixel' is a tuple returned by pnmreadpamrow(), then
185        pixel[PAM_GRN_PLANE] is the value of the green sample in that
186        pixel.
187        */
188 #define PAM_TRN_PLANE 3
189     /* A PAM with "RGB_ALPHA" tuple type has this 4th plane
190        for transparency.  0 = transparent, maxval = opaque.
191     */
192 #define PAM_GRAY_TRN_PLANE 1
193     /* For a "GRAYSCALE" tuple type, this is the transparency plane */
194 
195 typedef sample *tuple;
196     /* A tuple in a PAM.  This is an array such that tuple[i-1] is the
197        ith sample (element) in the tuple.  It's dimension is the depth
198        of the image (see pam.depth above).
199     */
200 
201 #define PAM_OVERALL_MAXVAL 65535
202 
203 /* Note: xv uses the same "P7" signature for its thumbnail images (it
204    started using it years before PAM and unbeknownst to the designer
205    of PAM).  But these images are still easily distinguishable from
206    PAMs
207 */
208 #define PAM_MAGIC1 'P'
209 #define PAM_MAGIC2 '7'
210 #define PAM_FORMAT (PAM_MAGIC1 * 256 + PAM_MAGIC2)
211 #define PAM_TYPE PAM_FORMAT
212 
213 /* Macro for turning a format number into a type number. */
214 
215 #define PAM_FORMAT_TYPE(f) ((f) == PAM_FORMAT ? PAM_TYPE : PPM_FORMAT_TYPE(f))
216 
217 struct pamtuples {
218     struct pam * pamP;
219     tuple ***    tuplesP;
220 };
221 
222 
223 typedef float * pnm_transformMap;
224     /* This is an array of transform maps.  transform[N] is the
225        array that is the map for Plane N.
226 
227        Transform maps define a transformation between PAM sample value
228        to normalized libnetpbm "samplen" value, i.e. what you get back
229        from pnm_readpamrown() or pass to pnm_writepamrown().
230        Typically, it's a gamma transfer function generated by
231        pnm_creategammatransform() or pnm_createungammatransform().
232 
233        NULL for any transform means just plain normalization -- divide
234        the PAM sample value by the maxval to get the samplen, multiply
235        samplen by the maxval and round to get PAM sample value.
236 
237        NULL for map table, or 'transform' member not present (pam
238        structure is too small to contain it) means ALL transforms
239        are plain normalization.
240 
241        Each transform map is an array indexed by a PAM sample
242        value, containing 'float' values.  So it must have 'maxval'
243        entries.  The sample -> samplen transformation is just the
244        obvious table lookup.  The samplen -> sample transformation is
245        more complicated -- if the samplen value is between map[N]
246        and map[N+1], then the sample value is N.  And only transforms
247        where map[N+1] > map[N] are allowed.
248     */
249 
250 /* Declarations of library functions. */
251 
252 /* We don't have a specific PAM function for init and nextimage, because
253    one can simply use pnm_init() and pnm_nextimage() from pnm.h.
254 */
255 
256 unsigned int
257 pnm_bytespersample(sample const maxval);
258 
259 int
260 pnm_tupleequal(const struct pam * const pamP,
261                tuple              const comparand,
262                tuple              const comparator);
263 
264 void
265 pnm_assigntuple(const struct pam * const pamP,
266                 tuple              const dest,
267                 tuple              const source);
268 
269 static __inline__ sample
pnm_scalesample(sample const source,sample const oldmaxval,sample const newmaxval)270 pnm_scalesample(sample const source,
271                 sample const oldmaxval,
272                 sample const newmaxval) {
273 
274     if (oldmaxval == newmaxval)
275         /* Fast path for common case */
276         return source;
277     else
278         return (source * newmaxval + (oldmaxval/2)) / oldmaxval;
279 }
280 
281 
282 
283 void
284 pnm_scaletuple(const struct pam * const pamP,
285                tuple              const dest,
286                tuple              const source,
287                sample             const newmaxval);
288 
289 void
290 pnm_scaletuplerow(const struct pam * const pamP,
291                   tuple *            const destRow,
292                   tuple *            const sourceRow,
293                   sample             const newMaxval);
294 
295 void
296 pnm_maketuplergb(const struct pam * const pamP,
297                  tuple              const tuple);
298 
299 void
300 pnm_makerowrgb(const struct pam * const pamP,
301                tuple *            const tuplerow);
302 
303 void
304 pnm_makearrayrgb(const struct pam * const pamP,
305                  tuple **           const tuples);
306 
307 void
308 pnm_makerowrgba(const struct pam * const pamP,
309                 tuple *            const tuplerow);
310 
311 void
312 pnm_addopacityrow(const struct pam * const pamP,
313                   tuple *            const tuplerow);
314 
315 void
316 pnm_getopacity(const struct pam * const pamP,
317                int *              const haveOpacityP,
318                unsigned int *     const opacityPlaneP);
319 
320 void
321 pnm_createBlackTuple(const struct pam * const pamP, tuple * const blackTupleP);
322 
323 tuple
324 pnm_allocpamtuple(const struct pam * const pamP);
325 
326 #define pnm_freepamtuple(tuple) pm_freerow((char*) tuple)
327 
328 tuple *
329 pnm_allocpamrow(const struct pam * const pamP);
330 
331 #define pnm_freepamrow(tuplerow) pm_freerow((char*) tuplerow)
332 
333 tuple **
334 pnm_allocpamarray(const struct pam * const pamP);
335 
336 void
337 pnm_freepamarray(tuple ** const tuplearray, const struct pam * const pamP);
338 
339 void
340 pnm_setminallocationdepth(struct pam * const pamP,
341                           unsigned int const allocationDepth);
342 
343 void
344 pnm_setpamrow(const struct pam * const pam,
345               tuple *            const tuplerow,
346               sample             const value);
347 
348 unsigned char *
349 pnm_allocrowimage(const struct pam * const pamP);
350 
351 void
352 pnm_freerowimage(unsigned char * const rowimage);
353 
354 void
355 pnm_readpaminit(FILE *       const file,
356                 struct pam * const pamP,
357                 int          const size);
358 
359 void
360 pnm_readpamrow(const struct pam * const pamP, tuple* const tuplerow);
361 
362 tuple **
363 pnm_readpam(FILE *       const file,
364             struct pam * const pamP,
365             int          const size);
366 
367 void
368 pnm_writepaminit(struct pam * const pamP);
369 
370 void
371 pnm_formatpamrow(const struct pam * const pamP,
372                  const tuple *      const tuplerow,
373                  unsigned char *    const outbuf,
374                  unsigned int *     const rowSizeP);
375 
376 void
377 pnm_writepamrow(const struct pam * const pamP, const tuple * const tuplerow);
378 
379 void
380 pnm_writepamrowmult(const struct pam * const pamP,
381                     const tuple *      const tuplerow,
382                     unsigned int       const rptcnt);
383 
384 void
385 pnm_writepam(struct pam * const pamP, tuple ** const tuplearray);
386 
387 void
388 pnm_checkpam(const struct pam *   const pamP,
389              enum pm_check_type   const checkType,
390              enum pm_check_code * const retvalP);
391 
392 /*----------------------------------------------------------------------------
393    Facilities for working with maxval-normalized samples.  Such samples
394    are floating point quantities in the range 0..1.
395 
396    This is just a working format; there is no Netpbm image format that
397    has normalized samples.
398 -----------------------------------------------------------------------------*/
399 typedef float samplen;
400 
401 typedef samplen *tuplen;
402     /* Same as 'tuple', except using normalized samples. */
403 
404 tuplen
405 pnm_allocpamtuplen(const struct pam * const pamP);
406 
407 #define pnm_freepamtuplen(tuplen) pm_freerow((char*) tuplen)
408 
409 tuplen *
410 pnm_allocpamrown(const struct pam * const pamP);
411 
412 #define pnm_freepamrown(tuplenrow) pm_freerow((char*) tuplenrow)
413 
414 tuplen *
415 pnm_allocpamrown(const struct pam * const pamP);
416 
417 void
418 pnm_readpamrown(const struct pam * const pamP,
419                 tuplen *           const tuplenrow);
420 
421 void
422 pnm_writepamrown(const struct pam * const pamP,
423                  const tuplen *     const tuplenrow);
424 
425 tuplen **
426 pnm_allocpamarrayn(const struct pam * const pamP);
427 
428 void
429 pnm_freepamarrayn(tuplen **          const tuplenarray,
430                   const struct pam * const pamP);
431 
432 tuplen**
433 pnm_readpamn(FILE *       const file,
434              struct pam * const pamP,
435              int          const size);
436 
437 void
438 pnm_writepamn(struct pam * const pamP,
439               tuplen **    const tuplenarray);
440 
441 samplen
442 pnm_normalized_sample(struct pam * const pamP,
443                       sample       const sample);
444 
445 sample
446 pnm_unnormalized_sample(struct pam * const pamP,
447                         samplen      const sampleVal);
448 
449 void
450 pnm_normalizetuple(struct pam * const pamP,
451                    tuple        const tuple,
452                    tuplen       const tuplen);
453 
454 void
455 pnm_unnormalizetuple(struct pam * const pamP,
456                      tuplen       const tuplen,
457                      tuple        const tuple);
458 
459 void
460 pnm_normalizeRow(struct pam *             const pamP,
461                  const tuple *            const tuplerow,
462                  const pnm_transformMap * const transform,
463                  tuplen *                 const tuplenrow);
464 
465 void
466 pnm_unnormalizeRow(struct pam *             const pamP,
467                    const tuplen *           const tuplenrow,
468                    const pnm_transformMap * const transform,
469                    tuple *                  const tuplerow);
470 
471 /*----------------------------------------------------------------------------
472    Facilities for working with visual images in particular
473 -----------------------------------------------------------------------------*/
474 
475 
476 void
477 pnm_gammarown(struct pam * const pamP,
478               tuplen *     const row);
479 
480 void
481 pnm_ungammarown(struct pam * const pamP,
482                 tuplen *     const row);
483 
484 void
485 pnm_applyopacityrown(struct pam * const pamP,
486                      tuplen *     const tuplenrow);
487 
488 void
489 pnm_unapplyopacityrown(struct pam * const pamP,
490                        tuplen *     const tuplenrow);
491 
492 void
493 pnm_maketuplergbn(const struct pam * const pamP,
494                   tuplen             const tuple);
495 
496 void
497 pnm_makerowrgbn(const struct pam * const pamP,
498                 tuplen *           const tuplerow);
499 
500 void
501 pnm_makearrayrgbn(const struct pam * const pamP,
502                   tuplen **          const tuples);
503 
504 pnm_transformMap *
505 pnm_creategammatransform(const struct pam * const pamP);
506 
507 void
508 pnm_freegammatransform(const pnm_transformMap * const transform,
509                        const struct pam *       const pamP);
510 
511 pnm_transformMap *
512 pnm_createungammatransform(const struct pam * const pamP);
513 
514 #define pnm_freeungammatransform pnm_freegammatransform;
515 
516 tuple
517 pnm_parsecolor2(const char * const colorname,
518                 sample       const maxval,
519                 int          const closeOk);
520 
521 tuple
522 pnm_parsecolor(const char * const colorname,
523                sample       const maxval);
524 
525 tuplen
526 pnm_parsecolorn(const char * const colorname);
527 
528 const char *
529 pnm_colorname(struct pam * const pamP,
530               tuple        const color,
531               int          const hexok);
532 
533 const char *
534 pnm_colorspec_rgb_integer(struct pam * const pamP,
535                           tuple        const color,
536                           sample       const maxval);
537 
538 const char *
539 pnm_colorspec_rgb_norm(struct pam * const pamP,
540                        tuple        const color,
541                        unsigned int const digitCt);
542 
543 const char *
544 pnm_colorspec_rgb_x11(struct pam * const pamP,
545                       tuple        const color,
546                       unsigned int const hexDigitCt);
547 
548 const char *
549 pnm_colorspec_dict(struct pam * const pamP,
550                    tuple        const color);
551 
552 const char *
553 pnm_colorspec_dict_close(struct pam * const pamP,
554                          tuple        const color);
555 
556 extern double
557 pnm_lumin_factor[3];
558 
559 void
560 pnm_YCbCrtuple(const tuple tuple,
561                double * const YP, double * const CbP, double * const CrP);
562 
563 void
564 pnm_YCbCr_to_rgbtuple(const struct pam * const pamP,
565                       tuple              const tuple,
566                       double             const Y,
567                       double             const Cb,
568                       double             const Cr,
569                       int *              const overflowP);
570 
571 #define pnm_rgbtupleisgray(tuple) \
572     ((tuple)[PAM_RED_PLANE] == (tuple)[PAM_GRN_PLANE] && \
573      (tuple)[PAM_RED_PLANE] == (tuple)[PAM_BLU_PLANE])
574 
575 tuple
576 pnm_backgroundtuple(struct pam *  const pamP,
577                     tuple      ** const tuples);
578 
579 /*----------------------------------------------------------------------------
580    These are meant for passing to pm_system() as Standard Input feeder
581    and Standard Output accepter.
582 
583    The 'feederParm' or 'accepterParm' is a pointer to a struct pamtuples.
584 -----------------------------------------------------------------------------*/
585 
586 void
587 pm_feed_from_pamtuples(int    const pipeToFeedFd,
588                        void * const feederParm);
589 
590 void
591 pm_accept_to_pamtuples(int    const pipeToSuckFd,
592                        void * const accepterParm);
593 
594 #ifdef __cplusplus
595 }
596 #endif
597 #endif
598