1Libnetpbm Image Processing MLainburaalr(y3)FunctionLsibMnaentupablm Image Processing Manual(3)
2
3
4
5 Table Of Contents ⟨#toc⟩
6
8 libnetpbm_image - overview of netpbm image-processing functions
9
11 This reference manual covers functions in the libnetpbm library for
12 processing images, using the Netpbm image formats and the libnetpbm in-
13 memory image formats.
14
15 For historical reasons as well as to avoid clutter, it does not cover
16 the largely obsolete PBM, PGM, PPM, and PNM classes of libnetpbm func‐
17 tions. For those, see PBM Function Manual (1), PGMFunctionManual(1),
18 PPMFunctionManual(1),and PNMFunctionManual(1).Notethatyoudonot need
19 those functions to process PBM, PGM, PPM, and PNM images. The func‐
20 tions in this manual are sufficient for that.
21
22 The PPM drawing functions are covered separately in PPMDrawingFunction‐
23 Manual[1m(1).
24
25 For introductory and general information using libnetpbm, see Libnetpb‐
26 mUser'sGuide(1).
27
28 libnetpbm also contains functions that are not specifically oriented
29 toward processing image data. Read about those in the LibnetpbmUtili‐
30 tyManual(1).
31
32 To use these services, #include pam.h.
33
34
35
37 Here are some important types that you use with libnetpbm:
38
39
40
41
42 sample A sample of a Netpbm image. See the format specifications -- as
43 an example, the red intensity of a particular pixel of a PPM
44 image is a sample. This is an integer type.
45
46
47 tuple A tuple from a PAM image or the PAM equivalent of a PNM image.
48 See the PAM format specification -- as an example, a pixel of a
49 PPM image would be a tuple. A tuple is an array of samples.
50
51
52 samplen
53 Same as sample, except in normalized form. This is a floating
54 point type with a value in the range 0..1. 0 corresponds to a
55 PAM/PNM sample value of 0. 1 corresponds to a PAM/PNM sample
56 value equal to the image's maxval.
57
58
59 tuplen The same as tuple, except composed of normalized samples (sam‐
60 plen) intead of regular samples (sample).
61
62
63
64 The main argument to most of the PAM functions is the address of a pam
65 structure, which is defined as follows:
66
67 struct pam { int size int len FILE *file int format int plainformat int
68 height int width int depth sample maxval int bytes_per_sample char
69 tuple_type[256] int allocation_depth char **comment_p; }
70
71 See The Libnetbm User's Guide ⟨libnetpbm_ug.html#pamstruct⟩ for infor‐
72 mation on the pam structure.
73
74
75
77 PNM_MAXMAXVAL is the maximum maxval that Netpbm images could histori‐
78 cally have: 255. Many programs aren't capable of handling Netpbm
79 images with a maxval larger than this. It's named this way for back‐
80 ward compatibility -- it had this name back when it was the maximum
81 maxval.
82
83 PNM_OVERALLMAXVAL is the maximum maxval that Netpbm images can have
84 today (65535).
85
86 PBM_FORMAT, RPBM_FORMAT, PGM_FORMAT, RPGM_FORMAT, PPM_FORMAT, RPPM_FOR‐
87 MAT, and PAM_FORMAT are the format codes of the various Netpbm formats.
88 RPBM_FORMAT is the raw PBM format and PBM_FORMAT is the plain PBM for‐
89 mat, and so on. See the format member of the pam structure
90 ⟨libnetpbm_ug.html#pamstruct⟩ .
91
92 PAM_FORMAT_TYPE(format) gives the type of a format, given the format
93 code. The types of formats are PBM, PGM, PPM, and PAM and macros for
94 the type codes are, respectively, PBM_TYPE, PGM_TYPE, PPM_TYPE, and
95 PAM_TYPE. Note that there are more format codes then there are format
96 types because there are different format codes for the plain and raw
97 subformats of each format.
98
99
100
101
103 These interfaces are declared in pam.h.
104
105
106 Memory Management
107 Synopsis
108
109 tuple ** pnm_allocpamarray( struct pam *pamP);
110
111 tuple * pnm_allocpamrow( struct pam *pamP);
112
113 void pnm_freepamarray( tuple **tuplearray, struct pam *pamP);
114
115 void pnm_freepamrow( tuple *tuplerow);
116
117 tuple * allocpamtuple( struct pam *pamP);
118
119 void pnm_freepamtuple( tuple tuple );
120
121 tuplen * pnm_allocpamrown( struct pam *pamP);
122
123 void pnm_freepamrown( tuplen *tuplenrow);
124
125
126
127 Description
128
129 pnm_allocpamarray() allocates space for an array of tuples.
130 pnm_freepamarray() frees an array space allocated by pnm_allocpamar‐
131 ray() or pnm_readpam().
132
133 pnm_allocpamrow() allocates space for a row of a PAM image, in basic
134 form. pnm_freepamrow() frees it.
135
136 pnm_allocpamrown() is the same as pnm_allocpamrow() except that it
137 allocates space for a PAM row in the normalized form. pnm_freepam‐
138 rown() is similarly like pnm_freepamrow.
139
140
141
142 Reading Netpbm Files
143 Synopsis
144
145 void pnm_readpaminit( FILE *file, struct pam *pamP, int size);
146
147 void pnm_readpamrow( struct pam *pamP, tuple *tuplerow);
148
149 tuple ** pnm_readpam( FILE *file, struct pam *pamP, int size);
150
151 void pnm_readpamrown( struct pam *pamP, tuplen *tuplenrow);
152
153
154 Description
155
156 pnm_readpaminit() reads the header of a Netpbm image.
157
158 See above for a general description of the pamP argument.
159
160 pnm_readpaminit() returns the information from the header in the *pamP
161 structure. It does not require any members of *pamP through tuple_type
162 to be set at invocation, and sets all of those members. It expects all
163 members after tuple_type to be meaningful.
164
165 size is the size of the *pamP structure as understood by the program
166 processing the image. pnm_readpaminit() does not attempt to use or set
167 any members of the structure beyond that. The point of this argument
168 is that the definition of the structure may change over time, with
169 additional fields being added to the end. This argument allows
170 pnm_readpaminit to distinguish between a new program that wants to
171 exploit the additional features and an old program that cannot (or a
172 new program that just doesn't want to deal with the added complexity).
173 At a minimum, this size must contain the members up through tuple_type.
174 You should use the PAM_STRUCT_SIZE macro to compute this argument.
175 E.g. PAM_STRUCT_SIZE(tuple_type).
176
177 PAM_STRUCT_SIZE was introduced in Netpbm 10.23 (July 2004). In older
178 Netpbm, you can just use sizeof(), but then your code is not forward
179 compatible at the source code level with newer libnetpbm (because when
180 you compile it with newer libnetpbm header files, you'll be saying your
181 structure contains all the new members that have been invented, but
182 your code doesn't actually initialize them). So you might want to com‐
183 pute a proper size yourself.
184
185 The function expects to find the image file positioned to the start of
186 the header and leaves it positioned to the start of the raster.
187
188 pnm_readpamrow() reads a row of the raster from a Netpbm image file.
189 It expects all of the members of the *pamP structure to be set upon
190 invocation and does not modify any of them. It expects to find the
191 file positioned to the start of the row in question in the raster and
192 leaves it positioned just after it. It returns the row as the array of
193 tuples tuplerow, which must already have its column pointers set up so
194 that it forms a C 2-dimensional array. The leftmost tuple is Element 0
195 of this array.
196
197 pnm_readpam() reads an entire image from a PAM or PNM image file and
198 allocates the space in which to return the raster. It expects to find
199 the file positioned to the first byte of the image and leaves it posi‐
200 tioned just after the image.
201
202 The function does not require *pamP to have any of its members set and
203 sets them all. size is the storage size in bytes of the *pamP struc‐
204 ture, normally sizeof(struct pam).
205
206 The return value is a newly allocated array of the rows of the image,
207 with the top row being Element 0 of the array. Each row is represented
208 as pnm_readpamrow() would return.
209
210 The return value is also effectively a 3-dimensional C array of sam‐
211 ples, with the dimensions corresponding to the height, width, and depth
212 of the image, in that order.
213
214 pnm_readpam() combines the functions of pnm_allocpamarray(), pnm_read‐
215 paminit(), and iterations of pnm_readpamrow(). It may require more
216 dynamic storage than you can afford.
217
218 pnm_readpamrown() is like pnm_readpamrow() except that it returns the
219 row contents in normalized form (composed of normalized tuples (tuplen)
220 instead of basic form (tuple).
221
222 pnm_readpaminit() and pnm_readpam abort the program with a message to
223 Standard Error if the PAM or PNM image header is not syntactically
224 valid, including if it contains a number too large to be processed
225 using the system's normal data structures (to wit, a number that won't
226 fit in a C 'int').
227
228
229 Writing Netpbm Files
230 Synopsis
231
232 void pnm_writepaminit( struct pam *pamP);
233
234 void pnm_writepamrow( struct pam *pamP, const tuple *tuplerow);
235
236 void pnm_writepam( struct pam *pamP, const tuple * const *tuplearray);
237
238 void pnm_writepamrown( struct pam *pamP, const tuplen *tuplerown);
239
240 void pnm_formatpamrow( struct pam *pamP, const tuple *tuplerow unsigned
241 char * const outbuf, unsigned int * const rowSizeP );
242
243 Description
244
245 pnm_writepaminit() writes the header of a PAM or PNM image and computes
246 some of the fields of the pam structure.
247
248 See above for a description of the pamP argument.
249
250 The following members of the *pamP structure must be set upon invoca‐
251 tion to tell the function how and what to write. size, len, file, for‐
252 mat, height, width, depth, maxval. Furthermore, if format is PAM_FOR‐
253 MAT, tuple_type must be set.
254
255 pnm_writepaminit() sets the plainformat and bytes_per_sample members
256 based on the information supplied.
257
258 pnm_writepamrow() writes a row of the raster into a PAM or PNM image
259 file. It expects to find the file positioned where the row should
260 start and leaves it positioned just after the row. The function
261 requires all the elements of *pamP to be set upon invocation and
262 doesn't modify them.
263
264 tuplerow is an array of tuples representing the row. The leftmost
265 tuple is Element 0 of this array.
266
267 pnm_writepam() writes an entire PAM or PNM image to a PAM or PNM image
268 file. It expects to find the file positioned to where the image should
269 start and leaves it positioned just after the image.
270
271 The following members of the *pamP structure must be set upon invoca‐
272 tion to tell the function how and what to write: size, len, file, for‐
273 mat, height, width, depth, maxval, tuple_type.
274
275 pnm_writepam() sets the plainformat and bytes_per_sample members based
276 on the information supplied.
277
278 tuplearray is an array of rows such that you would pass to
279 pnm_writepamrow(), with the top row being Element 0 of the array.
280
281 pnm_writepam() combines the functions of pnm_writepaminit(), and itera‐
282 tions of pnm_writepamrow(). Its raster input may be more storage than
283 you can afford.
284
285 pnm_writepamrown() is like pnm_writepamrow() except that it takes the
286 row contents in normalized form (composed of normalized tuples (tuplen)
287 instead of basic form (tuple).
288
289 pnm_formatpamrow() is like pnm_writepamrow(), except that instead of
290 writing a row to a file, it places the same bytes that would go in the
291 file in a buffer you supply. There isn't an equivalent function to
292 construct an image header; i.e. there is no analog to
293 pnm_writepaminit(). But the header format, particularly for PAM, is so
294 simple that you can easily build it yourself with standard C library
295 string functions.
296
297 pnm_formatpamrow() was new in Netpbm 10.25 (October 2004).
298
299
300 Transforming Pixels
301 Synopsis
302
303 void pnm_YCbCrtuple( tuple tuple, double *YP, double *CrP, double
304 *CbP);
305
306 void pnm_YCbCr_to_rgbtuple( const struct pam * const pamP, tuple const
307 tuple, double const Y, double const Cb, double const Cr, int * const
308 overflowP);
309
310 extern double pnm_lumin_factor[3];
311
312 void pnm_normalizetuple( struct pam * const pamP, tuple const
313 tuple, tuplen const tuplen);
314
315 void pnm_unnormalizetuple( struct pam * const pamP, tuplen const
316 tuplen, tuple const tuple);
317
318 void pnm_normalizeRow( struct pam * const pamP, const tuple *
319 const tuplerow, pnm_transformMap * const transform, tuplen *
320 const tuplenrow);
321
322 void pnm_unnormalizeRow( struct pam * const pamP, const tuplen *
323 const tuplenrow, pnm_transformMap * const transform, tuple *
324 const tuplerow);
325
326 void pnm_gammarown( struct pam * const pamP, tuplen * const row);
327
328 void pnm_ungammarown( struct pam * const pamP, tuplen * const row);
329
330 void pnm_applyopacityrown( struct pam * const pamP, tuplen * const
331 tuplenrow);
332
333 void pnm_unapplyopacityrown( struct pam * const pamP, tuplen *
334 const tuplenrow);
335
336 pnm_transformMap * pnm_creategammatransform( const struct pam * const
337 pamP);
338
339 void pnm_freegammatransform( const pnm_transformMap * const transform,
340 const struct pam * const pamP);
341
342 pnm_transformMap * pnm_createungammatransform( const struct pam * const
343 pamP);
344
345 void pnm_freeungammatransform( const pnm_transformMap * const trans‐
346 form, const struct pam * const pamP);
347
348
349 Description
350
351 pnm_YCbCrtuple() returns the Y/Cb/Cr luminance/chrominance representa‐
352 tion of the color represented by the input tuple, assuming that the
353 tuple is an RGB color representation (which is the case if it was read
354 from a PPM image). The output components are based on the same scale
355 (maxval) as the input tuple, but are floating point nonetheless to
356 avoid losing information due to rounding. Divide them by the maxval to
357 get normalized [0..1] values.
358
359 pnm_YCbCr_to_rgbtuple() does the reverse. pamP indicates the maxval
360 for the returned tuple, and the Y, Cb, and Cr arguments are of the same
361 scale.
362
363 It is possible for Y, Cb, and Cr to describe a color that cannot be
364 represented in RGB form. In that case, pnm_YCbCr_to_rgbtuple() chooses
365 a color as close as possible (by clipping each component to 0 and the
366 maxval) and sets *overflowP true. It otherwise sets *overflowP false.
367
368
369 pnm_lumin_factor[] is the factors (weights) one uses to compute the
370 intensity of a color (according to some standard -- I don't know
371 which). pnm_lumin_factor[0] is for the red component, [1] is for the
372 green, and [2] is for the blue. They add up to 1.
373
374 pnm_gammarown() and pnm_ungammarown() apply and unapply gamma correc‐
375 tion to a row of an image using the same transformation as
376 pm_gamma709() and pm_ungamma709() ⟨libpm.html#gamma⟩ . Note that these
377 operate on a row of normalized tuples (tuplen, not tuple).
378
379 pnm_applyopacityrown() reduces the intensity of samples in accordance
380 with the opacity plane of an image. The opacity plane, if it exists,
381 tells how much of the light from that pixel should show when the image
382 is composed with another image. You use pnm_applyopacityrown() in
383 preparation for doing such a composition. For example, if the opacity
384 plane says that the left half of the image is 50% opaque and the right
385 half 100% opaque, pnm_applyopacityrown() will reduce the intensity of
386 each sample of each tuple (pixel) in the left half of the image by 50%,
387 and leave the rest alone.
388
389 If the image does not have an opacity plane (i.e. its tuple type is not
390 one that libnetpbm recognizes as having an opacity plane), pnm_apply‐
391 opacityrown() does nothing (which is the same as assuming opacity
392 100%). The tuple types that libnetpbm recognizes as having opacity are
393 RGB_ALPHA and GRAYSCALE_ALPHA.
394
395 pnm_unapplyopacityrown() does the reverse. It assumes the intensities
396 are already reduced according to the opacity plane, and raises back to
397 normal.
398
399 pnm_applyopacityrown() works on (takes as input and produces as output)
400 normalized, intensity-proportional tuples. That means you will typi‐
401 cally read the row from the image file with pnm_readpamrown() and then
402 gamma-correct it with pnm_ungammarown(), and then do pnm_applyopacity‐
403 rown(). You then manipulate the row further (perhaps add it with other
404 rows you've processed similarly), then do pnm_unapplyopacityrown(),
405 then pnm_gammarown(), then pnm_writepamrown().
406
407 pnm_applyopacityrown() and pnm_unapplyopacityrown() were new in Netpbm
408 10.25 (October 2004).
409
410 pnm_normalizetuple() and pnm_unnormalizetuple() convert between a tuple
411 data type and a tuplen data type. The former represents a sample value
412 using the same unsigned integer that is in the PAM image, while the
413 latter represents a sample value as a number scaled by the maxval to
414 the range 0..1. I.e. pnm_normalizetuple() divides every sample value
415 by the maxval and pnm_unnormalizetuple() multiples every sample by the
416 maxval.
417
418 pnm_normalizeRow() and pnm_unnormalizeRow() do the same thing on an
419 entire tuple row, but also have an extra feature: You can specify a
420 transform function to be applied in addition. Typically, this is a
421 gamma transform function. You can of course more easily apply your
422 transform function separately from normalizing, but doing it all at
423 once is usually way faster. Why? Because you can use a lookup table
424 that is indexed by an integer on one side and produces a floating point
425 number on the other. To do it separately, you'd either have to do
426 floating point arithmetic on the normalized value or do the transform
427 on the integer values and lose a lot of precision.
428
429 If you don't have any transformation to apply, just specify NULL for
430 the transform argument and the function will just normalize (i.e.
431 divide or multiply by the maxval).
432
433 Here's an example of doing a transformation. The example composes two
434 images together, something that has to be done with intensity-linear
435 sample values.
436
437
438 pnm_transformMap * const transform1 = pnm_createungammatransform(&inpam1);
439 pnm_transformMap * const transform2 = pnm_createungammatransform(&inpam2);
440 pnm_transformMap * const transformOut = pnm_creategammatransform(&outpam);
441
442 pnm_readpamrow(&inpam1, inrow1);
443 pnm_readpamrow(&inpam2, inrow2);
444
445 pnm_normalizeRow(&inpam1, inrow1, transform1, normInrow1);
446 pnm_normalizeRow(&inpam2, inrow2, transform2, normInrow2);
447
448 for (col = 0; col < outpam.width; ++col)
449 normOutrow[col] = (normInrow1[col] + normInrow2[col])/2;
450
451 pnm_unnormalizeRow(&outpam, normOutrow, transformOut, outrow);
452
453 pnm_writepamrow(&outpam, outrow);
454
455
456 To specify a transform, you must create a special pnm_transformMap
457 object and pass it as the transform argument. Typically, your trans‐
458 form is a gamma transformation because you want to work in intensity-
459 proportional sample values and the PAM image format uses gamma-adjusted
460 ones. In that case, just use pnm_creategammatransform() and pnm_crea‐
461 teungammatransform() to create this object and don't worry about what's
462 inside it.
463
464 pnm_creategammatransform() and pnm_createungammatransform() create
465 objects that you use with pnm_normalizeRow() and pnm_unnormalizeRow()
466 as described above. The created object describes a transform that
467 applies or reverses the ITU-R Recommendation BT.709 gamma adjustment
468 that is used in PAM visual images and normalizes or unnormalizes the
469 sample values.
470
471 pnm_freegammatransform() and pnm_freeungammatransform() destroy the
472 objects.
473
474
475
476 Miscellaneous
477 Synopsis
478
479 void pnm_checkpam( struct pam *pamP, const enum pm_check_type
480 check_type, enum pm_check_code *retvalP);
481
482 void pnm_nextimage( FILE *file, int * const eofP);
483
484 Description
485
486 pnm_checkpam() checks for the common file integrity error where the
487 file is the wrong size to contain the raster, according to the informa‐
488 tion in the header.
489
490 pnm_nextimage()positions a Netpbm image input file to the next image in
491 it (so that a subsequent pnm_readpaminit() reads its header).
492
493
494
495netpbm documentation December 2L0i0b3netpbm Image Processing Manual(3)