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 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.3//EN">
<html>
<head>
<title>Libnetpbm Image Processing Manual</title>
<meta name="manual_section" content="3">
</head>
<body>
<h1>Libnetpbm Image Processing Manual</h1>
Updated: May 2018
<br>
<p><a href="#toc">Table Of Contents</a>
<?makeman .SH NAME ?>
<?makeman libnetpbm_image - overview of netpbm image-processing functions ?>
<?makeman .SH DESCRIPTION ?>
<p>This reference manual covers functions in the <b>libnetpbm</b>
library for processing images, using the Netpbm image formats and the
<b>libnetpbm</b> in-memory image formats.
<p>For historical reasons as well as to avoid clutter, it does not cover the
largely obsolete PBM, PGM, PPM, and PNM classes of <b>libnetpbm</b> functions.
For those, see
<ul>
<li><a href="libpbm.html">PBM Function Manual</a>,
<li><a href="libpgm.html">PGM Function Manual</a>,
<li><a href="libppm.html">PPM Function Manual</a>,
<li><a href="libpnm.html">PNM Function Manual</a>
</ul>
Note that you do <em>not</em> need those functions to process PBM, PGM, PPM,
and PNM images. The functions in this manual are sufficient for that.
<p>The PPM drawing functions are covered separately in
<a href="libnetpbm_draw.html">PPM Drawing Function Manual</a>.
<p>The PBM text font functions are convered separately in
<a href="libnetpbm_font.html">PBM Font Function Manual</a>.
<p>For introductory and general information using <b>libnetpbm</b>, see
<a href="libnetpbm_ug.html">Libnetpbm User's Guide</a>.
<p><b>libnetpbm</b> also contains functions that are not specifically
oriented toward processing image data. Read about those in the
<a href="libpm.html">Libnetpbm Utility Manual</a>.
<p>To use these services, #include <b>pam.h</b>.
<h2 id="types">Types</h2>
<p>Here are some important types that you use with <b>libnetpbm</b>:
<dl>
<dt>sample
<dd>A sample of a Netpbm image. See the format specifications -- as an
example, the red intensity of a particular pixel of a PPM image is a
sample. This is an integer type.
<dt>tuple
<dd>A tuple from a PAM image or the PAM equivalent of a PNM image.
See the PAM format specification -- as an example, a pixel of a PPM image
would be a tuple. A tuple is an array of samples.
<dt>samplen
<dd>Same as <b>sample</b>, except in normalized form. This is a floating
point type with a value in the range 0..1. 0 corresponds to a PAM/PNM
sample value of 0. 1 corresponds to a PAM/PNM sample value equal to the
image's maxval.
<dt>tuplen
<dd>The same as <b>tuple</b>, except composed of normalized samples
(<b>samplen</b>) instead of regular samples (<b>sample</b>).
</dl>
<h3 id="pamstruct">struct pam</h3>
<p>The main argument to most of the PAM functions is the address of
a <b>pam</b> structure, which is defined as follows:
<pre>
<code>
<b>struct pam {</b>
<b>int </b><i>size</i>
<b>int </b><i>len</i>
<b>FILE *</b><i>file </i>
<b>int </b><i>format</i>
<b>int </b><i>plainformat</i>
<b>int </b><i>height</i>
<b>int </b><i>width</i>
<b>int </b><i>depth</i>
<b>sample </b><i>maxval</i>
<b>int </b><i>bytes_per_sample</i>
<b>char </b><i>tuple_type</i><b>[256]</b>
<b>int </b><i>allocation_depth</i>
<b>char **</b><i>comment_p</i><b>;</b>
<b>}</b>
</code>
</pre>
<p>See <a href="libnetpbm_ug.html#pamstruct">The Libnetbm User's Guide</a>
for information on the <b>pam</b> structure.
<h2 id="macros">Macros</h2>
<b>PNM_MAXMAXVAL</b> is the maximum maxval that Netpbm images could
historically have: 255. Many programs aren't capable of handling Netpbm
images with a maxval larger than this. It's named this way for backward
compatibility -- it had this name back when it was <em>the</em> maximum
maxval.
<p><b>PNM_OVERALLMAXVAL</b> is the maximum maxval that Netpbm images can
have today (65535).
<p><b>PBM_FORMAT</b>, <b>RPBM_FORMAT</b>, <b>PGM_FORMAT</b>,
<b>RPGM_FORMAT</b>, <b>PPM_FORMAT</b>, <b>RPPM_FORMAT</b>, and
<b>PAM_FORMAT</b> are the format codes of the various Netpbm formats.
<b>RPBM_FORMAT</b> is the raw PBM format and <b>PBM_FORMAT</b> is the
plain PBM format, and so on. See the <i>format</i> member of <a
href="libnetpbm_ug.html#pamstruct">the <b>pam</b> structure</a>.
<p><b>PAM_FORMAT_TYPE(</b><i>format</i><b>)</b> gives the type of a
format, given the format code. The types of formats are PBM, PGM,
PPM, and PAM and macros for the type codes are, respectively,
PBM_TYPE, PGM_TYPE, PPM_TYPE, and PAM_TYPE. Note that there are more
format codes then there are format types because there are different
format codes for the plain and raw subformats of each format.
<p>Macros for the tuple types that are defined by Netpbm are as follows.
See the <i>tuple_type</i> member of <a
href="libnetpbm_ug.html#pamstruct">the <b>pam</b> structure</a>.
<ul>
<li><b>PAM_PBM_TUPLETYPE</b>
<li><b>PAM_PGM_TUPLETYPE</b>
<li><b>PAM_PPM_TUPLETYPE</b>
<li><b>PAM_PBM_ALPHA_TUPLETYPE</b>
<li><b>PAM_PGM_ALPHA_TUPLETYPE</b>
<li><b>PAM_PPM_ALPHA_TUPLETYPE</b>
</ul>
<h2 id="functions">Functions</h2>
<p>These interfaces are declared in <b>pam.h</b>.
<h3 id="memory">Memory Management</h3>
<h4>Synopsis</h4>
<p>
<b>tuple ** pnm_allocpamarray(</b>
<b>struct pam *</b><i>pamP</i><b>);</b>
<p>
<b>tuple * pnm_allocpamrow(</b>
<b>struct pam *</b><i>pamP</i><b>);</b>
<p>
<b>void pnm_freepamarray(</b>
<b>tuple **</b><i>tuplearray</i><b>,</b>
<b>struct pam *</b><i>pamP</i><b>);</b>
<p>
<b>void pnm_freepamrow(</b>
<b>tuple *</b><i>tuplerow</i><b>);</b>
<p>
<b>tuple * allocpamtuple(</b>
<b>struct pam *</b><i>pamP</i><b>);</b>
<p>
<b>void pnm_freepamtuple(</b>
<b>tuple </b><i>tuple</i>
<b>);</b>
<p>
<b>tuple * allocpamtuplen(</b>
<b>struct pam *</b><i>pamP</i><b>);</b>
<p>
<b>tuplen * pnm_allocpamrown(</b>
<b>struct pam *</b><i>pamP</i><b>);</b>
<p>
<b>void pnm_freepamrown(</b>
<b>tuplen *</b><i>tuplenrow</i><b>);</b>
<h4>Description</h4>
<p><b>pnm_allocpamtuple</b> allocates space for a tuple.
<b>pnm_freepamtuple</b> frees space allocated for a tuple.
<p><b>pnm_allocpamarray()</b> allocates space for an array of tuples.
<b>pnm_freepamarray()</b> frees an array space allocated by
<b>pnm_allocpamarray()</b> or <b>pnm_readpam()</b>.
<p><b>pnm_allocpamtuplen</b> is the same as <b>pnm_allocpamtuple</b>
except that it allocates space for a tuple in the normalized form.
<b>pnm_freepamtuplen</b> is similarly like <b>pnm_freepamtuple</b>.
<p><b>pnm_allocpamrow() </b> allocates space for a row of a PAM image,
in basic form. <b>pnm_freepamrow()</b> frees it.
<p><b>pnm_allocpamrown()</b> is the same as <b>pnm_allocpamrow()</b>
except that it allocates space for a PAM row in the normalized form.
<b>pnm_freepamrown()</b> is similarly like <b>pnm_freepamrow</b>.
<h3 id="reading">Reading Netpbm Files</h3>
<h4>Synopsis</h4>
<p>
<b>void pnm_readpaminit(</b>
<b>FILE *</b><i>file</i><b>,</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>int </b><i>size</i><b>);</b>
<p>
<b>void pnm_readpamrow(</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>tuple *</b><i>tuplerow</i><b>);</b>
<p>
<b>tuple ** pnm_readpam(</b>
<b>FILE *</b><i>file</i><b>,</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>int </b><i>size</i><b>);</b>
<p>
<b>void pnm_readpamrown(</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>tuplen *</b><i>tuplenrow</i><b>);</b>
<h4>Description</h4>
<p><b>pnm_readpaminit()</b> reads the header of a Netpbm image.
<p>See above for a general description of the <i>pamP</i> argument.
<p><b>pnm_readpaminit()</b> returns the information from the header in
the <b>*</b><i>pamP</i> structure. It does not require any members of
<b>*</b><i>pamP</i> through <b>tuple_type</b> to be set at invocation,
and sets all of those members. It expects all members after
<b>tuple_type</b> to be meaningful.
<p><i>size</i> is the size of the <b>*</b><i>pamP</i> structure as understood
by the program processing the image. <b>pnm_readpaminit()</b> does not
attempt to use or set any members of the structure beyond that. The point of
this argument is that the definition of the structure may change over time,
with additional fields being added to the end. This argument allows
<b>pnm_readpaminit</b> to distinguish between a new program that wants to
exploit the additional features and an old program that cannot (or a new
program that just doesn't want to deal with the added complexity). At a
minimum, this size must contain the members up through <b>tuple_type</b>. You
should use the <b>PAM_STRUCT_SIZE</b> macro to compute this argument.
E.g. <b>PAM_STRUCT_SIZE(tuple_type)</b>.
<b>PAM_STRUCT_SIZE</b> was introduced in Netpbm 10.23 (July 2004). In older
Netpbm, you can just use sizeof(), but then your code is <em>not</em> forward
compatible at the source code level with newer libnetpbm (because when you
compile it with newer libnetpbm header files, you'll be saying your structure
contains all the new members that have been invented, but your code doesn't
actually initialize them). So you might want to compute a proper size
yourself.
<p>The function expects to find the image file positioned to the start
of the header and leaves it positioned to the start of the raster.
<p><b>pnm_readpamrow()</b> reads a row of the raster from a Netpbm
image file. It expects all of the members of the <b>*pamP</b>
structure to be set upon invocation and does not modify any of them.
It expects to find the file positioned to the start of the row in
question in the raster and leaves it positioned just after it. It
returns the row as the array of tuples <i>tuplerow</i>, which must
already have its column pointers set up so that it forms a C
2-dimensional array. The leftmost tuple is Element 0 of this array.
<p><b>pnm_readpam()</b> reads an entire image from a PAM or PNM image
file and allocates the space in which to return the raster. It
expects to find the file positioned to the first byte of the image and
leaves it positioned just after the image.
<p><b>*</b><i>pamP</i> is the same as for <b>pnm_readpaminit()</b>.
<p>The return value is a newly allocated array of the rows of the image,
with the top row being Element 0 of the array. Each row is represented
as <b>pnm_readpamrow()</b> would return.
<p>The return value is also effectively a 3-dimensional C array of
samples, with the dimensions corresponding to the height, width, and
depth of the image, in that order.
<p><b>pnm_readpam()</b> combines the functions of
<b>pnm_allocpamarray()</b>, <b>pnm_readpaminit()</b>, and iterations
of <b>pnm_readpamrow()</b>. It may require more dynamic storage than
you can afford.
<p><b>pnm_readpamrown()</b> is like <b>pnm_readpamrow()</b> except that
it returns the row contents in normalized form (composed of normalized
tuples (<b>tuplen</b>) instead of basic form (<b>tuple</b>).
<p><b>pnm_readpaminit()</b> and <b>pnm_readpam</b> abort the program
with a message to Standard Error if the PAM or PNM image header is not
syntactically valid, including if it contains a number too large to be
processed using the system's normal data structures (to wit, a number
that won't fit in a C 'int').
<h3 id="writing">Writing Netpbm Files</h3>
<h4>Synopsis</h4>
<p>
<b>void pnm_writepaminit(</b>
<b>struct pam *</b><i>pamP</i><b>);</b>
<p>
<b>void pnm_writepamrow(</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>const tuple *</b><i>tuplerow</i><b>);</b>
<p>
<b>void pnm_writepam(</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>const tuple * const *</b><i>tuplearray</i><b>);</b>
<p>
<b>void pnm_writepamrown(</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>const tuplen *</b><i>tuplerown</i><b>);</b>
<p>
<b>void pnm_formatpamrow(</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>const tuple *</b><i>tuplerow</i>
<b>unsigned char * const </b><i>outbuf</i><b>,</b>
<b>unsigned int * const </b><i>rowSizeP</i>
<b>);</b>
<h4>Description</h4>
<p><b>pnm_writepaminit()</b> writes the header of a PAM or PNM image
and computes some of the fields of the pam structure.
<p>See above for a description of the <i>pamP</i> argument.
<p>The following members of the <b>*</b><i>pamP</i> structure must be
set upon invocation to tell the function how and what to write.
<b>size</b>, <b>len</b>, <b>file</b>, <b>format</b>, <b>height</b>,
<b>width</b>, <b>depth</b>, <b>maxval</b>. Furthermore, if
<b>format</b> is <b>PAM_FORMAT</b>, <b>tuple_type</b> must be set and
if <b>format</b> is <em>not</em> <b>PAM_FORMAT</b>, <b>plainformat</b>
must be set.
<p><b>pnm_writepaminit()</b> sets the <b>bytes_per_sample</b> member based on
the information supplied.
<p><b>pnm_writepamrow()</b> writes a row of the raster into a PAM or
PNM image file. It expects to find the file positioned where the row
should start and leaves it positioned just after the row. The
function requires all the elements of <b>*</b><i>pamP</i> to be set
upon invocation and doesn't modify them.
<p><i>tuplerow</i> is an array of tuples representing the row. The
leftmost tuple is Element 0 of this array.
<p><b>pnm_writepam()</b> writes an entire PAM or PNM image to a PAM or
PNM image file. It expects to find the file positioned to where the
image should start and leaves it positioned just after the image.
<p>The members of the <b>*</b><i>pamP</i> structure that must be set up
invocation, and their meanings, is the same as for <b>pnm_writepaminit</b>.
<p><b>pnm_writepam()</b> sets the <b>bytes_per_sample</b> member based on the
information supplied.
<p><i>tuplearray</i> is an array of rows such that you would pass to
<b>pnm_writepamrow()</b>, with the top row being Element 0 of the
array.
<p><b>pnm_writepam()</b> combines the functions of
<b>pnm_writepaminit()</b>, and iterations of <b>pnm_writepamrow()</b>.
Its raster input may be more storage than you can afford.
<p><b>pnm_writepamrown()</b> is like <b>pnm_writepamrow()</b> except that
it takes the row contents in normalized form (composed of normalized
tuples (<b>tuplen</b>) instead of basic form (<b>tuple</b>).
<p><b>pnm_formatpamrow()</b> is like <b>pnm_writepamrow()</b>, except
that instead of writing a row to a file, it places the same bytes that
would go in the file in a buffer you supply. There isn't an equivalent
function to construct an image header; i.e. there is no analog to
<b>pnm_writepaminit()</b>. But the header format, particularly for
PAM, is so simple that you can easily build it yourself with standard
C library string functions.
<p><b>pnm_formatpamrow()</b> was new in Netpbm 10.25 (October 2004).
<h3 id="transform">Transforming Pixels</h3>
<h4>Synopsis</h4>
<p>
<b>void pnm_YCbCrtuple(</b>
<b>tuple </b><i>tuple</i><b>,</b>
<b>double *</b><i>YP</i><b>,</b>
<b>double *</b><i>CrP</i><b>,</b>
<b>double *</b><i>CbP</i><b>);</b>
<p>
<b>void pnm_YCbCr_to_rgbtuple(</b>
<b>const struct pam * const </b><i>pamP</i><b>,</b>
<b>tuple const </b><i>tuple</i><b>,</b>
<b>double const </b><i>Y</i><b>,</b>
<b>double const </b><i>Cb</i><b>,</b>
<b>double const </b><i>Cr</i><b>,</b>
<b>int * const </b><i>overflowP</i><b>);</b>
<p>
<b>extern double pnm_lumin_factor[3];</b>
<p>
<b>void pnm_normalizetuple(</b>
<b>struct pam * const </b><i>pamP</i><b>,</b>
<b>tuple const </b><i>tuple</i><b>,</b>
<b>tuplen const </b><i>tuplen</i><b>);</b>
<p>
<b>void pnm_unnormalizetuple(</b>
<b>struct pam * const </b><i>pamP</i><b>,</b>
<b>tuplen const </b><i>tuplen</i><b>,</b>
<b>tuple const </b><i>tuple</i><b>);</b>
<p>
<b>void pnm_normalizeRow(</b>
<b>struct pam * const </b><i>pamP</i><b>,</b>
<b>const tuple * const </b><i>tuplerow</i><b>,</b>
<b>pnm_transformMap * const </b><i>transform</i><b>,</b>
<b>tuplen * const </b><i>tuplenrow</i><b>);</b>
<p>
<b>void pnm_unnormalizeRow(</b>
<b>struct pam * const </b><i>pamP</i><b>,</b>
<b>const tuplen * const </b><i>tuplenrow</i><b>,</b>
<b>pnm_transformMap * const </b><i>transform</i><b>,</b>
<b>tuple * const </b><i>tuplerow</i><b>);</b>
<p>
<b>void pnm_gammarown(</b>
<b>struct pam * const </b><i>pamP</i><b>,</b>
<b>tuplen * const </b><i>row</i><b>);</b>
<p>
<b>void pnm_ungammarown(</b>
<b>struct pam * const </b><i>pamP</i><b>,</b>
<b>tuplen * const </b><i>row</i><b>);</b>
<p>
<b>void pnm_applyopacityrown(</b>
<b>struct pam * const </b><i>pamP</i><b>,</b>
<b>tuplen * const </b><i>tuplenrow</i><b>);</b>
<p>
<b>void pnm_unapplyopacityrown(</b>
<b>struct pam * const </b><i>pamP</i><b>,</b>
<b>tuplen * const </b><i>tuplenrow</i><b>);</b>
<p>
<b>pnm_transformMap * pnm_creategammatransform(</b>
<b>const struct pam * const </b><i>pamP</i><b>);</b>
<p>
<b>void pnm_freegammatransform(</b>
<b>const pnm_transformMap * const </b><i>transform</i><b>,</b>
<b>const struct pam * const </b><i>pamP</i><b>);</b>
<p>
<b>pnm_transformMap * pnm_createungammatransform(</b>
<b>const struct pam * const </b><i>pamP</i><b>);</b>
<p>
<b>void pnm_freeungammatransform(</b>
<b>const pnm_transformMap * const </b><i>transform</i><b>,</b>
<b>const struct pam * const </b><i>pamP</i><b>);</b>
<h4>Description</h4>
<p><b>pnm_YCbCrtuple()</b> returns the Y/Cb/Cr luminance/chrominance
representation of the color represented by the input tuple, assuming
that the tuple is an RGB color representation (which is the case if it
was read from a PPM image). The output components are based on the
same scale (maxval) as the input tuple, but are floating point
nonetheless to avoid losing information because of rounding. Divide them
by the maxval to get normalized [0..1] values.
<p><b>pnm_YCbCr_to_rgbtuple()</b> does the reverse. <i>pamP</i>
indicates the maxval for the returned <i>tuple</i>, and the <i>Y</i>,
<i>Cb</i>, and <i>Cr</i> arguments are of the same scale.
<p>It is possible for <i>Y</i>, <i>Cb</i>, and <i>Cr</i> to describe a
color that cannot be represented in RGB form. In that case,
<b>pnm_YCbCr_to_rgbtuple()</b> chooses a color as close as possible
(by clipping each component to 0 and the maxval) and sets *overflowP
true. It otherwise sets *overflowP false.
<b>pnm_lumin_factor[]</b> is the factors (weights) one uses to compute
the intensity of a color (according to some standard -- I don't know
which). pnm_lumin_factor[0] is for the red component, [1] is for the
green, and [2] is for the blue. They add up to 1.
<p><b>pnm_gammarown()</b> and <b>pnm_ungammarown()</b> apply and unapply
gamma correction to a row of an image using the same transformation as
<a href="libpm.html#gamma"><b>pm_gamma709()</b> and <b>pm_ungamma709()</b></a>.
Note that these operate on a row of normalized tuples (<b>tuplen</b>,
not <b>tuple</b>).
<p><b>pnm_applyopacityrown()</b> reduces the intensity of samples in accordance
with the opacity plane of an image. The opacity plane, if it exists, tells
how much of the light from that pixel should show when the image is composed
with another image. You use <b>pnm_applyopacityrown()</b> in preparation for
doing such a composition. For example, if the opacity plane says that the
left half of the image is 50% opaque and the right half 100% opaque,
<b>pnm_applyopacityrown()</b> will reduce the intensity of each sample of each
tuple (pixel) in the left half of the image by 50%, and leave the rest
alone.
<p>If the image does not have an opacity plane (i.e. its tuple type is
not one that <b>libnetpbm</b> recognizes as having an opacity plane),
<b>pnm_applyopacityrown()</b> does nothing (which is the same as assuming
opacity 100%). The tuple types that <b>libnetpbm</b> recognizes as
having opacity are <b>RGB_ALPHA</b> and <b>GRAYSCALE_ALPHA</b>.
<p><b>pnm_unapplyopacityrown()</b> does the reverse. It assumes the
intensities are already reduced according to the opacity plane, and
raises back to normal.
<p><b>pnm_applyopacityrown()</b> works on (takes as input and produces as
output) <em>normalized</em>, <em>intensity-proportional</em> tuples.
That means you will typically read the row from the image file with
<b>pnm_readpamrown()</b> and then gamma-correct it with
<b>pnm_ungammarown()</b>, and then do <b>pnm_applyopacityrown()</b>. You
then manipulate the row further (perhaps add it with other rows you've
processed similarly), then do <b>pnm_unapplyopacityrown()</b>, then
<b>pnm_gammarown()</b>, then <b>pnm_writepamrown()</b>.
<p><b>pnm_applyopacityrown()</b> and <b>pnm_unapplyopacityrown()</b>
were new in Netpbm 10.25 (October 2004).
<p><b>pnm_normalizetuple()</b> and <b>pnm_unnormalizetuple()</b>
convert between a <b>tuple</b> data type and a <b>tuplen</b> data
type. The former represents a sample value using the same unsigned
integer that is in the PAM image, while the latter represents a
sample value as a number scaled by the maxval to the range 0..1.
I.e. <b>pnm_normalizetuple()</b> divides every sample value by the
maxval and <b>pnm_unnormalizetuple()</b> multiples every sample by the
maxval.
<p><b>pnm_normalizeRow()</b> and <b>pnm_unnormalizeRow()</b> do the same
thing on an entire tuple row, but also have an extra feature: You can
specify a transform function to be applied in addition. Typically, this
is a gamma transform function. You can of course more easily apply your
transform function separately from normalizing, but doing it all at once
is usually way faster. Why? Because you can use a lookup table that
is indexed by an integer on one side and produces a floating point number
on the other. To do it separately, you'd either have to do floating point
arithmetic on the normalized value or do the transform on the integer
values and lose a lot of precision.
<p>If you don't have any transformation to apply, just specify
<b>NULL</b> for the <i>transform</i> argument and the function will
just normalize (i.e. divide or multiply by the maxval).
<p>Here's an example of doing a transformation. The example composes
two images together, something that has to be done with intensity-linear
sample values.
<pre>
pnm_transformMap * const transform1 = pnm_createungammatransform(&inpam1);
pnm_transformMap * const transform2 = pnm_createungammatransform(&inpam2);
pnm_transformMap * const transformOut = pnm_creategammatransform(&outpam);
pnm_readpamrow(&inpam1, inrow1);
pnm_readpamrow(&inpam2, inrow2);
pnm_normalizeRow(&inpam1, inrow1, transform1, normInrow1);
pnm_normalizeRow(&inpam2, inrow2, transform2, normInrow2);
for (col = 0; col < outpam.width; ++col)
normOutrow[col] = (normInrow1[col] + normInrow2[col])/2;
pnm_unnormalizeRow(&outpam, normOutrow, transformOut, outrow);
pnm_writepamrow(&outpam, outrow);
</pre>
<p>To specify a transform, you must create a special
<b>pnm_transformMap</b> object and pass it as the <i>transform</i>
argument. Typically, your transform is a gamma transformation because
you want to work in intensity-proportional sample values and the PAM
image format uses gamma-adjusted ones. In that case, just use
<b>pnm_creategammatransform()</b> and
<b>pnm_createungammatransform()</b> to create this object and don't
worry about what's inside it.
<p><b>pnm_creategammatransform()</b> and
<b>pnm_createungammatransform()</b> create objects that you use with
<b>pnm_normalizeRow()</b> and <b>pnm_unnormalizeRow()</b> as described
above. The created object describes a transform that applies or
reverses the ITU-R Recommendation BT.709 gamma adjustment that is used
in PAM visual images and normalizes or unnormalizes the sample values.
<b>pnm_freegammatransform()</b> and <b>pnm_freeungammatransform()</b>
destroy the objects.
<h3 id="colorspec">Color specification</h3>
<p>These are functions you use that deal with names or identifiers for colors.
<h4>Synopsis</h4>
<p>
<b>tuple pnm_parsecolor(</b>
<b>const char * </b><i>colorname</i><b>,</b>
<b>sample </b><i>maxval</i>
<b>);</b>
<p>
<b>tuple pnm_parsecolor2(</b>
<b>const char * </b><i>colorname</i><b>,</b>
<b>sample </b><i>maxval</i><b>,</b>
<b>int </b><i>closeOk</i>
<b>);</b>
<p>
<b>tuplen pnm_parsecolorn(</b>
<b>const char * </b><i>colorname</i>
<b>);</b>
<p>
<b>pnm_colorspec_rgb_integer(</b>
<b>struct pam * </b><i>pamP</i><b>,</b>
<b>tuple </b><i>color</i><b>,</b>
<b>sample </b><i>maxval</i>
<b>);</b>
<p>
<b>pnm_colorspec_rgb_norm(</b>
<b>struct pam * </b><i>pamP</i><b>,</b>
<b>tuple </b><i>color</i>
<b>unsigned int </b><i>digitCt</i>
<b>);</b>
<p>
<b>pnm_colorspec_rgb_x11(</b>
<b>struct pam * </b><i>pamP</i><b>,</b>
<b>tuple </b><i>color</i><b>,</b>
<b>unsigned int </b><i>hexDigitCt</i>
<b>);</b>
<p>
<b>pnm_colorspec_dict(</b>
<b>struct pam * </b><i>pamP</i><b>,</b>
<b>tuple </b><i>color</i>
<b>);</b>
<p>
<b>pnm_colorspec_dict_close(</b>
<b>struct pam * </b><i>pamP</i><b>,</b>
<b>tuple </b><i>color</i>
<b>);</b>
<h4>Description</h4>
<p>These functions deal with color names, either interpreting a given color
name as a color or determining a color name for a given color. Examples of
color names are "pink" and "rgbi:1.0/0.5/0.25". See
<a href="#colorname">Color name</a> for a description of the various
ways Netpbm names colors.
<p><b>pnm_parsecolor</b>, <b>pnm_parsecolor2</b>, and <b>pnm_parsecolorn</b>
return a color in the conventional form used by <b>libnetpbm</b> to
represent a color, given a human-intelligible name for the color such
as "red" or "rgbi:1.0/0.5/0.25".
<p><b>pnm_parsecolorn</b> returns a normalized tuple (type <b>tuplen</b>),
whereas <b>pnm_parsecolor</b> and <b>pnm_parsecolor2</b> return a tuple that
uses an integer scale with a specified maxval.
<p>When you use an integer scale, only certain discrete colors can be
represented, so the functions may round. For example, "wheat" which
is 245/222/179 with maxval 255, cannot be represented exactly with maxval 15,
so if you call <b>pnm_parsecolor</b> to produce a wheat color tuple with
maxval 15, you get 14/13/11, which is not quite the same.
With <b>pnm_parsecolor2</b>, you get a warning message to Standard Error when
such rounding occurs, unless you specify <i>closeOk</i> = true.
<b>pnm_parsecolor</b> never warns about this.
<p><b>pnm_colorspec_rgb_integer</b> returns the color specification for the
color <i>color</i> in integer/maxval form like "rgb-255:0/128/254".
<i>maxval</i> is the maxval to be used in the color specification (255 in this
example);
<p><b>pnm_colorspec_rgb_norm</b> returns the color specification for the
color <i>color</i> in normalized form like "rgbi:0.000/0.052/0.996".
<i>digitCt</i> is the number of digits after the decimal point (3 in this
example). The function rounds and zero-fills as necessary.
<p><b>pnm_colorspec_rgb_x11</b> returns the color specification for the
color <i>color</i> in X11 form like "rgb:00/80/fe".
<i>hexDigitCt</i> is the number of hexadecimal digits to use for each
component (2 in this example). The function rounds and zero-fills as
necessary.
<p><b>pnm_colorspec_dict</b> returns the color specification for the
color <i>color</i> as name such as "pink" from the color dictionary.
If the color is not in the dictionary, including where the function does not
find a color dictionary file, the return value is null.
<p><b>pnm_colorspect_dict_close</b> is the same as <b>pnm_colorspec_dict</b>
except that when the color is not in the dictionary, it returns the closest
color to it that <em>is</em> in the dictionary. As an exception, if the
function cannot find a color dictionary file or the file it finds does not
contain even a single color definition, the function returns a null string.
<h5 id="colorname">Color Name</h5>
<p>Color names in Netpbm are ASCII text in one of the formats described
below. This is what you use for the <i>colorname</i> argument of functions
such as <b>pnm_parsecolor</b> and is the return value of functions such as
<b>pnm_colorspec_rgb_norm</b>.
<ul>
<li>a name, as defined in the <a href="libppm.html#dictionary">system color dictionary
</a>.
<li> An X11-style hexadecimal specifier:
<span style="font-family: monospace">rgb:<i>r</i>/<i>g</i>/<i>b</i></span>,
where <i>r</i>, <i>g</i>, and
<i>b</i> are each 1- to 4-digit hexadecimal numbers. For each, the maxval is
the maximum number that can be represented in the number of hexadecimal digits
given. Example: <span style="font-family: monospace">rgb:01/ff/8000</span>
specifies 1/255 red intensity, maximum green intensity, and about half blue
intensity.
<li> An X11-style decimal specifier:
<span style="font-family: monospace">rgbi:<i>r</i>/<i>g</i>/<i>b</i></span>,
where <i>r</i>, <i>g</i>, and <i>b</i> are floating point numbers from 0 to 1.
Example: <span style="font-family: monospace">rgbi:1.0/0.5/.25</span>.
<li><span style="font-family:monospace">rgb-<i>maxval</i>:<i>r</i>/<i>g</i>/<i>b</i></span>, where <i>r</i>, <i>g</i>, and <i>b</i> are decimal integers
from 0 to <i>maxval</i>. Example: <span style="font-family: monospace">
rgb-255:255/128/64</span>. <i>maxval</i> can be from 1 to 65535.
<p>
This format was new in Netpbm 10.83 (June 2018).
<li>an old-X11-style hexadecimal triple: <span style="font-family: monospace">
#rgb</span>, <span style="font-family: monospace">#rrggbb</span>,
<span style="font-family: monospace">#rrrgggbbb</span>, or
<span style="font-family: monospace">#rrrrggggbbbb</span>.
<li>A triplet of decimal floating point numbers from 0.0 to 1.0, representing
red, green, and blue intensities respectively, separated by commas.
Example: <span style="font-family: monospace">1.0,0.5,.25</span>. This is for
backwards compatibility; it was in use before MIT came up with the similar and
preferred rgbi style).
</ul>
<p>If <i>colorname</i> does not conform to any of these formats, including the
case that it is a name, but is not in the system color dictionary,
<b>pnm_parsecolor()</b> <a href="liberror.html">throws an error</a>.
<h3 id="misc">Miscellaneous</h3>
<h4>Synopsis</h4>
<p>
<b>void pnm_checkpam(</b>
<b>struct pam *</b><i>pamP</i><b>,</b>
<b>const enum pm_check_type </b><i>check_type</i><b>,</b>
<b>enum pm_check_code *</b><i>retvalP</i><b>);</b>
<p>
<b>void pnm_nextimage(</b>
<b>FILE *</b><i>file</i><b>,</b>
<b>int * const </b><i>eofP</i><b>);</b>
<h4>Description</h4>
<p><b>pnm_checkpam()</b> checks for the common file integrity error
where the file is the wrong size to contain the raster, according to
the information in the header.
<p><b>pnm_nextimage()</b>positions a Netpbm image input file to the
next image in it (so that a subsequent <b>pnm_readpaminit()</b> reads
its header).
<hr>
<h2 id="toc">Table Of Contents</h2>
<ul>
<li><a href="#types">Types</a>
<ul>
<li><a href="#pamstruct">struct pam</a>
</ul>
<li><a href="#macros">Macros</a>
<li><a href="#functions">Functions</a>
<ul>
<li><a href="#memory">Memory Management</a>
<li><a href="#reading">Reading Netpbm Files</a>
<li><a href="#writing">Writing Netpbm Files</a>
<li><a href="#transform">Transforming Pixels</a>
<li><a href="#colorspec">Color Specification</a>
<li><a href="#misc">Miscellaneous</a>
</ul>
</ul>
</body>
</html>
|