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 function 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( tuple *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 The function expects to find the image file positioned to the start of
178 the header and leaves it positioned to the start of the raster.
179
180 pnm_readpamrow() reads a row of the raster from a Netpbm image file.
181 It expects all of the members of the *pamP structure to be set upon
182 invocation and does not modify any of them. It expects to find the
183 file positioned to the start of the row in question in the raster and
184 leaves it positioned just after it. It returns the row as the array of
185 tuples tuplerow, which must already have its column pointers set up so
186 that it forms a C 2-dimensional array. The leftmost tuple is Element 0
187 of this array.
188
189 pnm_readpam() reads an entire image from a PAM or PNM image file and
190 allocates the space in which to return the raster. It expects to find
191 the file positioned to the first byte of the image and leaves it posi‐
192 tioned just after the image.
193
194 The function does not require *pamP to have any of its members set and
195 sets them all. size is the storage size in bytes of the *pamP struc‐
196 ture, normally sizeof(struct pam).
197
198 The return value is a newly allocated array of the rows of the image,
199 with the top row being Element 0 of the array. Each row is represented
200 as pnm_readpamrow() would return.
201
202 The return value is also effectively a 3-dimensional C array of sam‐
203 ples, with the dimensions corresponding to the height, width, and depth
204 of the image, in that order.
205
206 pnm_readpam() combines the functions of pnm_allocpamarray(), pnm_read‐
207 paminit(), and iterations of pnm_readpamrow(). It may require more
208 dynamic storage than you can afford.
209
210 pnm_readpamrown() is like pnm_readpamrow() except that it returns the
211 row contents in normalized form (composed of normalized tuples (tuplen)
212 instead of basic form (tuple).
213
214 pnm_readpaminit() and pnm_readpam abort the program with a message to
215 Standard Error if the PAM or PNM image header is not syntactically
216 valid, including if it contains a number too large to be processed
217 using the system's normal data structures (to wit, a number that won't
218 fit in a C 'int').
219
220
221 Writing Netpbm Files
222 Synopsis
223
224 void pnm_writepaminit( struct pam *pamP);
225
226 void pnm_writepamrow( struct pam *pamP, const tuple *tuplerow);
227
228 void pnm_writepam( struct pam *pamP, const tuple * const *tuplearray);
229
230 void pnm_writepamrown( struct pam *pamP, const tuplen *tuplerown);
231
232 void pnm_formatpamrow( struct pam *pamP, const tuple *tuplerow unsigned
233 char * const outbuf, unsigned int * const rowSizeP );
234
235 Description
236
237 pnm_writepaminit() writes the header of a PAM or PNM image and computes
238 some of the fields of the pam structure.
239
240 See above for a description of the pamP argument.
241
242 The following members of the *pamP structure must be set upon invoca‐
243 tion to tell the function how and what to write. size, len, file, for‐
244 mat, height, width, depth, maxval, tuple_type.
245
246 pnm_writepaminit() sets the plainformat and bytes_per_sample members
247 based on the information supplied.
248
249 pnm_writepamrow() writes a row of the raster into a PAM or PNM image
250 file. It expects to find the file positioned where the row should
251 start and leaves it positioned just after the row. The function
252 requires all the elements of *pamP to be set upon invocation and
253 doesn't modify them.
254
255 tuplerow is an array of tuples representing the row. The leftmost
256 tuple is Element 0 of this array.
257
258 pnm_writepam() writes an entire PAM or PNM image to a PAM or PNM image
259 file. It expects to find the file positioned to where the image should
260 start and leaves it positioned just after the image.
261
262 The following members of the *pamP structure must be set upon invoca‐
263 tion to tell the function how and what to write: size, len, file, for‐
264 mat, height, width, depth, maxval, tuple_type.
265
266 pnm_writepam() sets the plainformat and bytes_per_sample members based
267 on the information supplied.
268
269 tuplearray is an array of rows such that you would pass to
270 pnm_writepamrow(), with the top row being Element 0 of the array.
271
272 pnm_writepam() combines the functions of pnm_writepaminit(), and itera‐
273 tions of pnm_writepamrow(). Its raster input may be more storage than
274 you can afford.
275
276 pnm_writepamrown() is like pnm_writepamrow() except that it takes the
277 row contents in normalized form (composed of normalized tuples (tuplen)
278 instead of basic form (tuple).
279
280 pnm_formatpamrow() is like pnm_writepamrow(), except that instead of
281 writing a row to a file, it places the same bytes that would go in the
282 file in a buffer you supply. There isn't an equivalent function to
283 construct an image header; i.e. there is no analog to
284 pnm_writepaminit(). But the header format, particularly for PAM, is so
285 simple that you can easily build it yourself with standard C library
286 string functions.
287
288 pnm_formatpamrow() was new in Netpbm 10.25 (October 2004).
289
290
291 Transforming Pixels
292 Synopsis
293
294 void pnm_YCbCrtuple( tuple tuple, double *YP, double *CrP, double
295 *CbP);
296
297 void pnm_YCbCr_to_rgbtuple( const struct pam * const pamP, tuple const
298 tuple, double const Y, double const Cb, double const Cr, int * const
299 overflowP);
300
301 extern double pnm_lumin_factor[3];
302
303 void pnm_normalizetuple( struct pam * const pamP, tuple const
304 tuple, tuplen const tuplen);
305
306 void pnm_unnormalizetuple( struct pam * const pamP, tuplen const
307 tuplen, tuple const tuple);
308
309 void pnm_normalizeRow( struct pam * const pamP, const tuple *
310 const tuplerow, pnm_transformMap * const transform, tuplen *
311 const tuplenrow);
312
313 void pnm_unnormalizeRow( struct pam * const pamP, const tuplen *
314 const tuplenrow, pnm_transformMap * const transform, tuple *
315 const tuplerow);
316
317 void pnm_gammarown( struct pam * const pamP, tuplen * const row);
318
319 void pnm_ungammarown( struct pam * const pamP, tuplen * const row);
320
321 void pnm_applyopacityrown( struct pam * const pamP, tuplen * const
322 tuplenrow);
323
324 void pnm_unapplyopacityrown( struct pam * const pamP, tuplen *
325 const tuplenrow);
326
327 pnm_transformMap * pnm_creategammatransform( const struct pam * const
328 pamP);
329
330 void pnm_freegammatransform( const pnm_transformMap * const transform,
331 const struct pam * const pamP);
332
333 pnm_transformMap * pnm_createungammatransform( const struct pam * const
334 pamP);
335
336 void pnm_freeungammatransform( const pnm_transformMap * const trans‐
337 form, const struct pam * const pamP);
338
339
340 Description
341
342 pnm_YCbCrtuple() returns the Y/Cb/Cr luminance/chrominance representa‐
343 tion of the color represented by the input tuple, assuming that the
344 tuple is an RGB color representation (which is the case if it was read
345 from a PPM image). The output components are based on the same scale
346 (maxval) as the input tuple, but are floating point nonetheless to
347 avoid losing information due to rounding. Divide them by the maxval to
348 get normalized [0..1] values.
349
350 pnm_YCbCr_to_rgbtuple() does the reverse. pamP indicates the maxval
351 for the returned tuple, and the Y, Cb, and Cr arguments are of the same
352 scale.
353
354 It is possible for Y, Cb, and Cr to describe a color that cannot be
355 represented in RGB form. In that case, pnm_YCbCr_to_rgbtuple() chooses
356 a color as close as possible (by clipping each component to 0 and the
357 maxval) and sets *overflowP true. It otherwise sets *overflowP false.
358
359
360 pnm_lumin_factor[] is the factors (weights) one uses to compute the
361 intensity of a color (according to some standard -- I don't know
362 which). pnm_lumin_factor[0] is for the red component, [1] is for the
363 green, and [2] is for the blue. They add up to 1.
364
365 pnm_gammarown() and pnm_ungammarown() apply and unapply gamma correc‐
366 tion to a row of an image using the same transformation as
367 pm_gamma709() and pm_ungamma709() ⟨libpm.html#gamma⟩ . Note that these
368 operate on a row of normalized tuples (tuplen, not tuple).
369
370 pnm_applyopacityrown() reduces the intensity of samples in accordance
371 with the opacity plane of an image. The opacity plane, if it exists,
372 tells how much of the light from that pixel should show when the image
373 is composed with another image. You use pnm_applyopacityrown() in
374 preparation for doing such a composition. For example, if the opacity
375 plane says that the left half of the image is 50% opaque and the right
376 half 100% opaque, pnm_applyopacityrown() will reduce the intensity of
377 each sample of each tuple (pixel) in the left half of the image by 50%,
378 and leave the rest alone.
379
380 If the image does not have an opacity plane (i.e. its tuple type is not
381 one that libnetpbm recognizes as having an opacity plane), pnm_apply‐
382 opacityrown() does nothing (which is the same as assuming opacity
383 100%). The tuple types that libnetpbm recognizes as having opacity are
384 RGB_ALPHA and GRAYSCALE_ALPHA.
385
386 pnm_unapplyopacityrown() does the reverse. It assumes the intensities
387 are already reduced according to the opacity plane, and raises back to
388 normal.
389
390 pnm_applyopacityrown() works on (takes as input and produces as output)
391 normalized, intensity-proportional tuples. That means you will typi‐
392 cally read the row from the image file with pnm_readpamrown() and then
393 gamma-correct it with pnm_ungammarown(), and then do pnm_applyopacity‐
394 rown(). You then manipulate the row further (perhaps add it with other
395 rows you've processed similarly), then do pnm_unapplyopacityrown(),
396 then pnm_gammarown(), then pnm_writepamrown().
397
398 pnm_applyopacityrown() and pnm_unapplyopacityrown() were new in Netpbm
399 10.25 (October 2004).
400
401 pnm_normalizetuple() and pnm_unnormalizetuple() convert between a tuple
402 data type and a tuplen data type. The former represents a sample value
403 using the same unsigned integer that is in the PAM image, while the
404 latter represents a sample value as a number scaled by the maxval to
405 the range 0..1. I.e. pnm_normalizetuple() divides every sample value
406 by the maxval and pnm_unnormalizetuple() multiples every sample by the
407 maxval.
408
409 pnm_normalizeRow() and pnm_unnormalizeRow() do the same thing on an
410 entire tuple row, but also have an extra feature: You can specify a
411 transform function to be applied in addition. Typically, this is a
412 gamma transform function. You can of course more easily apply your
413 transform function separately from normalizing, but doing it all at
414 once is usually way faster. Why? Because you can use a lookup table
415 that is indexed by an integer on one side and produces a floating point
416 number on the other. To do it separately, you'd either have to do
417 floating point arithmetic on the normalized value or do the transform
418 on the integer values and lose a lot of precision.
419
420 If you don't have any transformation to apply, just specify NULL for
421 the transform argument and the function will just normalize (i.e.
422 divide or multiply by the maxval).
423
424 Here's an example of doing a transformation. The example composes two
425 images together, something that has to be done with intensity-linear
426 sample values.
427
428
429 pnm_transformMap * const transform1 = pnm_createungammatransform(&inpam1);
430 pnm_transformMap * const transform2 = pnm_createungammatransform(&inpam2);
431 pnm_transformMap * const transformOut = pnm_creategammatransform(&outpam);
432
433 pnm_readpamrow(&inpam1, inrow1);
434 pnm_readpamrow(&inpam2, inrow2);
435
436 pnm_normalizeRow(&inpam1, inrow1, transform1, normInrow1);
437 pnm_normalizeRow(&inpam2, inrow2, transform2, normInrow2);
438
439 for (col = 0; col < outpam.width; ++col)
440 normOutrow[col] = (normInrow1[col] + normInrow2[col])/2;
441
442 pnm_unnormalizeRow(&outpam, normOutrow, transformOut, outrow);
443
444 pnm_writepamrow(&outpam, outrow);
445
446
447 To specify a transform, you must create a special pnm_transformMap
448 object and pass it as the transform argument. Typically, your trans‐
449 form is a gamma transformation because you want to work in intensity-
450 proportional sample values and the PAM image format uses gamma-adjusted
451 ones. In that case, just use pnm_creategammatransform() and pnm_crea‐
452 teungammatransform() to create this object and don't worry about what's
453 inside it.
454
455 pnm_creategammatransform() and pnm_createungammatransform() create
456 objects that you use with pnm_normalizeRow() and pnm_unnormalizeRow()
457 as described above. The created object describes a transform that
458 applies or reverses the ITU-R Recommendation BT.709 gamma adjustment
459 that is used in PAM visual images and normalizes or unnormalizes the
460 sample values.
461
462 pnm_freegammatransform() and pnm_freeungammatransform() destroy the
463 objects.
464
465
466
467 Miscellaneous
468 Synopsis
469
470 void pnm_checkpam( struct pam *pamP, const enum pm_check_type
471 check_type, enum pm_check_code *retvalP);
472
473 void pnm_nextimage( FILE *file, int * const eofP);
474
475 Description
476
477 pnm_checkpam() checks for the common file integrity error where the
478 file is the wrong size to contain the raster, according to the informa‐
479 tion in the header.
480
481 pnm_nextimage()positions a Netpbm image input file to the next image in
482 it (so that a subsequent pnm_readpaminit() reads its header).
483
484
485
486netpbm documentation December 2L0i0b3netpbm Image Processing Manual(3)