On-the-fly Spinneret Web Graphics
Phil Pilgrim (PhiPi)
Posts: 23,514
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:
-Phil
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.
-Phil


Comments
-Phil