Initial orientator
This commit is contained in:
80
internal/pipeline/imgrot.go
Normal file
80
internal/pipeline/imgrot.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package pipeline
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/image/tiff"
|
||||
_ "golang.org/x/image/webp" // decode-only; we re-encode webp as png
|
||||
)
|
||||
|
||||
// RotateImage rotates src clockwise by angle (must be 0/90/180/270).
|
||||
func RotateImage(src image.Image, angle int) image.Image {
|
||||
angle = ((angle % 360) + 360) % 360
|
||||
if angle == 0 {
|
||||
return src
|
||||
}
|
||||
b := src.Bounds()
|
||||
w, h := b.Dx(), b.Dy()
|
||||
switch angle {
|
||||
case 180:
|
||||
dst := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
dst.Set(w-1-x, h-1-y, src.At(b.Min.X+x, b.Min.Y+y))
|
||||
}
|
||||
}
|
||||
return dst
|
||||
case 90:
|
||||
dst := image.NewRGBA(image.Rect(0, 0, h, w))
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
dst.Set(h-1-y, x, src.At(b.Min.X+x, b.Min.Y+y))
|
||||
}
|
||||
}
|
||||
return dst
|
||||
case 270:
|
||||
dst := image.NewRGBA(image.Rect(0, 0, h, w))
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
dst.Set(y, w-1-x, src.At(b.Min.X+x, b.Min.Y+y))
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
return src
|
||||
}
|
||||
|
||||
// EncodeImage re-encodes img using format hint from the original filename / detected format.
|
||||
// Falls back to PNG when format is not directly writable.
|
||||
func EncodeImage(img image.Image, format string) ([]byte, string, error) {
|
||||
var buf bytes.Buffer
|
||||
switch strings.ToLower(format) {
|
||||
case "jpeg", "jpg":
|
||||
if err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: 92}); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return buf.Bytes(), "jpg", nil
|
||||
case "tiff", "tif":
|
||||
if err := tiff.Encode(&buf, img, &tiff.Options{Compression: tiff.Deflate}); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return buf.Bytes(), "tiff", nil
|
||||
case "png", "":
|
||||
if err := png.Encode(&buf, img); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return buf.Bytes(), "png", nil
|
||||
case "webp":
|
||||
// Re-encode to PNG (no webp encoder in stdlib/x/image).
|
||||
if err := png.Encode(&buf, img); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return buf.Bytes(), "png", nil
|
||||
}
|
||||
return nil, "", fmt.Errorf("unsupported format: %s", format)
|
||||
}
|
||||
Reference in New Issue
Block a user