On-the-fly Spinneret Web Graphics

Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 21,044
edited March 2011 in Accessories Vote Up0Vote Down
In my Spinneret webcam, I use Spin methods to generate the BMP outputs for both the camera image and and the little colored bar graphs that show the camera's exposure settings and pan position. The bar graphs are generated one horizontal line at a time, starting at the bottom, from a generalized rectangle-pair drawing method. The two rectangles are nested and can have different colors. Here's an example that shows the parameters used to define it:


To create such an image, you can go here:

Feel free to experiment by changing the parameters to get different sizes and colors. As simple as it is, two nested rectangles like this can be used to create color swatches, horizontal and vertical bar meters, a point locatable on a two-dimensional rectangular background (for position tracking, say), among other graphical devices.

Here's the code that generates the rectangles:

  long zero[16]

PUB do_rects(rwidth, rheight, rx, ry, rdx, rdy, rbg, rfg) | row_size, row, char, i, j, pix

  rwidth := rwidth #> 0 <# 512
  rheight := rheight #> 0 <# 512
  rx := rx #> 0 <# rwidth - 1
  ry := ry #> 0 <# rheight - 1
  rdx := rdx #> 0 <# rwidth - rx
  rdy := rdy #> 0 <# rheight - ry
  row_size := bitmap_header(rwidth, rheight, 1, @rbg)
  repeat ry
    [b]server.array[/b](@zero, row_size)
  repeat rdy
    repeat i from 0 to row_size - 1
      repeat j from 0 to 7
        pix := i << 3 + j
        char := char << 1 - (pix => rx and pix < rx + rdx)
      byte[@buffer][i] := char
    [b]server.array[/b](@buffer, row_size)
  repeat (rheight - ry - rdy)
    [b]server.array[/b](@zero, row_size)
PUB bitmap_header(img_width, img_height, bits_per_pixel, color_array) | i, j, colors, row_size

  wrword_bytes(@bmp_width, img_width)
  wrword_bytes(@bmp_height, img_height)
  bmp_bitspp := bits_per_pixel
  row_size := (bits_per_pixel * img_width + 31) >> 5 << 2
  colors := 1 << bits_per_pixel
  wrword_bytes(@bmp_data_addr, $1a + 3 * colors)
  wrlong_bytes(@bmp_file_size, $1a + 3 * colors + row_size * ||img_height)
  [b]server.array[/b](@bmp_hdr, @bmp_hdr_end - @bmp_hdr)
  repeat i from 0 to colors - 1
    repeat j from 0 to 2
      [b]server.out[/b](byte[color_array][i << 2 + j])
  return row_size                             

PUB wrlong_bytes(addr, data)

  wrword_bytes(addr, data)
  wrword_bytes(addr + 2, data >> 16)

PUB wrword_bytes(addr, data)

  byte[addr++] := data
  byte[addr] := data >> 8


bmp_hdr       byte      "Content-type: image/bmp",EOL
              byte      "Cache-control: no-store",EOL,EOL
              byte      "BM"
bmp_file_size byte      $4a,$18,0,0
              byte      0,0,0,0
bmp_data_addr byte      $4a,0
              byte      0,0,$0c,0,0,0
bmp_width     byte      $80,0
bmp_height    byte      $60,0
              byte      $01,0
bmp_bitspp    byte      $04,0
The highlighted methods in the server object are as follows:
  • custom_content: Begin the HTTP header:
    HTTP/1.1 200 OK
    Connection: close
  • array: Output a block of bytes, beginning at the specified address and with a specified length.
  • out: Output a single byte.
  • end_custom_content: Close the socket, thus ending the transmission.
I plan to expand on the on-the-fly graphics theme quite a bit in the coming weeks. It will have to be done in PASM, though, for speed.

400 x 281 - 8K
“Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery


  • 2 Comments sorted by Date Added Votes
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 21,044
    edited March 2011 Vote Up0Vote Down
    'Forgot to mention: Total width and height are currently restricted to 512 pixels max.

    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
Sign In or Register to comment.