|
|
@@ -0,0 +1,111 @@
|
|
|
+package agi
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "image"
|
|
|
+ "image/jpeg"
|
|
|
+ "os"
|
|
|
+ "path/filepath"
|
|
|
+ "testing"
|
|
|
+ "time"
|
|
|
+
|
|
|
+ "imuslab.com/arozos/mod/filesystem"
|
|
|
+ "imuslab.com/arozos/mod/filesystem/abstractions/localfs"
|
|
|
+)
|
|
|
+
|
|
|
+// newImageTestFSH creates a FileSystemHandler backed by a temporary local
|
|
|
+// directory for exercising the imagelib helpers.
|
|
|
+func newImageTestFSH(t *testing.T) (*filesystem.FileSystemHandler, string) {
|
|
|
+ t.Helper()
|
|
|
+ dir := t.TempDir()
|
|
|
+ abs := localfs.NewLocalFileSystemAbstraction("TEST", dir+"/", "public", false)
|
|
|
+ fsh := &filesystem.FileSystemHandler{
|
|
|
+ Name: "test",
|
|
|
+ UUID: "TEST",
|
|
|
+ Path: dir + "/",
|
|
|
+ ReadOnly: false,
|
|
|
+ Hierarchy: "public",
|
|
|
+ InitiationTime: time.Now().Unix(),
|
|
|
+ FileSystemAbstraction: abs,
|
|
|
+ Filesystem: "ext4",
|
|
|
+ }
|
|
|
+ return fsh, dir
|
|
|
+}
|
|
|
+
|
|
|
+// smallJPEGBytes returns a small solid image encoded as JPEG. Written into a
|
|
|
+// RAW-extension file it stands in for the embedded preview that real RAW photos
|
|
|
+// carry, which is what convertRawToJPEG extracts.
|
|
|
+func smallJPEGBytes(t *testing.T) []byte {
|
|
|
+ t.Helper()
|
|
|
+ img := image.NewRGBA(image.Rect(0, 0, 32, 24))
|
|
|
+ var buf bytes.Buffer
|
|
|
+ if err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: 90}); err != nil {
|
|
|
+ t.Fatalf("jpeg encode: %v", err)
|
|
|
+ }
|
|
|
+ return buf.Bytes()
|
|
|
+}
|
|
|
+
|
|
|
+func TestConvertRawToJPEG(t *testing.T) {
|
|
|
+ jpegBytes := smallJPEGBytes(t)
|
|
|
+
|
|
|
+ t.Run("RAW with embedded JPEG is converted", func(t *testing.T) {
|
|
|
+ fsh, dir := newImageTestFSH(t)
|
|
|
+ src := filepath.Join(dir, "photo.arw")
|
|
|
+ if err := os.WriteFile(src, jpegBytes, 0644); err != nil {
|
|
|
+ t.Fatalf("write src: %v", err)
|
|
|
+ }
|
|
|
+ dst := filepath.Join(dir, "photo.jpg")
|
|
|
+
|
|
|
+ if err := convertRawToJPEG(fsh, src, fsh, dst); err != nil {
|
|
|
+ t.Fatalf("convertRawToJPEG returned error: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ out, err := os.ReadFile(dst)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("output not written: %v", err)
|
|
|
+ }
|
|
|
+ img, format, err := image.Decode(bytes.NewReader(out))
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("output is not a decodable image: %v", err)
|
|
|
+ }
|
|
|
+ if format != "jpeg" {
|
|
|
+ t.Errorf("expected jpeg output, got %q", format)
|
|
|
+ }
|
|
|
+ if b := img.Bounds(); b.Dx() != 32 || b.Dy() != 24 {
|
|
|
+ t.Errorf("unexpected output dimensions: %dx%d", b.Dx(), b.Dy())
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ t.Run("non-RAW source is rejected", func(t *testing.T) {
|
|
|
+ fsh, dir := newImageTestFSH(t)
|
|
|
+ src := filepath.Join(dir, "photo.png")
|
|
|
+ if err := os.WriteFile(src, jpegBytes, 0644); err != nil {
|
|
|
+ t.Fatalf("write src: %v", err)
|
|
|
+ }
|
|
|
+ if err := convertRawToJPEG(fsh, src, fsh, filepath.Join(dir, "out.jpg")); err == nil {
|
|
|
+ t.Errorf("expected error for non-RAW source, got nil")
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ t.Run("non-JPEG output extension is rejected", func(t *testing.T) {
|
|
|
+ fsh, dir := newImageTestFSH(t)
|
|
|
+ src := filepath.Join(dir, "photo.arw")
|
|
|
+ if err := os.WriteFile(src, jpegBytes, 0644); err != nil {
|
|
|
+ t.Fatalf("write src: %v", err)
|
|
|
+ }
|
|
|
+ if err := convertRawToJPEG(fsh, src, fsh, filepath.Join(dir, "out.png")); err == nil {
|
|
|
+ t.Errorf("expected error for non-JPEG output, got nil")
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ t.Run("RAW without embedded JPEG fails cleanly", func(t *testing.T) {
|
|
|
+ fsh, dir := newImageTestFSH(t)
|
|
|
+ src := filepath.Join(dir, "garbage.cr2")
|
|
|
+ if err := os.WriteFile(src, []byte("not a real raw file"), 0644); err != nil {
|
|
|
+ t.Fatalf("write src: %v", err)
|
|
|
+ }
|
|
|
+ if err := convertRawToJPEG(fsh, src, fsh, filepath.Join(dir, "out.jpg")); err == nil {
|
|
|
+ t.Errorf("expected error for RAW without embedded JPEG, got nil")
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|