{"id":10321,"date":"2025-04-25T03:00:00","date_gmt":"2025-04-25T07:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=10321"},"modified":"2025-04-19T13:49:29","modified_gmt":"2025-04-19T17:49:29","slug":"draw-in-color-using-portable-pix-maps","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=10321","title":{"rendered":"Draw in color using Portable Pix Maps"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"10321\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div>\n<p>The Portable aNy Map (PNM) is an older image file format \u201cfamily\u201d that dates back to the 1980s. Originally designed to transmit images over email as plain text, these images became popular at the time because the relatively simple file format made it easy to create all kinds of images.<\/p>\n\n\n\n<p>Portable aNy Map files come in several types:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Portable Bit Map (PBM) for black and white images<\/li>\n\n\n\n<li>Portable Gray Map (PGM) for grayscale images<\/li>\n\n\n\n<li>Portable Pix Map (PPM) for color images<\/li>\n<\/ol>\n\n\n\n<p>See my other articles about creating <a href=\"https:\/\/www.both.org\/?p=10297\">black and white images<\/a> in PBM and <a href=\"https:\/\/www.both.org\/?p=10313\">grayscale images<\/a> in PGM. Let\u2019s explore how to create colorful images using PPM:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"plain-text-ppm\">Plain text PPM<\/h2>\n\n\n\n<p>Like other images in the PNM \u201cfamily,\u201d Portable Pix Map images have a <em>header<\/em> section that defines the image dimensions, and a <em>data<\/em> section with the image values. The PPM header starts with <code>P3<\/code> as the \u201cmagic number\u201d that identifies the file as a PPM image, then the width and height of the image in pixels, followed by the maximum color value in the image. All of these values are plain text, separated by whitespace like a tab, space, or newline.<\/p>\n\n\n\n<p>For example, to create a 9&#215;10 image, with a maximum color value of 2, use this header:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>P3\n9 10 2<\/code><\/pre>\n\n\n\n<p>The maximum color value is the highest decimal value that can be used in a red\/green\/blue color, or RGB. In this case, <code>2<\/code> means any red, green, or blue color can be in the range of 0, 1, or 2\u2014that\u2019s 3 possible gradations for each RGB value, for a color palette of 3x3x3 = 27 different combinations of red, green, and blue. If the maximum color value is 0 to 255, colors are assumed to be 1-byte values; for color values 256 to 65,535, colors use 2-byte values.<\/p>\n\n\n\n<p>The data section is a series of RGB values, each given in that order: red, green, then blue. Separate each value by whitespace, such as spaces or tabs or newlines. Continuing with the above example, we can write this sample PPM image that contains a series of vertical stripes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>P3\n9 10 2\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0\n0 0 0  0 0 1  0 0 2  0 0 0  0 1 0  0 2 0  0 0 0  1 0 0  2 0 0<\/code><\/pre>\n\n\n\n<p>A 9&#215;10 image is too small to display effectively on a website, so here\u2019s the same image after it\u2019s been expanded to 90&#215;100 size. You can see the image has stripes of colors, divided into three bands of red, green, and blue, going from dark (black) to bright:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"90\" height=\"100\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2025\/04\/stripes.png\" alt=\"stripes showing different shades of red, green, and blue\" class=\"wp-image-10318\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"binary-ppm\">Binary PPM<\/h2>\n\n\n\n<p>Programs can write image files more efficiently if they write in binary mode, and that\u2019s why PPM also supports a <em>raw<\/em> binary version. The file is basically the same, except that the header uses <code>P6<\/code> for the \u201cmagic number,\u201d and the RGB data is written as binary triplet values, such as could be written using the <code>\"%c%c%c\"<\/code> format in a C program.<\/p>\n\n\n\n<p>When writing color PPM files, consider the palette you need to use. You aren\u2019t restricted to using a pre-defined palette like RGB values from 0,0,0 (black) to 0xff,0xff,0xff (white in the standard 256-color screen palette). Instead, you can choose your own palette. That means for a maximum color value of <em>n<\/em>, black will always be 0,0,0 and white will always be <em>n,n,n<\/em> and other colors for intermediate RGB values. The colors will be translated to screen values when the image is displayed.<\/p>\n\n\n\n<p>Here\u2019s an example program that generates the web-safe colors. Normally, you would use the standard web colors from R,G,B=0,0,0 to R,G,B=0xff,0xff,0xff but using \u201csteps\u201d from 00 to 33, 66, 99, cc, and ff. You can write a sample HTML file with a Bash script, like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n\ncat&lt;&lt;EOF\n&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;&lt;title&gt;Web safe colors&lt;\/title&gt;\n&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;\n&lt;style&gt;\nbody{display:grid; grid-template-columns:repeat(6,1fr);}\ndiv{padding:1em;}\n&lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\nEOF\n\nwebcolors='00 33 66 99 cc ff'\n\nfor r in $webcolors; do\n  for g in $webcolors; do\n    for b in $webcolors; do\n      color=\"$r$g$b\"\n      echo \"&lt;div style='background-color:#$color'&gt;$color&lt;\/div&gt;\"\n    done\n  done\ndone\n\ncat&lt;&lt;EOF\n&lt;\/body&gt;\n&lt;\/html&gt;\nEOF<\/code><\/pre>\n\n\n\n<p>There\u2019s a lot in that script, because it also writes the supporting HTML elements and styles that make it look nice on a screen. The most important part is the three \u201cnested\u201d <code>for<\/code> loops, each moving from 00 to ff with each \u201cstep\u201d at 33. If you run the script and save the output to a file, you can view the HTML file in a browser to see the web-safe colors:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ bash websafe.bash &gt; websafe.html<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"962\" height=\"511\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2025\/04\/websafe.png\" alt=\"web safe colors in a web browser\" class=\"wp-image-10320\"\/><figcaption class=\"wp-element-caption\">Viewing the web-safe colors in a web browser<\/figcaption><\/figure>\n\n\n\n<p>Writing a PPM file to show these same web-safe colors requires iterating over six possible values for each red, green, and blue value. That means a color range from 0 to 5, which gives six values. An RGB triplet of 0,0,0 is black, and a triplet of 5,5,5 is bright white.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n\nint main()\n{\n    puts(\"P6 6 36 5\");\n\n    for (int r = 0; r &lt;= 5; r++) {\n        for (int g = 0; g &lt;= 5; g++) {\n            for (int b = 0; b &lt;= 5; b++) {\n                printf(\"%c%c%c\", r, g, b);\n            }\n        }\n    }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>Compile this program and run it to generate the web-safe palette as a PPM file. The program writes to standard output, so you also need to redirect the output to a file that you can view later.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gcc -Wall -o webcolors webcolors.c\n$ .\/webcolors &gt; webcolors.ppm<\/code><\/pre>\n\n\n\n<p>This generates a small file that\u2019s just 6 pixels wide and 36 pixels tall. Here\u2019s the same image after I\u2019ve \u201czoomed in\u201d so you can see each of the pixel values:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"60\" height=\"360\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2025\/04\/webcolors.png\" alt=\"web safe colors as a PPM image\" class=\"wp-image-10319\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"more-information\">More information<\/h2>\n\n\n\n<p>Creating color images is easy using the Portable Pix Map (PPM) file format. Write a header that defines the dimensions and maximum color value, then write the header in either plain text or binary. Use the \u201cmagic number\u201d to define the kind of file you want to create: <code>P3<\/code> for a plain text PPM image, or <code>P6<\/code> for a binary PPM image. The <a href=\"https:\/\/netpbm.sourceforge.net\/\">Netpbm project<\/a> at Sourceforge has the full details about PPM files and other file formats in the Portable aNy Map (PNM) \u201cfamily\u201d of images. See the <a href=\"https:\/\/netpbm.sourceforge.net\/doc\/ppm.html\">ppm manual page<\/a> for more information about creating PPM images.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Create colorful images using the Portable Pix Map format.<\/p>\n","protected":false},"author":33,"featured_media":6830,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[150],"tags":[152],"class_list":["post-10321","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming","tag-programming"],"modified_by":"Jim Hall","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10321"}],"version-history":[{"count":4,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10321\/revisions"}],"predecessor-version":[{"id":10325,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10321\/revisions\/10325"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/6830"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}