From b298cb019d019dbaf8aa3a3489a5d851798b26af Mon Sep 17 00:00:00 2001 From: Balakrishnan Balasubramanian Date: Fri, 11 Aug 2023 23:20:53 -0400 Subject: [PATCH] add Make collage --- collage/collage.go | 52 +++++++++++++++++++++++++++++++++-------- collage/collage_test.go | 50 +++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 15 deletions(-) diff --git a/collage/collage.go b/collage/collage.go index 61db586..832e17b 100644 --- a/collage/collage.go +++ b/collage/collage.go @@ -3,10 +3,13 @@ package collage import ( "errors" - "fmt" "image" + "image/draw" + "image/jpeg" "io" "io/fs" + + "go.oneofone.dev/resize" ) type Dimension struct { @@ -31,24 +34,53 @@ func (r Rectangle) ToImgRect() image.Rectangle { } } +type Photo struct { + ImageName string `json:"image"` + Crop Rectangle `json:"crop"` + Frame Rectangle `json:"frame"` +} + type Request struct { BackgroundImage string `json:"background_image"` Aspect Dimension `json:"aspect"` Dimension Dimension `json:"dimension"` - Photos []struct { - ImageName string `json:"image"` - Crop Rectangle `json:"crop"` - Frame Rectangle `json:"frame"` - } `json:"photos"` + Photos []Photo `json:"photos"` } -func Make(req Request, source fs.FS, output io.Writer) { +func Make(req Request, source fs.FS, output io.Writer) error { rec := image.Rect(0, 0, int(req.Aspect.Width), int(req.Aspect.Height)) canvas := image.NewRGBA64(rec) - for photo := range req.Photos { - fmt.Println(photo) + for _, photo := range req.Photos { + img, err := GetImage(source, photo.ImageName) + if err != nil { + return err + } + croppedImage, err := Crop(img, photo.Crop) + if err != nil { + return err + } + + destRect := FrameTranslate(req.Aspect, req.Dimension, photo.Frame).ToImgRect() + resizedImg := resize.Resize(uint(destRect.Dx()), uint(destRect.Dy()), croppedImage, resize.Lanczos3) + draw.Draw(canvas, destRect, resizedImg, image.Point{0, 0}, draw.Src) + } + var opt jpeg.Options + opt.Quality = 100 + + return jpeg.Encode(output, canvas, &opt) +} + +func FrameTranslate(resolution Dimension, frameSize Dimension, frame Rectangle) Rectangle { + newX := func(oldX uint) uint { + return oldX * resolution.Width / frameSize.Width + } + newY := func(oldY uint) uint { + return oldY * resolution.Height / frameSize.Height + } + return Rectangle{ + Start: Point{newX(frame.Start.X), newY(frame.Start.Y)}, + End: Point{newX(frame.End.X), newY(frame.End.Y)}, } - fmt.Println(canvas) } type HasSubImage interface { diff --git a/collage/collage_test.go b/collage/collage_test.go index 49fa31c..5971111 100644 --- a/collage/collage_test.go +++ b/collage/collage_test.go @@ -26,12 +26,52 @@ func init() { } func TestMake(t *testing.T) { - t.Log("Test was run") - img1f, err := testDataFS.Open("img1.jpg") - if err != nil { - t.Fatalf("opening image failed %v", err) + req := Request{ + BackgroundImage: "", + Aspect: Dimension{ + Width: 816 * 4, + Height: 528 * 4 * 2, + }, + Dimension: Dimension{ + Width: 816, + Height: 528 * 2, + }, + Photos: []Photo{ + { + ImageName: "img1.jpg", + Crop: Rectangle{ + Start: Point{ + X: 431, + Y: 697, + }, + End: Point{ + X: 2514, + Y: 2047, + }, + }, + Frame: Rectangle{ + Start: Point{ + X: 0, + Y: 0, + }, + End: Point{ + X: 816, + Y: 528, + }, + }, + }, + }, } - fmt.Printf("%#v\n", img1f) + out, err := os.Create("./test_op.jpg") + if err != nil { + t.Fatalf("failed to create ouput image file %v", err) + } + + err = Make(req, testDataFS, out) + if err != nil { + t.Fatalf("failed to make collage %v", err) + } + } func TestCrop(t *testing.T) {