Skip to footer navigation.

« Oatmeal

A quick and dirty intro to the .pbm file format

I’ve been fiddling with writing programs that draw pictures. I started with PostScript for this, but have since moved to writing programs that output in the .pbm format.

My goal here is to write noise to a .pbm file.

A .pbm file is the lowest common denominator among image file formats.

An example of the format,

# comment describing the file 

5 5
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1

The first line is a required magic number, the next a comment.

Then comes a blank line, followed by declaration of height and width.

Last but not least is the image data, where 1 is a black pixel and 0 is white/blank.

The most fun part of this exercise comes from a suggestion from crc, the main developer behind RetroForth, and allows for the writing of all the data to the file in one go by using c:puts hook. For more context, see here. For more on hooks, see this excellent blog post from a friend!

'output.pbm file:open-for-writing 'PBM-Target var-n

:c:to-file [ @PBM-Target file:write ] &c:put set-hook ;
:c:to-display &c:put unhook ;

Next I whip out my trusty word that returns a random number within a range.

    over - n:inc n:random swap mod + ;

Next comes some housekeeping, defining the width and height the file will be. Of note, I’m not sure if these integers are referencing pixels, printer points, or just like blocks or something…

#100 !w
#100 !h

Last but not least comes the (veggie)meat of the thing: we open a file for writing into, define the body to be written into the file, and then spew it all into the file. Last but not least we display a string to let us know everything is Done.

'P1 s:put nl
'#_sample_pbm_file_made_from_retro s:put nl nl
@h '_ @w n:put s:put n:put nl
@h [ @w [ #0 #1 n:ranged-random n:put '_ s:put ] times nl ] times nl

'Done s:put nl
@PBM-Target file:close

An example .pbm file, converted to png

With this as a basis, I’m excited to start putting together more complicated patterns.