summaryrefslogtreecommitdiff
path: root/pngmeta/metareader_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'pngmeta/metareader_test.go')
-rw-r--r--pngmeta/metareader_test.go164
1 files changed, 164 insertions, 0 deletions
diff --git a/pngmeta/metareader_test.go b/pngmeta/metareader_test.go
index 5d9a0e2..f88de06 100644
--- a/pngmeta/metareader_test.go
+++ b/pngmeta/metareader_test.go
@@ -1,7 +1,19 @@
package pngmeta
import (
+ "bytes"
+ "gf-lt/models"
+ "encoding/base64"
+ "encoding/binary"
+ "encoding/json"
+ "errors"
"fmt"
+ "image"
+ "image/color"
+ "image/png"
+ "io"
+ "os"
+ "path/filepath"
"testing"
)
@@ -28,3 +40,155 @@ func TestReadMeta(t *testing.T) {
})
}
}
+
+// Test helper: Create a simple PNG image with test shapes
+func createTestImage(t *testing.T) string {
+ img := image.NewRGBA(image.Rect(0, 0, 200, 200))
+ // Fill background with white
+ for y := 0; y < 200; y++ {
+ for x := 0; x < 200; x++ {
+ img.Set(x, y, color.White)
+ }
+ }
+ // Draw a red square
+ for y := 50; y < 150; y++ {
+ for x := 50; x < 150; x++ {
+ img.Set(x, y, color.RGBA{R: 255, A: 255})
+ }
+ }
+ // Draw a blue circle
+ center := image.Point{100, 100}
+ radius := 40
+ for y := center.Y - radius; y <= center.Y+radius; y++ {
+ for x := center.X - radius; x <= center.X+radius; x++ {
+ dx := x - center.X
+ dy := y - center.Y
+ if dx*dx+dy*dy <= radius*radius {
+ img.Set(x, y, color.RGBA{B: 255, A: 255})
+ }
+ }
+ }
+ // Create temp file
+ tmpDir := t.TempDir()
+ fpath := filepath.Join(tmpDir, "test-image.png")
+ f, err := os.Create(fpath)
+ if err != nil {
+ t.Fatalf("Error creating temp file: %v", err)
+ }
+ defer f.Close()
+ if err := png.Encode(f, img); err != nil {
+ t.Fatalf("Error encoding PNG: %v", err)
+ }
+ return fpath
+}
+
+func TestWriteToPng(t *testing.T) {
+ // Create test image
+ srcPath := createTestImage(t)
+ dstPath := filepath.Join(filepath.Dir(srcPath), "output.png")
+ // dstPath := "test.png"
+ // Create test metadata
+ metadata := &models.CharCardSpec{
+ Description: "Test image containing a red square and blue circle on white background",
+ }
+ // Embed metadata
+ if err := WriteToPng(metadata, srcPath, dstPath); err != nil {
+ t.Fatalf("WriteToPng failed: %v", err)
+ }
+ // Verify output file exists
+ if _, err := os.Stat(dstPath); os.IsNotExist(err) {
+ t.Fatalf("Output file not created: %v", err)
+ }
+ // Read and verify metadata
+ t.Run("VerifyMetadata", func(t *testing.T) {
+ data, err := os.ReadFile(dstPath)
+ if err != nil {
+ t.Fatalf("Error reading output file: %v", err)
+ }
+ // Verify PNG header
+ if string(data[:8]) != pngHeader {
+ t.Errorf("Invalid PNG header")
+ }
+ // Extract metadata
+ embedded := extractMetadata(t, data)
+ if embedded.Description != metadata.Description {
+ t.Errorf("Metadata mismatch\nWant: %q\nGot: %q",
+ metadata.Description, embedded.Description)
+ }
+ })
+ // Optional: Add cleanup if needed
+ // t.Cleanup(func() {
+ // os.Remove(dstPath)
+ // })
+}
+
+// Helper to extract embedded metadata from PNG bytes
+func extractMetadata(t *testing.T, data []byte) *models.CharCardSpec {
+ r := bytes.NewReader(data[8:]) // Skip PNG header
+ for {
+ var length uint32
+ if err := binary.Read(r, binary.BigEndian, &length); err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
+ t.Fatalf("Error reading chunk length: %v", err)
+ }
+ chunkType := make([]byte, 4)
+ if _, err := r.Read(chunkType); err != nil {
+ t.Fatalf("Error reading chunk type: %v", err)
+ }
+ // Read chunk data
+ chunkData := make([]byte, length)
+ if _, err := r.Read(chunkData); err != nil {
+ t.Fatalf("Error reading chunk data: %v", err)
+ }
+ // Read and discard CRC
+ if _, err := r.Read(make([]byte, 4)); err != nil {
+ t.Fatalf("Error reading CRC: %v", err)
+ }
+ if string(chunkType) == embType {
+ parts := bytes.SplitN(chunkData, []byte{0}, 2)
+ if len(parts) != 2 {
+ t.Fatalf("Invalid tEXt chunk format")
+ }
+ decoded, err := base64.StdEncoding.DecodeString(string(parts[1]))
+ if err != nil {
+ t.Fatalf("Base64 decode error: %v", err)
+ }
+ var result models.CharCardSpec
+ if err := json.Unmarshal(decoded, &result); err != nil {
+ t.Fatalf("JSON unmarshal error: %v", err)
+ }
+ return &result
+ }
+ }
+ t.Fatal("Metadata not found in PNG")
+ return nil
+}
+
+func readTextChunk(t *testing.T, r io.ReadSeeker) *models.CharCardSpec {
+ var length uint32
+ binary.Read(r, binary.BigEndian, &length)
+ chunkType := make([]byte, 4)
+ r.Read(chunkType)
+ data := make([]byte, length)
+ r.Read(data)
+ // Read CRC (but skip validation for test purposes)
+ crc := make([]byte, 4)
+ r.Read(crc)
+ parts := bytes.SplitN(data, []byte{0}, 2) // Split key-value pair
+ if len(parts) != 2 {
+ t.Fatalf("Invalid tEXt chunk format")
+ }
+ // key := string(parts[0])
+ value := parts[1]
+ decoded, err := base64.StdEncoding.DecodeString(string(value))
+ if err != nil {
+ t.Fatalf("Base64 decode error: %v; value: %s", err, string(value))
+ }
+ var result models.CharCardSpec
+ if err := json.Unmarshal(decoded, &result); err != nil {
+ t.Fatalf("JSON unmarshal error: %v", err)
+ }
+ return &result
+}