{"id":10297,"date":"2025-04-21T03:00:00","date_gmt":"2025-04-21T07:00:00","guid":{"rendered":"https:\/\/www.both.org\/?p=10297"},"modified":"2025-04-19T12:05:00","modified_gmt":"2025-04-19T16:05:00","slug":"write-tiny-images-using-pbm","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=10297","title":{"rendered":"Write tiny images using PBM"},"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=\"10297\" 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 Bit Map (\u201cPBM\u201d) image file format was invented in the 1980s as a way to transmit small black and white images as plain text. The PBM image format is one of a \u201cfamily\u201d of related images with basically the same image format, collectively called the \u201cPortable aNy Map\u201d (PNM) format.<\/p>\n\n\n\n<p>PBM files have a very simple format that makes it easy for anyone to create a PBM file. This simplicity also made PBM briefly popular as an icon image format on monochrome systems.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"plain-text-pbm\">Plain text PBM<\/h2>\n\n\n\n<p>The basic outline of any \u201cPNM\u201d image is a <em>header<\/em> section and a <em>data<\/em> section. The PBM header is the value <code>P1<\/code> as the \u201cmagic number\u201d (to indicate the file type) and two values for the width and height. All three entries must be separated by one whitespace character, which could include space, tab, or newline.<\/p>\n\n\n\n<p>The PBM data section is a series of ones and zeroes that indicate black (1) or white (0). Because this is a single digit, any whitespace characters are safely ignored here.<\/p>\n\n\n\n<p>For example, let\u2019s say I wanted to draw an 8&#215;8 black and white image of the \u201ccopyright\u201d symbol: that\u2019s just a \u201cc\u201d inside a circle. I might start by drawing the \u201cdots\u201d or \u201cpixels\u201d that make up the image on a piece of paper or in a scratch file. In this example, I might enter text into an editor, using periods for blank spaces and asterisks for black pixels:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>..****..\n.*....*.\n*..**..*\n*.*....*\n*.*....*\n*..**..*\n.*....*.\n..****..<\/code><\/pre>\n\n\n\n<p>After creating a sample image as plain text, it\u2019s a simple process of search-and-replace in my editor to turn all periods to zeroes, and all asterisks to ones. Adding the magic number and the x and y dimensions makes this a valid PBM file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>P1\n8 8\n00111100\n01000010\n10011001\n10100001\n10100001\n10011001\n01000010\n00111100<\/code><\/pre>\n\n\n\n<p>Web browsers don\u2019t understand the PBM format, so here\u2019s the PBM image converted to a more common PNG format, and \u201cblown up\u201d from 8&#215;8 to 64&#215;64 so you can see the pixels:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"64\" height=\"64\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2025\/04\/copyr64.png\" alt=\"black and white image of a C inside a circle\" class=\"wp-image-10300\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"binary-pbm\">Binary PBM<\/h2>\n\n\n\n<p>Storing a black and white image as a series of 1-byte characters isn\u2019t very space-efficient: the values are either <code>0<\/code> (ASCII 48) or <code>1<\/code> (ASCII 49). Including the newline characters, this file is 79 bytes. A more compact way to write this is to use a raw binary pattern to represent each \u201coff\u201d (<code>0<\/code>) or \u201con\u201d (<code>1<\/code>) value.<\/p>\n\n\n\n<p>The basic format remains the same for this \u201craw\u201d file: a header section and a data section. The header section is the same, except for a different magic number: plain text PBM files use <code>P1<\/code> for the magic number, and raw PBM files use <code>P4<\/code>. This is because the Portable aNy Map \u201cfamily\u201d of file formats was initially just three files:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Magic Number<\/th><th>File Type<\/th><th>Colors<\/th><\/tr><\/thead><tbody><tr><td><code>P1<\/code><\/td><td>Portable Bit Map (PBM)<\/td><td>Black and white<\/td><\/tr><tr><td><code>P2<\/code><\/td><td>Portable Gray Map (PGM)<\/td><td>Grayscale<\/td><\/tr><tr><td><code>P3<\/code><\/td><td>Portable Pix Map (PPM)<\/td><td>Full color<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Each of the initial file types were plain text, so they could be sent over email. To make the file sizes smaller, and easier for programs to read and write the files, each file also has a raw binary file type:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Text File<\/th><th>Raw File<\/th><th>File Type<\/th><th>Colors<\/th><\/tr><\/thead><tbody><tr><td><code>P1<\/code><\/td><td><code>P4<\/code><\/td><td>Portable Bit Map (PBM)<\/td><td>Black and white<\/td><\/tr><tr><td><code>P2<\/code><\/td><td><code>P5<\/code><\/td><td>Portable Gray Map (PGM)<\/td><td>Grayscale<\/td><\/tr><tr><td><code>P3<\/code><\/td><td><code>P6<\/code><\/td><td>Portable Pix Map (PPM)<\/td><td>Full color<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>As another example, let\u2019s say I wanted to draw an 8&#215;8 empty box as a PBM image. I might start by drawing this on a piece of paper or in a text file, like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>11111111\n10000001\n10000001\n10000001\n10000001\n10000001\n10000001\n11111111<\/code><\/pre>\n\n\n\n<p>I\u2019ve drawn the image as plain text in a text editor, using zeroes for white spaces and ones for black dots. To turn this into a raw PBM file, I need to break up the data into a series of bytes; this is convenient because I already defined the image as an 8&#215;8 black and white image, and 8 bits is a byte.<\/p>\n\n\n\n<p>In binary, bits are either <code>1<\/code> for \u201con\u201d or <code>0<\/code> for \u201coff,\u201d and there are 8 bits in a byte. Each bit goes up in value by a power of 2, starting with <code>1<\/code> in the far-right position:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>128<\/th><th>64<\/th><th>32<\/th><th>16<\/th><th>8<\/th><th>4<\/th><th>2<\/th><th>1<\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td>1<\/td><td>1<\/td><td>1<\/td><td>1<\/td><td>1<\/td><td>1<\/td><td>1<\/td><td>1<\/td><td>255<\/td><\/tr><tr><td>1<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>0<\/td><td>1<\/td><td>129<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>So to create a raw PBM file of an 8&#215;8 empty box, I need to write the binary value 255, followed by six binary values of 129, and one more binary value 255. This is easiest to do in a program:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n\nint main()\n{\n  puts(\"P4 8 8\");\n  printf(\"%c\", 255);\n  for (int i=0; i&lt;6; i++) { printf(\"%c\", 129); }\n  printf(\"%c\", 255);\n  return 0;\n}<\/code><\/pre>\n\n\n\n<p>This program writes a single binary 255 value, then six binary 129 values, followed by another binary 255 value. The program writes to standard output, so you need to redirect the output to a file when you run it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ gcc -Wall -o box box.c\n$ .\/box &gt; box.pbm<\/code><\/pre>\n\n\n\n<p>The result is a raw PBM file that\u2019s only 15 bytes long. Here\u2019s a copy of the image, blown up to 64&#215;64 size so you can see the pixels:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"64\" height=\"64\" src=\"http:\/\/www.both.org\/wp-content\/uploads\/2025\/04\/box64.png\" alt=\"black and white image of an empty box\" class=\"wp-image-10299\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"portable-images\">Portable images<\/h2>\n\n\n\n<p>PBM, PGM, and PPM files make it easy to create simple images on your own. Use Portable Bit Map (PBM) if you only need to create black and white images, like these sample images. To learn more about these images, see the <a href=\"https:\/\/netpbm.sourceforge.net\/\">Netpbm project<\/a> hosted at SourceForge. The <a href=\"https:\/\/netpbm.sourceforge.net\/doc\/#formats\">Netpbm Formats<\/a> section in the user manual describes the file formats. See the <a href=\"https:\/\/netpbm.sourceforge.net\/doc\/pbm.html\">pbm man page<\/a> in the manual for a complete description of the PBM format.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Portable Bit Map (&ldquo;PBM&rdquo;) image file format was invented in the 1980s as a way to transmit<\/p>\n","protected":false},"author":33,"featured_media":2952,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[150],"tags":[152],"class_list":["post-10297","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\/10297","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=10297"}],"version-history":[{"count":2,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10297\/revisions"}],"predecessor-version":[{"id":10301,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/10297\/revisions\/10301"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/2952"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10297"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10297"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10297"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}