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 x := startX; x < stopX; x++ { for y := startY; y < stopY; y++ { 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 }