186 lines
3.2 KiB
Go
186 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"math"
|
|
"sync"
|
|
"time"
|
|
|
|
"golang.org/x/image/bmp"
|
|
)
|
|
|
|
func SnakeGenerateByteImagePart(data []byte, startX, startY, stopX, stopY, xLen, yLen int, img *image.RGBA) {
|
|
for y := startY; y < stopY; y++ {
|
|
for x := startX; x < stopX; x++ {
|
|
|
|
B := byte(0)
|
|
|
|
if x+y*xLen < len(data) {
|
|
B = data[x+y*xLen]
|
|
}
|
|
|
|
r, g, b := byte(0), byte(0), byte(0)
|
|
|
|
if B > 0 {
|
|
r = B >> 6
|
|
g = (B >> 4) & 3
|
|
b = (B >> 2) & 3
|
|
a := B & 3
|
|
|
|
r = (r << 2) + a
|
|
g = (g << 2) + a
|
|
b = (b << 2) + a
|
|
|
|
r <<= 4
|
|
g <<= 4
|
|
b <<= 4
|
|
}
|
|
|
|
img.Set(x, y, color.RGBA{r, g, b, 0xFF})
|
|
}
|
|
}
|
|
}
|
|
|
|
func SnakeGenerateByteImage(data []byte) ([]byte, error) {
|
|
length := len(data)
|
|
xLen := int(math.Floor(math.Sqrt(float64(length))))
|
|
yLen := xLen
|
|
|
|
if yLen*xLen < int(length) {
|
|
yLen++
|
|
}
|
|
|
|
img := image.NewRGBA(image.Rect(0, 0, xLen-1, yLen-1))
|
|
|
|
fmt.Printf("Start generating image of data with %d bytes\n", length)
|
|
|
|
startTime := time.Now()
|
|
|
|
var wg sync.WaitGroup
|
|
wg.Add(4)
|
|
|
|
go func() {
|
|
SnakeGenerateByteImagePart(data, 0, 0, xLen/2, yLen/2, xLen, yLen, img)
|
|
wg.Done()
|
|
}()
|
|
|
|
go func() {
|
|
SnakeGenerateByteImagePart(data, xLen/2, 0, xLen, yLen/2, xLen, yLen, img)
|
|
wg.Done()
|
|
}()
|
|
|
|
go func() {
|
|
SnakeGenerateByteImagePart(data, 0, yLen/2, xLen/2, yLen, xLen, yLen, img)
|
|
wg.Done()
|
|
}()
|
|
|
|
go func() {
|
|
SnakeGenerateByteImagePart(data, xLen/2, yLen/2, xLen, yLen, xLen, yLen, img)
|
|
wg.Done()
|
|
}()
|
|
|
|
wg.Wait()
|
|
|
|
endTime := time.Now()
|
|
|
|
fmt.Printf("Generated in %f seconds\n", endTime.Sub(startTime).Seconds())
|
|
|
|
fmt.Println("Start encoding image as bmp")
|
|
|
|
startTime = time.Now()
|
|
|
|
buffer := new(bytes.Buffer)
|
|
|
|
err := bmp.Encode(buffer, img)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
endTime = time.Now()
|
|
|
|
fmt.Printf("Encoded in %f seconds\n", endTime.Sub(startTime).Seconds())
|
|
|
|
return buffer.Bytes(), nil
|
|
}
|
|
|
|
func HilbertCurveGenerateByteImage(data []byte) ([]byte, error) {
|
|
length := len(data)
|
|
|
|
fmt.Printf("Start generating hilbert curve")
|
|
startTime := time.Now()
|
|
|
|
h := NewHilbertCurve()
|
|
|
|
for length > h.Length() {
|
|
h.Expand()
|
|
}
|
|
|
|
endTime := time.Now()
|
|
|
|
fmt.Printf("Generated a hilbert curve of order %d in %f seconds", h.Order(), endTime.Sub(startTime).Seconds())
|
|
|
|
fmt.Printf("Start generating image of data with %d bytes\n", length)
|
|
|
|
startTime = time.Now()
|
|
|
|
curve := h.Get()
|
|
|
|
img := image.NewRGBA(image.Rect(0, 0, curve.width-1, curve.height-1))
|
|
|
|
for y := 0; y < curve.height; y++ {
|
|
for x := 0; x < curve.width; x++ {
|
|
B := byte(0)
|
|
|
|
pos := curve.At(x, y)
|
|
|
|
if pos < len(data) {
|
|
B = data[pos]
|
|
}
|
|
|
|
r, g, b := byte(0), byte(0), byte(0)
|
|
|
|
if B > 0 {
|
|
r = B >> 6
|
|
g = (B >> 4) & 3
|
|
b = (B >> 2) & 3
|
|
a := B & 3
|
|
|
|
r = (r << 2) + a
|
|
g = (g << 2) + a
|
|
b = (b << 2) + a
|
|
|
|
r <<= 4
|
|
g <<= 4
|
|
b <<= 4
|
|
}
|
|
|
|
img.Set(x, y, color.RGBA{r, g, b, 0xFF})
|
|
}
|
|
}
|
|
|
|
endTime = time.Now()
|
|
|
|
fmt.Printf("Generated in %f seconds\n", endTime.Sub(startTime).Seconds())
|
|
|
|
fmt.Println("Start encoding image as bmp")
|
|
|
|
startTime = time.Now()
|
|
|
|
buffer := new(bytes.Buffer)
|
|
|
|
err := bmp.Encode(buffer, img)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
endTime = time.Now()
|
|
|
|
fmt.Printf("Encoded in %f seconds\n", endTime.Sub(startTime).Seconds())
|
|
|
|
return buffer.Bytes(), nil
|
|
}
|