The PBM image format- portable pixmap format

The P6 version of this is a straight expression of the R, G and B components of each pixel. The preamble is much simpler than that used for BMP format images- has a 'P6' identifier, a line or more of comments, a line of space-separated width, height and number of levels ( 256), and the data. The preamble lines are separated by CR characters, but the data is just consecutive.

Seen in a text editor the preamble is therefore human-radable, although the data will probably appear as weird UniCode characters..

P6
# Created by GIMP version 2.10.22 PNM plug-in
200 200
255
ÃqLÅqMÆqNÇrM¿kG¼fD¹d?´_ª....RGB data bytes....

A BMP displayed in a text editor shows nothing humanly intelligible beyond the first two bytew, 'BM'!

Further examples in LB

When coding in LB, you can create a pixel array pixel( x, y) and set values in it, then so easily save as a PBM. I have already put up the histogram /display as black-and-white based on above or below median. But I have also played with many other versions. Many can be done directly and much faster by a good painting package like PhotoShop or the GIMP. Others are up to your wild imagination- swap colors around, creat swirls and waves, modulate brightness- the sky is the limit.


Code


      '        create a ppm file
      '        fill an image with a plain RGB color,
      '        set a given pixel with a color,
      '        get the color of a pixel.
      '        Bresenham draw line
      '        Convert image to grayscale;
      '        Compute the histogram
      '             Find the median: defined as the luminance such that the image has an approximately
      '                 equal number of pixels with lesser and greater luminance.
      '             Replace each pixel of luminance lesser than the median to black, and others to white.

      ' Load and display a ppm file

      nomainwin

      dim redVal( 256), grnVal( 256), bluVal( 256)

      open "lenaP6.ppm" for input as #fIn
        data$     =input$( #fIn, lof( #fIn))
      close #fIn

      id$ =word$( data$, 1, chr$( 10))
      'print id$
      if id$ <>"P6" then end

      comment$ =word$( data$, 2, chr$( 10))
      'print comment$

      size$     =word$( data$, 3, chr$( 10))

      Width     =val( size$)
      space     =instr( size$, " ")
      Height    =val( mid$( size$, space))
      'print Width, Height

      pixelData$ =word$( data$, 5, chr$( 10))

      WindowWidth  =1610
      WindowHeight = 500

      bg$ ="200 200 80"

      open "Read and display ppm" for graphics_nsb as #wg

      #wg "trapclose quit"
      #wg "down ; fill "; bg$; " ; backcolor "; bg$
      #wg "font Arial 14"

      call showText 4, 220, "Read a ppm file; display greyscale brightness-                      " +_
        "and examine fractions of each of R, G, B, and display as histogram.              "+_
        "           Display with R and B swapped, or R inverted."

      po =0
      for y =0 to Height -1
        for x =0 to Width -1
          re    =asc( mid$( pixelData$, po +1, 1)): redVal( re) =redVal( re) +re
          gr    =asc( mid$( pixelData$, po +2, 1)): grnVal( gr) =grnVal( gr) +gr
          bl    =asc( mid$( pixelData$, po +3, 1)): bluVal( bl) =bluVal( bl) +bl
          #wg "color "; str$( re); " "; str$( gr); " "; str$( bl)
          #wg "set "; x +2; " "; y +2
          gr    =asc( mid$( pixelData$, po +2, 1))
          bl    =asc( mid$( pixelData$, po +3, 1))

          lv     = int( 0.3 *re + 0.59 *gr + 0.11 *bl +0.5)

          #wg "color "; str$( re); " "; str$( gr); " "; str$( bl)
          #wg "set "; x +2; " "; y +2

          #wg "color "; str$( lv); " "; str$( lv); " "; str$( lv)
          #wg "set "; x +204; " "; y +2

          #wg "color "; str$( bl); " "; str$( gr); " "; str$( re)
          #wg "set "; x +1180; " "; y +2

          #wg "color "; str$( 255 -re); " "; str$( gr); " "; str$( bl)
          #wg "set "; x +1390; " "; y +2

          #wg "color "; str$( re); " 0 0"
          #wg "set "; x +500; " "; y +252

          #wg "color "; "0 "; str$( lv); " 0"
          #wg "set "; x +702; " "; y +252

          #wg "color "; "0 0 "; str$( bl)
          #wg "set "; x +904; " "; y +252

          po =po +3
          scan
        next x
      next y

      oldX =410: oldYr =198:  oldYg =198:  oldYb =198

      '#wg "size 2"

      for i =0 to 255

        nX      = 410 +i *3

        nYr     =198 -int( redVal( i) /Width /Height *100)
        #wg "color red ; up ; goto "; oldX; " "; oldYr
        #wg "down ; goto "; nX; " "; nYr

        nYg     =198 -int( grnVal( i) /Width /Height *100)
        #wg "color darkgreen ; up ; goto "; oldX; " "; oldYg
        #wg "down ; goto "; nX; " "; nYg

        nYb     =198 -int( bluVal( i) /Width /Height *100)
        #wg "color blue ; up ; goto "; oldX; " "; oldYb
        #wg "down ; goto "; nX; " "; nYb

        oldYr   =nYr
        oldYg   =nYg
        oldYb   =nYb

        oldX    =nX
      next i

      #wg "flush"

      wait

      sub quit h$
        close #wg
        end
      end sub

      sub showText x, y, text$
        #wg "up ; goto "; x; " "; y
        #wg "down"
        #wg "\" +text$
      end sub


      end

The image of Lena is on my site and is the standard image for this kind of play...