Shop OBEX P1 Docs P2 Docs Learn Events
On-the-fly Spinneret Web Graphics — Parallax Forums

On-the-fly Spinneret Web Graphics

Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
edited 2011-03-01 15:28 in Accessories
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:

attachment.php?attachmentid=78791&d=1299007503

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:
VAR

  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)
  [b]server.end_custom_content[/b]
  
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.custom_content[/b]
  [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

DAT

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
bmp_hdr_end
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.

-Phil

Comments

Sign In or Register to comment.