2020-02-05 19:26:43 +01:00
package pixelflut
import (
2020-02-06 13:39:24 +01:00
"fmt"
"image"
"image/color"
2020-02-05 19:26:43 +01:00
"math/rand"
)
// Commands represent a list of messages to be sent to a pixelflut server.
2020-02-06 13:39:24 +01:00
type commands [ ] [ ] byte
2020-02-05 19:26:43 +01:00
// Chunk splits commands into equally sized chunks, while flattening each chunk
// so that all commands are concatenated as a single `[]byte`.
2020-02-06 13:39:24 +01:00
func ( c commands ) Chunk ( numChunks int ) [ ] [ ] byte {
2020-02-05 19:26:43 +01:00
chunks := make ( [ ] [ ] byte , numChunks )
chunkLength := len ( c ) / numChunks
for i := 0 ; i < numChunks ; i ++ {
cmdOffset := i * chunkLength
for j := 0 ; j < chunkLength ; j ++ {
chunks [ i ] = append ( chunks [ i ] , c [ cmdOffset + j ] ... )
}
}
return chunks
}
// Shuffle reorders commands randomly, in place.
2020-02-06 13:39:24 +01:00
func ( c commands ) Shuffle ( ) {
2020-02-05 19:26:43 +01:00
for i := range c {
j := rand . Intn ( i + 1 )
c [ i ] , c [ j ] = c [ j ] , c [ i ]
}
}
2020-02-06 13:39:24 +01:00
2020-12-29 18:28:19 +01:00
// AddOffset uses the OFFSET command to send the image at a specific place (not supported by all servers. example: https://github.com/TobleMiner/shoreline)
func OffsetCmd ( x , y int ) [ ] byte {
return [ ] byte ( fmt . Sprintf ( "OFFSET %d %d\n" , x , y ) )
}
2020-02-06 13:39:24 +01:00
// CommandsFromImage converts an image to the respective pixelflut commands
2020-02-14 12:39:16 +01:00
func commandsFromImage ( img * image . NRGBA , offset image . Point ) ( cmds commands ) {
2020-02-06 13:39:24 +01:00
b := img . Bounds ( )
cmds = make ( [ ] [ ] byte , b . Size ( ) . X * b . Size ( ) . Y )
numCmds := 0
for x := b . Min . X ; x < b . Max . X ; x ++ {
for y := b . Min . Y ; y < b . Max . Y ; y ++ {
2020-02-14 12:39:16 +01:00
c := img . At ( x , y ) . ( color . NRGBA )
2020-02-06 13:39:24 +01:00
// ignore transparent pixels
if c . A == 0 {
continue
}
2020-12-28 09:33:52 +01:00
var cmd string
if c . A != 255 {
cmd = fmt . Sprintf ( "PX %d %d %.2x%.2x%.2x%.2x\n" ,
x + offset . X , y + offset . Y , c . R , c . G , c . B , c . A )
} else {
// @speed: this sprintf call is quite slow..
cmd = fmt . Sprintf ( "PX %d %d %.2x%.2x%.2x\n" ,
x + offset . X , y + offset . Y , c . R , c . G , c . B )
}
2020-02-06 13:39:24 +01:00
cmds [ numCmds ] = [ ] byte ( cmd )
numCmds ++
}
}
return cmds [ : numCmds ]
}
func cmdsFetchImage ( bounds image . Rectangle ) ( cmds commands ) {
cmds = make ( [ ] [ ] byte , bounds . Size ( ) . X * bounds . Size ( ) . Y )
numCmds := 0
for x := bounds . Min . X ; x < bounds . Max . X ; x ++ {
for y := bounds . Min . Y ; y < bounds . Max . Y ; y ++ {
cmd := fmt . Sprintf ( "PX %d %d\n" , x , y )
cmds [ numCmds ] = [ ] byte ( cmd )
numCmds ++
}
}
return cmds
}