summary refs log tree commit diff
path: root/libppm.html
blob: a37ac6953cbd075b27d910eff778c2d5921f1c78 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
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
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.3//EN">
<html>
<head>
<title>User manual for old ppm functions</title>
<meta name="manual_section" content="3">
</head>
<body>
<h1>libppm</h1>
Updated: 31 March 2024
<br>
<a href="#index">Table Of Contents</a>

<h2>NAME</h2>

libppm - functions for PPM programs

<h2 id="synopsis">SYNOPSIS</h2>

<b>#include &lt;netpbm/ppm.h&gt;</b>

<p>
<b>void ppm_init(</b><b>int *</b> <i>argcP</i><b>,</b>
  <b>char *</b> <i>argv</i><b>[]</b><b>);</b>

<p>
<b>pixel ** ppm_allocarray(</b>

<b>int </b><i>cols</i><b>,</b><b>int</b> <i>rows</i><b>);</b>

<p>
<b>pixel * ppm_allocrow(</b><b>int</b> <i>cols</i><b>);</b>

<p>
<b>void ppm_freearray(</b><b>pixel **</b> <i>pixels</i><b>,</b>
  <b>int</b> <i>rows</i><b>);</b>

<p>
<b>void ppm_freerow(</b><b>pixel *</b> <i>pixelrow</i><b>);</b>

<p>
<b>void ppm_readppminit(</b><b>FILE *</b> <i>fp</i><b>,</b>
  <b>int *</b> <i>colsP</i><b>,</b>
  <b>int *</b> <i>rowsP</i><b>,</b>

<b>pixval *</b> <i>maxvalP</i><b>,</b><b>int *</b> <i>formatP</i><b> );</b>

<p>
<b>void ppm_readppmrow(</b><b>FILE *</b><i>fp</i><b>,</b>
  <b>pixel *</b> <i>pixelrow</i><b>,</b>
  <b>int </b><i>cols</i><b>,</b>
  <b>pixval </b><i>maxval</i><b>,</b>
  <b>int </b><i>format</i><b>);</b>

<p>
<b>pixel ** ppm_readppm(</b><b>FILE *</b> <i>fp</i><b>,</b>
  <b>int *</b> <i>colsP</i><b>,</b>
  <b>int *</b> <i>rowsP</i><b>,</b>
  <b>pixvalP *</b> <i>maxvalP</i><b>);</b>

<p>
<b>void ppm_writeppminit(</b><b>FILE * <i>fp</i>,</b>
  <b>int</b> <i>cols</i><b>,</b>
  <b>int</b> <i>rows</i><b>,</b>
  <b>pixval</b> <i>maxval</i><b>,</b>
  <b>int</b> <i>forceplain</i><b>);</b>

<p>
<b>void ppm_writeppmrow(</b><b>FILE *</b> <i>fp</i><b>,</b>
  <b>pixel *</b> <i>pixelrow</i><b>,</b>
  <b>int</b> <i>cols</i><b>,</b>
  <b>pixval</b> <i>maxval</i><b>,</b>
  <b>int</b> <i>forceplain</i><b>);</b>

<p>
<b>void ppm_writeppm(</b><b>FILE *</b> <i>fp</i><b>,</b>
  <b>pixel **</b> <i>pixels</i><b>,</b>
  <b>int</b> <i>cols</i><b>,</b>
  <b>int</b> <i>rows</i><b>,</b>
  <b>pixval</b> <i>maxval</i><b>,</b>
  <b>int</b> <i>forceplain</i><b>);</b>

<p>
<b>void ppm_writeppm(</b><b>FILE *</b> <i>fp</i><b>,</b>
  <b>pixel **</b> <i>pixels</i><b>,</b>
  <b>int</b> <i>cols</i><b>,</b>
  <b>int</b> <i>rows</i><b>,</b>
  <b>pixval</b> <i>maxval</i><b>,</b>
  <b>int</b> <i>forceplain</i><b>);</b>

<p>
<b>void ppm_nextimage(</b><b>FILE *</b> <i>file</i><b>,</b>
  <b>int * const</b> <i>eofP</i><b>);</b>

<p>
<b>void ppm_check(</b><b>FILE *</b> <i>file</i><b>,</b>
  <b>const enum pm_check_type</b> <i>check_type</i><b>,</b>
  <b>const int</b> <i>format</i><b>,</b>
  <b>const int</b> <i>cols</i><b>,</b>
  <b>const int</b> <i>rows</i><b>,</b>
  <b>const int</b> <i>maxval</i><b>,</b>

<br>

<b>enum pm_check_code * const</b> <i>retval</i><b>);</b>

<p>
<b>typedef ... pixel;</b>

<b>typedef ... pixval;</b>

<p>
<b>#define PPM_MAXMAXVAL ...</b>

<p>
<b>#define PPM_OVERALLMAXVAL ...</b>

<p>
<b>#define PPM_FORMAT ...</b>

<p>
<b>#define RPPM_FORMAT ...</b>

<p>
<b>#define PPM_TYPE PPM_FORMAT</b>

<p>
<b>#define</b> <b>PPM_FORMAT_TYPE(</b><i>format</i><b>)</b> <b>...</b>

<p>
<b>pixval PPM_GETR(pixel</b> <i>p</i><b>)</b>

<p>
<b>pixval PPM_GETG(pixel</b> <i>p</i><b>)</b>

<p>
<b>pixval PPM_GETB(pixel</b> <i>p</i><b>)</b>

<p>
<b>void PPM_ASSIGN(pixel</b> <i>p</i><b>,</b>
  <b>pixval</b> <i>red</i><b>,</b>
  <b>pixval</b> <i>grn</i><b>,</b>
  <b>pixval</b> <i>blu</i><b>)</b>

<p>
<b>int PPM_EQUAL(pixel</b> <i>p</i><b>,</b>
  <b>pixel</b> <i>q</i><b>)</b>

<p>
<b>int PPM_ISGRAY(pixel</b> <i>p</i><b>)</b>

<p>
<b>void</b>
  <b>PPM_DEPTH(pixel</b> <i>newp</i><b>,</b>
  <b>pixel</b> <i>p</i><b>,</b>
  <b>pixval</b> <i>oldmaxval</i><b>,</b>
  <b>pixval</b> <i>newmaxval</i><b>)</b>

<p>
<b>pixel ppm_parsecolor(char *</b> <i>colorname</i><b>,</b>
   <b>pixval</b> <i>maxval</i><b>)</b>

<p>
<b>pixel ppm_parsecolor2(</b>
<b>char *</b> <i>colorname</i><b>,</b>
<b>pixval</b> <i>maxval</i><b>,</b>
<b>int</b> <i>closeOk</i>
<b>)</b>

<p>
<b>char * ppm_colorname(pixel *</b> <i>colorP</i><b>,</b>
  <b>pixval</b> <i>maxval</i><b>,</b>
  <b>int</b> <i>hexok</i><b>)</b>

<p>
<b>void ppm_readcolornamefile(</b>
  <b>const char *</b><i>fileName</i>, 
  <b>int</b> <i>mustOpen</i>,
  <b>colorhash_table *</b> <i>chtP</i>, 
  <b>const char ***</b> <i>colornamesP</i>
  <b>)</b>


<h2 id="description">DESCRIPTION</h2>

<p>These library functions are part of <a href="index.html">Netpbm</a>.

<h3 id="types">TYPES AND CONSTANTS</h3>

Each <b>pixel</b> contains three <b>pixval</b>s, each of which should
contain only the values between <b>0</b> and <b>PPM_MAXMAXVAL</b>.


<h3 id="manipulating_pixels">MANIPULATING PIXELS</h3>

<p>The macros <b>PPM_GETR</b>, <b>PPM_GETG</b>, and <b>PPM_GETB</b>
retrieve the red, green, or blue sample, respectively, from the given
pixel.

<p>The <b>PPM_ASSIGN</b> macro assigns the given values to the red,
green, and blue samples of the given pixel.

<p>The <b>PPM_EQUAL</b> macro tests two pixels for equality.

<p>The <b>PPM_ISGRAY</b> macro tests a pixel for being gray.  It
returns true if and only if the color of pixel <i>p</i> is black,
white, or gray.

<p>The <b>PPM_DEPTH</b> macro scales the colors of pixel <i>p</i>
according the old and new maxvals and assigns the new values to
<i>newp</i>.  It is intended to make writing ppmtowhatever easier.

<p>The <b>PPM_LUMIN</b>, <b>PPM_CHROM_R</b>, and <b>PPM_CHROM_B</b>
macros determine the luminance, red chrominance, and blue chrominance,
respectively, of the pixel <i>p</i>.  The scale of all these values is
the same as the scale of the input samples (i.e. 0 to maxval for
luminance, -maxval/2 to maxval/2 for chrominance).

<p>Note that the macros do it by floating point multiplication.  If
you are computing these values over an entire image, it may be
significantly faster to do it with multiplication tables instead.
Compute all the possible products once up front, then for each pixel,
just look up the products in the tables.

<h3 id="initialization">INITIALIZATION</h3>

<p><b>ppm_init()</b> is obsolete (at least since Netpbm 9.25 (March 2002)).
Use <a href="libpm.html#initialization"><b>pm_proginit()</b></a> instead.

<p><b>ppm_init()</b> is identical to <b>pm_proginit</b>.


<h3 id="memorymanagement">MEMORY MANAGEMENT</h3>

<b>ppm_allocarray()</b> allocates an array of pixels.

<p><b>ppm_allocrow()</b> allocates a row of the given number of
pixels.

<p><b>ppm_freearray()</b> frees the array allocated with
<b>ppm_allocarray()</b> containing the given number of rows.

<p><b>ppm_freerow()</b> frees a row of pixelss allocated with
<b>ppm_allocrow()</b>.

<h3 id="readingfiles">READING FILES</h3>

<p>If a function in this section is called on a PBM or PGM format
file, it translates the PBM or PGM file into a PPM file on the fly and
functions as if it were called on the equivalent PPM file.  The
<i>format</i> value returned by <b>ppm_readppminit()</b> is, however,
not translated.  It represents the actual format of the PBM or PGM
file.

<p><b>ppm_readppminit()</b> reads the header of a PPM file, returning
all the information from the header and leaving the file positioned
just after the header.

<p><b>ppm_readppmrow()</b> reads a row of pixels into the
<i>pixelrow</i> array.  <i>format</i>, <i>cols</i>, and <i>maxval</i>
are the values returned by <b>ppm_readppminit()</b>.

<p><b>ppm_readppm()</b> reads an entire PPM image into memory,
returning the allocated array as its return value and returning the
information from the header as <i>rows</i>, <i>cols</i>, and
<i>maxval</i>.  This function combines <b>ppm_readppminit()</b>,
<b>ppm_allocarray()</b>, and <b>ppm_readppmrow()</b>.


<h3 id="writingfiles">WRITING FILES</h3>

<b>ppm_writeppminit()</b> writes the header for a PPM file and leaves
it positioned just after the header.

<p><i>forceplain</i> is a logical value that tells
<b>ppm_writeppminit() </b> to write a header for a plain PPM format
file, as opposed to a raw PPM format file.

<p><b>ppm_writeppmrow()</b> writes the row <i>pixelrow</i> to a PPM
file.  For meaningful results, <i>cols</i>, <i>maxval</i>, and
<i>forceplain</i> must be the same as was used with
<b>ppm_writeppminit()</b>.

<p><b>ppm_writeppm()</b> write the header and all data for a PPM
image.  This function combines <b>ppm_writeppminit()</b> and
<b>ppm_writeppmrow()</b>.

<h3 id="miscellaneous">MISCELLANEOUS</h3>

<p><b>ppm_nextimage()</b> positions a PPM input file to the next image
in it (so that a subsequent <b>ppm_readppminit()</b> reads its
header).

<p><b>ppm_nextimage()</b> is analogous to <b>pbm_nextimage()</b>, but
works on PPM, PGM, and PBM files.

<p><b>ppm_check() </b> checks for the common file integrity error
where the file is the wrong size to contain all the image data.

<p><b>ppm_check() </b> is analogous to <b>pbm_check()</b>, but works
on PPM, PGM, and PBM files.


<h3 id="color">COLOR</h3>

<h4 id="luminance">Luminance, Chrominance (YcbCr)</h4>

<pre>
<code>
    float PPM_LUMIN(pixel p);
    float PPM_CHROM_B(pixel p);
    float PPM_CHROM_R(pixel p);
</code>
</pre>

<p><b>PPM_LUMIN</b> takes a <b>pixel</b> as an argument and returns
the luminance of that pixel, with the same maxval as the pixel
(e.g. if the pixel's maxval is 255, a <b>PPM_LUMIN</b> value of 255
means fully luminant).

<p><b>PPM_CHROM_B</b> and <b>PPM_CHROM_R</b> are similar, for the red
and blue chrominance values.


<pre>
<code>
    pixel
    ppm_color_from_ycbcr(unsigned int y, 
                         int          cb, 
                         int          cr);
</code>
</pre>

<p><b>ppm_color_from_ycbcr()</b> converts in the other direction.
Given luminance and chrominance, it returns a pixel value.

<h4 id="hsv">Hue, Saturation, Value (HSV)</h4>

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

<pre>
<code>
    pixel
    ppm_color_from_hsv(struct hsv const hsv,
                       pixval     const maxval);
</code>
</pre>

<pre>
<code>
    struct hsv
    ppm_hsv_from_color(pixel  const color,
                       pixval const maxval);
</code>
</pre>

<p>These convert a color between from <b>pixel</b> (RGB) form and HSV.

<pre>
<code>
    pixval
    ppm_saturation(pixel  const p,
                   pixval const maxval);
</code>
</pre>

<p>This gives you the saturation of a color, as a pixval.  (e.g. if
the saturation of <i>p</i> is 50% and <i>maxval</i> is 100,
<b>ppm_saturation()</b> returns 50).


<h4 id="berlinkay">Berlin-Kay Color</h4>

<p>Brent Berlin and Paul Kay in 1969 did a study which identified
a set of 11 basic colors people universally recognize.  They are:

<ul>
<li>black
<li>gray
<li>white
<li>red
<li>orange
<li>yellow
<li>green
<li>blue
<li>violet
<li>purple
<li>brown
</ul>

<p>The <b>bk_color</b> type represents a color from this set:

<pre>
<code>
    typedef enum {
        BKCOLOR_BLACK = 0,
        BKCOLOR_GRAY,
        BKCOLOR_WHITE,
        BKCOLOR_RED,
        BKCOLOR_ORANGE,
        BKCOLOR_YELLOW,
        BKCOLOR_GREEN,
        BKCOLOR_BLUE,
        BKCOLOR_VIOLET,
        BKCOLOR_PURPLE,
        BKCOLOR_BROWN
    } bk_color;
</code>
</pre>

<p>You can use this as an index of an array, in which case you might also
want macro <b>BKCOLOR_COUNT</b>, which is the number of colors in the
set (11).

<p>To translate between the <b>bk_color</b> type and the English names
of the colors, use <b>ppm_bk_color_from_name()</b> and
<b>ppm_name_from_bk_color()</b>:

<pre>
<code>
    bk_color
    ppm_bk_color_from_name(const char * name);
    
    const char *
    ppm_name_from_bk_color(bk_color bkColor);
</code>
</pre>


<p><b>ppm_bk_color_from_color()</b> tells you to which Berlin-Kay color
a certain color is closest, by way of a fuzzy color matching algorithm:

<pre>
<code>
    bk_color
    ppm_bk_color_from_color(pixel  color,
                            pixval maxval);
</code>
</pre>

<p><i>maxval</i> is the maxval on which <i>color</i> is based.

<p><b>ppm_color_from_bk_color()</b> converts the opposite way: given
a Berlin-Kay color, it gives the color, in <b>pixel</b> form, that best
represents it.

<pre>
<code>
    pixel
    ppm_color_from_bk_color(bk_color bkColor,
                            pixval   maxval);
</code>
</pre>

<p><i>maxval</i> is the maxval on which the returned color is based.

<p>All of the facilities in this section were new in Netpbm 10.34
(June 2006).

<h3 id="colorname">COLOR NAMES</h3>

<h4 id="dictionary">System Color Dictionary</h4>

<p>Netpbm uses the system's X11 color dictionary (usually in
<b>/usr/lib/X11/rgb.txt</b>).  This is the same file the X Window
System typically uses to associate colors with their names.

<p>The color dictionary that Netpbm uses is in the file whose name is
the value of the <b>RGBDEF</b> environment variable.  If <b>RGBDEF</b>
is not set, Netpbm defaults to the first existing file from this list:

<ol>
<li><b>/usr/local/netpbm/rgb.txt</b>
<li><b>/usr/share/netpbm/rgb.txt</b>
<li><b>/etc/X11/rgb.txt</b>
<li><b>/usr/lib/X11/rgb.txt</b>
<li><b>/usr/openwinlib/rgb.txt</b>
<li><b>/usr/X11R6/lib/X11/rgb.txt</b>
</ol>

This is the default list; it can vary based on options used when Netbpm is
built.

<p>You can see the color names from a typical X11 color dictionary,
which is probably very close to what is on your system, along with the
colors, <a
href="http://people.csail.mit.edu/~jaffer/Color/x11.pdf">here</a>.  <a
href="http://people.csail.edu/~jaffer/Color/Dictionaries.html">This
website</a> shows a bunch of other versions you could use.

<p>Netpbm accepts color dictionaries that have multiple colors for a given
name and multiple names for a given color.  Entries in a color dictionary are
ordered, and when Netpbm looks up a color name, it ignores all but the first
entry for that name, and when it looks up a color, it ignores all but the
first entry for that color.
  
<p>Netpbm is packaged with a color dictionary.  A standard Netpbm
installation installs this file as "misc/rgb.txt" in the Netpbm
directory.  This color dictionary has colors from everywhere the
Netpbm maintainer could find them, and is a superset of XFree 86's
color dictionary.

<h4 id="ppm_parsecolor">ppm_parsecolor</h4>

<p><b>ppm_parsecolor()</b> interprets a color specification and returns a
pixel of the color that it indicates.  It is the same as
<a href="libnetpbm_image.html#colorname">pnm_parsecolor</a>, except that it
returns a <b>pixel</b> instead of a <b>tuple</b>.

<h4 id="ppm_parsecolor2">ppm_parsecolor2</h4>

<p><b>ppm_parsecolor2()</b> interprets a color specification and returns a
pixel of the color that it indicates and warns about rounding.  It is the same
as <a href="libnetpbm_image.html#colorname">pnm_parsecolor2</a>, except
that it returns a <b>pixel</b> instead of a <b>tuple</b>.

<h4 id="ppm_colorname">ppm_colorname</h4>

<p><b>ppm_colorname()</b> returns a string that describes the color
of the given pixel.  If a <a href="#dictionary">system color dictionary</a>
is available and the color appears in it, <b>ppm_colorname()</b>
returns the name of the color from the file.  If the color does not
appear in a system color dictionary and <i>hexok</i> is true,
<b>ppm_colorname()</b> returns a hexadecimal color specification
triple (#rrggbb).  If a system color dictionary is available but the
color does not appear in it and <i>hexok</i> is false,
<b>ppm_colorname()</b> returns the name of the closest matching color
in the color file.  Finally, if there is no system color dictionary
available and <i>hexok</i> is false, <b>ppm_colorname()</b> fails and
<a href="liberror.html#error">throws an error</a>.

<p>The string returned is in static libppm library storage which is
overwritten by every call to <b>ppm_colorname()</b>.


<h4 id="ppm_readcolornamefile">ppm_readcolornamefile</h4>

<p><b>ppm_readcolornamefile()</b> reads the entire contents of the color
dictionary in the file named <i>fileName</i> into data structures you
can use to access it easily.

<p>The function returns all the color names as an array of
null-terminated strings.  It mallocs the space for this array and
returns its address at <i>colornamesP</i>.
<b>(*colornamesP)[</b><i>i</i><b>]</b> is the address of the first
character in the null-terminated string that is the name of the
<i>i</i>th color in the dictionary.

<p>The function also returns a <b>colorhash_table</b> (see <a
href="#colorindex">COLOR INDEXING</a>) that matches all these color names
up to the colors they represent.  It mallocs the space for the
<b>colorhash_table</b> and returns its address at <i>chtP</i>.  The
number that the <b>colorhash_table</b> associates with each color is
the index into the color name array described above of the name of
that color.

<p>You may specify a null pointer for <i>fileName</i> to indicate the
default color dictionary.

<p><i>mustOpen</i> is a boolean.  If it is nonzero, the function fails
and aborts the program if it is unable to open the specified color dictionary
file.  If it is zero, though, it simply treats an unopenable color dictionary
as an empty one.  The colorhash and color name array it returns contain no
colors or names.

<p><b>ppm_readcolornamefile()</b> was new in Netpbm 10.15 (April 2003).


<h3 id="colorindex">COLOR INDEXING</h3>

<p>Sometimes in processing images, you want to associate a value with
a particular color.  Most often, that's because you're generating a
color mapped graphics format.  In a color mapped graphics format, the
raster contains small numbers, and the file contains a color map that
tells what color each of those small numbers refers to.  If your image
has only 256 colors, but each color takes 24 bits to describe, this
can make your output file much smaller than a straightforward RGB
raster would.

<p>So, continuing the above example, say you have a <b>pixel</b> value
for chartreuse and in your output file and you are going to represent
chartreuse by the number 12.  You need a data structure that allows
your program quickly to find out that the number for a chartreuse
<b>pixel</b> is 12.  Netpbm's color indexing data types and functions
give you that.

<p><b>colorhash_table</b> is a C data type that associates an integer
with each of an arbitrary number of colors.  It is a hash table, so it
uses far less space than an array indexed by the color's RGB values
would.

<p>The problem with a <b>colorhash_table</b> is that you can only look
things up in it.  You can't find out what colors are in it.  So Netpbm
has another data type for representing the same information, the
poorly but historically named <b>colorhist_vector</b>.  A
<b>colorhist_vector</b> is just an array.  Each entry represents a
color and contains the color's value (as a <b>pixel</b>) and the
integer value associated with it.  The entries are filled in starting
with subscript 0 and going consecutively up for the number of colors
in the histogram.

<p>(The reason the name is poor is because a color histogram is only
one of many things that could be represented by it).

<p><b>colorhash_table ppm_alloccolorhash()</b>

<p>This creates a <b>colorhash_table</b> using dynamically allocated
storage.  There are no colors in it.  If there is not enough storage,
<a href="liberror.html#error">throws an error</a>.

<p><b>void ppm_freecolorhash()</b>

<p>This destroys a <b>ppm_freecolorhash </b> and frees all the storage
associated with it.

<p><b>int ppm_addtocolorhash( colorhash_table cht, const pixel * const
colorP, const int value)</b>

<p>This adds the specified color to the specified <b>colorhash_table
</b> and associates the specified value with it.

<p>You must ensure that the color you are adding isn't already present
in the <b>colorhash_table</b>.

<p>There is no way to update an entry or delete an entry from a 
<b>colorhash_table</b>.

<p><b>int ppm_lookupcolor( const colorhash_table cht, const pixel *
const colorP )</b>

<p>This looks up the specified color in the specified
<b>colorhash_table</b>.  It returns the integer value associated with
that color.

<p>If the specified color is not in the hash table, the function
returns -1.  (So if you assign the value -1 to a color, the return
value is ambiguous).

<p><b>colorhist_vector ppm_colorhashtocolorhist( const colorhash_table cht,</b>

<b>const int ncolors )</b>

<p>This converts a <b>colorhash_table</b> to a
<b>colorhist_vector</b>.  The return value is a new
<b>colorhist_vector</b> which you must eventually free with
<b>ppm_freecolorhist()</b>.

<p><b>ncolors</b> is the number of colors in <b>cht</b>.  If it has
more colors than that, <b>ppm_colorhashtocolorhist</b> does not create
a <b>colorhist_vector</b> and returns NULL.

<p><b>colorhash_table ppm_colorhisttocolorhash( const colorhist_vector chv, 
const int ncolors ) </b>

<p>This poorly named function does <em>not</em> convert from a
<b>colorhist_vector</b> to a <b>colorhash_table</b>.

<p>It does create a <b>colorhash_table</b> based on a
<b>colorhist_vector</b> input, but the integer value for a given color
in the output is not the same as the integer value for that same color
in the input.  <b>ppm_colorhisttocolorhash()</b> ignores the integer
values in the input.  In the output, the integer value for a color is
the index in the input <b>colorhist_vector</b> for that color.

<p>You can easily create a color map for an image by running
<b>ppm_computecolorhist() </b> over the image, then
<b>ppm_colorhisttocolorhash()</b> over the result.  Now you can use
<b>ppm_lookupcolor()</b> to find a unique color index for any pixel in
the input.

<p>If the same color appears twice in the input,
<b>ppm_colorhisttocolorhash()</b> <a href="liberror.html#error">throws an
error</a>.

<p><b>ncolors</b> is the number of colors in <b>chv</b>.

<p>The return value is a new <b>colorhash_table</b> which you must
eventually free with <b>ppm_freecolorhash()</b>.

<h3 id="histogram">COLOR HISTOGRAMS</h3>

<p>The Netpbm libraries give you functions to examine a Netpbm image
and determine what colors are in it and how many pixels of each color
are in it.  This information is known as a color histogram.  Netpbm
uses its <b>colorhash_table</b> data type to represent a color
histogram.

<p><b>colorhash_table ppm_computecolorhash( pixel ** const pixels,
const int cols, const int rows, const int maxcolors, int* const colorsP )</b>

<p>This poorly but historically named function generates a
<b>colorhash_table</b> whose value for each color is the number of
pixels in a specified image that have that color.  (I.e. a color
histogram).  As a bonus, it returns the number of colors in the image.

<p>(It's poorly named because not all <b>colorhash_table</b>s are
color histograms, but that's all it generates).

<p><b>pixels</b>, <b>cols</b>, and <b>rows</b> describe the input
image.

<p><b>maxcolors</b> is the maximum number of colors you want
processed.  If there are more colors that that in the input image,
<b>ppm_computecolorhash()</b> returns NULL as its return value and
stops processing as soon as it discovers this.  This makes it run
faster and use less memory.  One use for <b>maxcolors</b> is when you
just want to find out whether or not the image has more than N colors
and don't want to wait to generate a huge color table if so.  If you
don't want any limit on the number of colors, specify
<b>maxcolors</b>=<b>0</b>.

<p><b>ppm_computecolorhash()</b> returns the actual number of colors
in the image as <b>*colorsP</b>, but only if it is less than or equal
to <b>maxcolors</b>.

<p><b>colorhash_table ppm_computecolorhash2( FILE * const ifp,
const int cols, const int rows, const pixval maxval, const int format,</b>

<b>const int maxcolors, int* const colorsP )</b>

<p>This is the same as <b>ppm_computecolorhash()</b> except that
instead of feeding it an array of pixels in storage, you give it an
open file stream and it reads the image from the file.  The file must
be positioned after the header, at the raster.  Upon return, the file
is still open, but its position is undefined.

<p><b>maxval</b> and <b>format</b> are the values for the image
(i.e. information from the file's header).

<p><b>colorhist_vector ppm_computecolorhist( pixel ** pixels,
int cols, int rows, int maxcolors, int * colorsP )</b>

<p>This is like <b>ppm_computecolorhash()</b> except that it creates a
<b>colorhist_vector</b> instead of a <b>colorhash_table</b>.

<p>If you supply a nonzero <b>maxcolors</b> argument, that is the
maximum number of colors you expect to find in the input image.  If
there are more colors than you say in the image,
<b>ppm_computecolorhist()</b> returns a null pointer as its return
value and nothing meaningful as <b>*colorsP</b>.

<p>If not, the function returns the new <b>colorhist_vector </b> as
its return value and the actual number of colors in the image as
<b>*colorsP</b>.  The returned array has space allocated for the
specified number of colors regardless of how many actually exist.  The
extra space is at the high end of the array and is available for your
use in expanding the <b>colorhist_vector</b>.

<p>If you specify <b>maxcolors</b>=<b>0</b>, there is no limit on the
number of colors returned and the return array has space for 5 extra
colors at the high end for your use in expanding the
<b>colorhist_vector</b>.

<p><b>colorhist_vector ppm_computecolorhist2( FILE * ifp,
int cols, int rows, int maxcolors, pixval maxval, int format,
int * colorsP )</b>

<p>This is the same as <b>ppm_computecolorhist()</b> except that
instead of feeding it an array of pixels in storage, you give it an
open file stream and it reads the image from the file.  The file must
be positioned after the header, at the raster.  Upon return, the file
is still open, but its position is undefined.

<h2 id="seealso">SEE ALSO</h2>

<b><a href="pbm.html">pbm</a></b>,
<b><a href="pgm.html">pgm</a></b>,
<b><a href="libpbm.html">libpbm</a></b>

<h2 id="author">AUTHOR</h2>

Copyright (C) 1989, 1991 by Tony Hansen and Jef Poskanzer.

<hr>
<h2 id="index">Table Of Contents</h2>
<ul>
<li><a href="#synopsis">SYNOPSIS</a>
<li><a href="#description">DESCRIPTION</a>
  <ul>
  <li><a href="#types">TYPES AND CONSTANTS</a>
  <li><a href="#manipulating_pixels">MANIPULATING PIXELS</a>
  <li><a href="#initialization">INITIALIZATION</a>
  <li><a href="#memorymanagement">MEMORY MANAGEMENT</a>
  <li><a href="#readingfiles">READING FILES</a>
  <li><a href="#writingfiles">WRITING FILES</a>
  <li><a href="#miscellaneous">MISCELLANEOUS</a>
  <li><a href="#color">COLOR</a>
    <ul>
    <li><a href="#luminance">Luminance, Chrominance (YcbCr)</a>
    <li><a href="#berlinkay">Berlin-Kay Color</a>
    </ul>
  <li><a href="#colorname">COLOR NAMES</a>
    <ul>
    <li><a href="#dictionary">System Color Dictionary</a>
    <li><a href="#ppm_parsecolor">ppm_parsecolor</a>
    <li><a href="#ppm_parsecolor2">ppm_parsecolor2</a>
    <li><a href="#ppm_colorname">ppm_colorname</a>
    <li><a href="#ppm_readcolornamefile">ppm_readcolornamefile</a>
    </ul>
  <li><a href="#colorindex">COLOR INDEXING</a>
  <li><a href="#histogram">COLOR HISTOGRAMS</a>
  </ul>
  <li><a href="#seealso">SEE ALSO</a>
  <li><a href="#author">AUTHOR</a>
  </ul>
</body>
</html>