---
name: "libppm"
section: "3"
platform: "linux"
package: "netpbm"
version: "10.86.51-2"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/libppm"
---

# libppm(3)

functions for PPM programs

## NAME

libppm - functions for PPM programs

## SYNOPSIS

**#include \<netpbm/ppm.h\>**

**void ppm\_init(int \*** *argcP***,**\
   **char \*** *argv***\[\]);**

**pixel \*\* ppm\_allocarray(**

**int** *cols***,int** *rows***);**

**pixel \* ppm\_allocrow(int** *cols***);**

**void ppm\_freearray(pixel \*\*** *pixels***,**\
   **int** *rows***);**

**void ppm\_freerow(pixel \*** *pixelrow***);**

**void ppm\_readppminit(FILE \*** *fp***,**\
   **int \*** *colsP***,**\
   **int \*** *rowsP***,**

**pixval \*** *maxvalP***,int \*** *formatP* **);**

**void ppm\_readppmrow(FILE \****fp***,**\
   **pixel \*** *pixelrow***,**\
   **int** *cols***,**\
   **pixval** *maxval***,**\
   **int** *format***);**

**pixel \*\* ppm\_readppm(FILE \*** *fp***,**\
   **int \*** *colsP***,**\
   **int \*** *rowsP***,**\
   **pixval \*** *maxvalP***);**

**void ppm\_writeppminit(FILE \*** *fp***,**\
   **int** *cols***,**\
   **int** *rows***,**\
   **pixval** *maxval***,**\
   **int** *forceplain***);**

**void ppm\_writeppmrow(FILE \*** *fp***,**\
   **pixel \*** *pixelrow***,**\
   **int** *cols***,**\
   **pixval** *maxval***,**\
   **int** *forceplain***);**

**void ppm\_writeppm(FILE \*** *fp***,**\
   **pixel \*\*** *pixels***,**\
   **int** *cols***,**\
   **int** *rows***,**\
   **pixval** *maxval***,**\
   **int** *forceplain***);**

**void ppm\_writeppm(FILE \*** *fp***,**\
   **pixel \*\*** *pixels***,**\
   **int** *cols***,**\
   **int** *rows***,**\
   **pixval** *maxval***,**\
   **int** *forceplain***);**

**void ppm\_nextimage(FILE \*** *file***,**\
   **int \* const** *eofP***);**

**void ppm\_check(FILE \*** *file***,**\
   **const enum pm\_check\_type** *check\_type***,**\
   **const int** *format***,**\
   **const int** *cols***,**\
   **const int** *rows***,**\
   **const int** *maxval***,** **enum pm\_check\_code \* const** *retval***);**

**typedef ... pixel;**

**typedef ... pixval;**

**#define PPM\_MAXMAXVAL ...**

**#define PPM\_OVERALLMAXVAL ...**

**#define PPM\_FORMAT ...**

**#define RPPM\_FORMAT ...**

**#define PPM\_TYPE PPM\_FORMAT**

**#define** **PPM\_FORMAT\_TYPE(***format***)** **...**

**pixval PPM\_GETR(pixel** *p***)**

**pixval PPM\_GETG(pixel** *p***)**

**pixval PPM\_GETB(pixel** *p***)**

**void PPM\_ASSIGN(pixel** *p***,**\
   **pixval** *red***,**\
   **pixval** *grn***,**\
   **pixval** *blu***)**

**int PPM\_EQUAL(pixel** *p***,**\
   **pixel** *q***)**

**int PPM\_ISGRAY(pixel** *p***)**

**void**\
   **PPM\_DEPTH(pixel** *newp***,**\
   **pixel** *p***,**\
   **pixval** *oldmaxval***,**\
   **pixval** *newmaxval***)**

**pixel ppm\_parsecolor(char \*** *colorname***,**\
    **pixval** *maxval***)**

**pixel ppm\_parsecolor2(** **char \*** *colorname***,** **pixval** *maxval***,** **int** *closeOk* **)**

**char \* ppm\_colorname(pixel \*** *colorP***,**\
   **pixval** *maxval***,**\
   **int** *hexok***)**

**void ppm\_readcolornamefile(**\
   **const char \****fileName,* \
   **int** *mustOpen,*\
   **colorhash\_table \*** *chtP,* \
   **const char \*\*\*** *colornamesP*\
   **)**

## DESCRIPTION

*These library functions are part of* **Netpbm**(1) *.*

### TYPES AND CONSTANTS

*Each* **pixel** *contains three* **pixval***s, each of which should* *contain only the values between* **0** *and* **PPM\_MAXMAXVAL***.*

### MANIPULATING PIXELS

*The macros* **PPM\_GETR***,* **PPM\_GETG***, and* **PPM\_GETB** *retrieve the red, green, or blue sample, respectively, from the given* *pixel.*

*The* **PPM\_ASSIGN** *macro assigns the given values to the red,* *green, and blue samples of the given pixel.*

*The* **PPM\_EQUAL** *macro tests two pixels for equality.*

*The* **PPM\_ISGRAY** *macro tests a pixel for being gray.  It* *returns true if and only if the color of pixel p is black,* *white, or gray.*

*The* **PPM\_DEPTH** *macro scales the colors of pixel p* *according the old and new maxvals and assigns the new values to* *newp.  It is intended to make writing ppmtowhatever easier.*

*The* **PPM\_LUMIN***,* **PPM\_CHROM\_R***, and* **PPM\_CHROM\_B** *macros determine the luminance, red chrominance, and blue chrominance,* *respectively, of the pixel p.  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).*

*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.*

### INITIALIZATION

**ppm\_init()** *is obsolete (at least since Netpbm 9.25 (March 2002)).* *Use*  **pm\_proginit()** ⟨libpm.html#initialization⟩  *instead.*

**ppm\_init()** *is identical to* **pm\_proginit***.*

### MEMORY MANAGEMENT

**ppm\_allocarray()** *allocates an array of pixels.*

**ppm\_allocrow()** *allocates a row of the given number of* *pixels.*

**ppm\_freearray()** *frees the array allocated with* **ppm\_allocarray()** *containing the given number of rows.*

**ppm\_freerow()** *frees a row of pixelss allocated with* **ppm\_allocrow()***.*

### READING FILES

*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* *format value returned by* **ppm\_readppminit()** *is, however,* *not translated.  It represents the actual format of the PBM or PGM* *file.*

**ppm\_readppminit()** *reads the header of a PPM file, returning* *all the information from the header and leaving the file positioned* *just after the header.*

**ppm\_readppmrow()** *reads a row of pixels into the* *pixelrow array.  format, cols, and maxval* *are the values returned by* **ppm\_readppminit()***.*

**ppm\_readppm()** *reads an entire PPM image into memory,* *returning the allocated array as its return value and returning the* *information from the header as rows, cols, and* *maxval.  This function combines* **ppm\_readppminit()***,* **ppm\_allocarray()***, and* **ppm\_readppmrow()***.*

### WRITING FILES

**ppm\_writeppminit()** *writes the header for a PPM file and leaves* *it positioned just after the header.*

*forceplain is a logical value that tells* **ppm\_writeppminit()**  *to write a header for a plain PPM format* *file, as opposed to a raw PPM format file.*

**ppm\_writeppmrow()** *writes the row pixelrow to a PPM* *file.  For meaningful results, cols, maxval, and* *forceplain must be the same as was used with* **ppm\_writeppminit()***.*

**ppm\_writeppm()** *write the header and all data for a PPM* *image.  This function combines* **ppm\_writeppminit()** *and* **ppm\_writeppmrow()***.*

### MISCELLANEOUS

**ppm\_nextimage()** *positions a PPM input file to the next image* *in it (so that a subsequent* **ppm\_readppminit()** *reads its* *header).*

**ppm\_nextimage()** *is analogous to* **pbm\_nextimage()***, but* *works on PPM, PGM, and PBM files.*

**ppm\_check()**  *checks for the common file integrity error* *where the file is the wrong size to contain all the image data.*

**ppm\_check()**  *is analogous to* **pbm\_check()***, but works* *on PPM, PGM, and PBM files.*

### COLOR

**Luminance, Chrominance (YcbCr)**

```
    float PPM_LUMIN(pixel p);
    float PPM_CHROM_B(pixel p);
    float PPM_CHROM_R(pixel p);
```

**PPM\_LUMIN** *takes a* **pixel** *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* **PPM\_LUMIN** *value of 255* *means fully luminant).*

**PPM\_CHROM\_B** *and* **PPM\_CHROM\_R** *are similar, for the red* *and blue chrominance values.*

```
    pixel
    ppm_color_from_ycbcr(unsigned int y,
                         int          cb,
                         int          cr);
```

**ppm\_color\_from\_ycbcr()** *converts in the other direction.* *Given luminance and chrominance, it returns a pixel value.*

**Hue, Saturation, Value (HSV)**

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

```
    pixel
    ppm_color_from_hsv(struct hsv const hsv,
                       pixval     const maxval);
```

```
    struct hsv
    ppm_hsv_from_color(pixel  const color,
                       pixval const maxval);
```

*These convert a color between from* **pixel** *(RGB) form and HSV.*

```
    pixval
    ppm_saturation(pixel  const p,
                   pixval const maxval);
```

*This gives you the saturation of a color, as a pixval.  (e.g. if* *the saturation of p is 50% and maxval is 100,* **ppm\_saturation()** *returns 50).*

**Berlin-Kay Color**

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

- •

  *black*

- •

  *gray*

- •

  *white*

- •

  *red*

- •

  *orange*

- •

  *yellow*

- •

  *green*

- •

  *blue*

- •

  *violet*

- •

  *purple*

- •

  *brown*

*The* **bk\_color** *type represents a color from this set:*

```
    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;
```

*You can use this as an index of an array, in which case you might also* *want macro* **BKCOLOR\_COUNT***, which is the number of colors in the* *set (11).*

*To translate between the* **bk\_color** *type and the English names* *of the colors, use* **ppm\_bk\_color\_from\_name()** *and* **ppm\_name\_from\_bk\_color()***:*

```
    bk_color
    ppm_bk_color_from_name(const char * name);
    const char *
    ppm_name_from_bk_color(bk_color bkColor);
```

**ppm\_bk\_color\_from\_color()** *tells you to which Berlin-Kay color* *a certain color is closest, by way of a fuzzy color matching algorithm:*

```
    bk_color
    ppm_bk_color_from_color(pixel  color,
                            pixval maxval);
```

*maxval is the maxval on which color is based.*

**ppm\_color\_from\_bk\_color()** *converts the opposite way: given* *a Berlin-Kay color, it gives the color, in* **pixel** *form, that best* *represents it.*

```
    pixel
    ppm_color_from_bk_color(bk_color bkColor,
                            pixval   maxval);
```

*maxval is the maxval on which the returned color is based.*

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

### COLOR NAMES

**System Color Dictionary**

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

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

- •

  **/usr/local/netpbm/rgb.txt**

- •

  **/usr/share/netpbm/rgb.txt**

- •

  **/etc/X11/rgb.txt**

- •

  **/usr/lib/X11/rgb.txt**

- •

  **/usr/openwinlib/rgb.txt**

- •

  **/usr/X11R6/lib/X11/rgb.txt**

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

*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, on* *the*  *Aubrey Jaffer&apos;s website* ⟨http://people.csail.mit.edu/~jaffer/Color/x11.pdf⟩ *.  Jaffer also index a bunch* *of*  *other versions* ⟨http://people.csail.mit.edu/~jaffer/Color/Dictionaries⟩  *you could use.*

*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.*

*Before Netpbm 11.07 (June 2024),* **ppm\_readcolornamefile()** *fails if* *your color dictionary has more than 1000 entries in it.  So does* **ppm\_readcolordict** *if you request the color name array.  This means* *programs* **ppmhist** *with a* **-colorname** *option and* **ppmtoxpm** *without a* **-hexonly** *option fail.*

*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.*

**ppm\_parsecolor**

**ppm\_parsecolor()** *interprets a color specification and returns a* *pixel of the color that it indicates.  It is the same as* *pnm\_parsecolor* ⟨libnetpbm\_image.html#colorname⟩ *, except that it* *returns a* **pixel** *instead of a* **tuple***.*

**ppm\_parsecolor2**

**ppm\_parsecolor2()** *interprets a color specification and returns a* *pixel of the color that it indicates and warns about rounding.  It is the same* *as*  *pnm\_parsecolor2* ⟨libnetpbm\_image.html#colorname⟩ *, except* *that it returns a* **pixel** *instead of a* **tuple***.*

**ppm\_colorname**

**ppm\_colorname()** *returns a string that describes the color* *of the given pixel.  If a*  *system color dictionary* ⟨#dictionary⟩ *is available and the color appears in it,* **ppm\_colorname()** *returns the name of the color from the file.  If the color does not* *appear in a system color dictionary and hexok is true,* **ppm\_colorname()** *returns a hexadecimal color specification* *triple (#rrggbb).  If a system color dictionary is available but the* *color does not appear in it and hexok is false,* **ppm\_colorname()** *returns the name of the closest matching color* *in the color file.  Finally, if there is no system color dictionary* *available and hexok is false,* **ppm\_colorname()** *fails and* *throws an error* ⟨liberror.html#error⟩ *.*

*The string returned is in static libppm library storage which is* *overwritten by every call to* **ppm\_colorname()***.*

**ppm\_readcolornamefile**

**ppm\_readcolornamefile()** *reads the entire contents of the color* *dictionary in the file named fileName into data structures you* *can use to access it easily.*

*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 colornamesP.* **(\*colornamesP)\[***i***\]** *is the address of the first* *character in the null-terminated string that is the name of the* *ith color in the dictionary.*

*The function also returns a* **colorhash\_table** *(see*  *COLOR INDEXING* ⟨#colorindex⟩ *) that matches all these color names* *up to the colors they represent.  It mallocs the space for the* **colorhash\_table** *and returns its address at chtP.  The* *number that the* **colorhash\_table** *associates with each color is* *the index into the color name array described above of the name of* *that color.*

*You may specify a null pointer for fileName to indicate the* *default color dictionary.*

*mustOpen 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.*

**ppm\_readcolornamefile()** *was new in Netpbm 10.15 (April 2003).*

### COLOR INDEXING

*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.*

*So, continuing the above example, say you have a* **pixel** *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* **pixel** *is 12.  Netpbm's color indexing data types and functions* *give you that.*

**colorhash\_table** *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.*

*The problem with a* **colorhash\_table** *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* **colorhist\_vector***.  A* **colorhist\_vector** *is just an array.  Each entry represents a* *color and contains the color's value (as a* **pixel***) 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.*

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

**colorhash\_table ppm\_alloccolorhash()**

*This creates a* **colorhash\_table** *using dynamically allocated* *storage.  There are no colors in it.  If there is not enough storage,* *throws an error* ⟨liberror.html#error⟩ *.*

**void ppm\_freecolorhash()**

*This destroys a* **ppm\_freecolorhash**  *and frees all the storage* *associated with it.*

**int ppm\_addtocolorhash( colorhash\_table cht, const pixel \* const** **colorP, const int value)**

*This adds the specified color to the specified* **colorhash\_table**  *and associates the specified value with it.*

*You must ensure that the color you are adding isn't already present* *in the* **colorhash\_table***.*

*There is no way to update an entry or delete an entry from a*  **colorhash\_table***.*

**int ppm\_lookupcolor( const colorhash\_table cht, const pixel \*** **const colorP )**

*This looks up the specified color in the specified* **colorhash\_table***.  It returns the integer value associated with* *that color.*

*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).*

**colorhist\_vector ppm\_colorhashtocolorhist( const colorhash\_table cht,**

**const int ncolors )**

*This converts a* **colorhash\_table** *to a* **colorhist\_vector***.  The return value is a new* **colorhist\_vector** *which you must eventually free with* **ppm\_freecolorhist()***.*

**ncolors** *is the number of colors in* **cht***.  If it has* *more colors than that,* **ppm\_colorhashtocolorhist** *does not create* *a* **colorhist\_vector** *and returns NULL.*

**colorhash\_table ppm\_colorhisttocolorhash( const colorhist\_vector chv,**  **const int ncolors )**

*This poorly named function does not convert from a* **colorhist\_vector** *to a* **colorhash\_table***.*

*It does create a* **colorhash\_table** *based on a* **colorhist\_vector** *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.*  **ppm\_colorhisttocolorhash()** *ignores the integer* *values in the input.  In the output, the integer value for a color is* *the index in the input* **colorhist\_vector** *for that color.*

*You can easily create a color map for an image by running* **ppm\_computecolorhist()**  *over the image, then* **ppm\_colorhisttocolorhash()** *over the result.  Now you can use* **ppm\_lookupcolor()** *to find a unique color index for any pixel in* *the input.*

*If the same color appears twice in the input,* **ppm\_colorhisttocolorhash()**  *throws an error* ⟨liberror.html#error⟩ *.*

**ncolors** *is the number of colors in* **chv***.*

*The return value is a new* **colorhash\_table** *which you must* *eventually free with* **ppm\_freecolorhash()***.*

### COLOR HISTOGRAMS

*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* **colorhash\_table** *data type to represent a color* *histogram.*

**colorhash\_table ppm\_computecolorhash( pixel \*\* const pixels,** **const int cols, const int rows, const int maxcolors, int\* const colorsP )**

*This poorly but historically named function generates a* **colorhash\_table** *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.*

*(It's poorly named because not all* **colorhash\_table***s are* *color histograms, but that's all it generates).*

**pixels***,* **cols***, and* **rows** *describe the input* *image.*

**maxcolors** *is the maximum number of colors you want* *processed.  If there are more colors that that in the input image,* **ppm\_computecolorhash()** *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* **maxcolors** *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* **maxcolors***=***0***.*

**ppm\_computecolorhash()** *returns the actual number of colors* *in the image as* **\*colorsP***, but only if it is less than or equal* *to* **maxcolors***.*

**colorhash\_table ppm\_computecolorhash2( FILE \* const ifp,** **const int cols, const int rows, const pixval maxval, const int format,**

**const int maxcolors, int\* const colorsP )**

*This is the same as* **ppm\_computecolorhash()** *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.*

**maxval** *and* **format** *are the values for the image* *(i.e. information from the file's header).*

**colorhist\_vector ppm\_computecolorhist( pixel \*\* pixels,** **int cols, int rows, int maxcolors, int \* colorsP )**

*This is like* **ppm\_computecolorhash()** *except that it creates a* **colorhist\_vector** *instead of a* **colorhash\_table***.*

*If you supply a nonzero* **maxcolors** *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,* **ppm\_computecolorhist()** *returns a null pointer as its return* *value and nothing meaningful as* **\*colorsP***.*

*If not, the function returns the new* **colorhist\_vector**  *as* *its return value and the actual number of colors in the image as* **\*colorsP***.  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* **colorhist\_vector***.*

*If you specify* **maxcolors***=***0***, 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* **colorhist\_vector***.*

**colorhist\_vector ppm\_computecolorhist2( FILE \* ifp,** **int cols, int rows, int maxcolors, pixval maxval, int format,** **int \* colorsP )**

*This is the same as* **ppm\_computecolorhist()** *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.*

## SEE ALSO

**pbm**(1) *,* **pgm**(1) *,* **libpbm**(1)

## AUTHOR

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

## DOCUMENT SOURCE

*This manual page was generated by the Netpbm tool 'makeman' from HTML* *source.  The master documentation is at*

-

  **http://netpbm.sourceforge.net/doc/libppm.html**
