mirror of
https://github.com/h2non/imaginary.git
synced 2025-12-13 20:37:04 +01:00
This commit is contained in:
@@ -10,9 +10,8 @@ services:
|
||||
dist: focal
|
||||
|
||||
go:
|
||||
- "1.12"
|
||||
- "1.13"
|
||||
# - "1.14"
|
||||
- "1.14"
|
||||
|
||||
env:
|
||||
global:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
ARG GOLANG_VERSION=1.13
|
||||
ARG GOLANG_VERSION=1.14
|
||||
FROM golang:${GOLANG_VERSION} as builder
|
||||
|
||||
ARG IMAGINARY_VERSION=dev
|
||||
ARG LIBVIPS_VERSION=8.9.2
|
||||
ARG GOLANGCILINT_VERSION=1.23.3
|
||||
ARG GOLANGCILINT_VERSION=1.29.0
|
||||
|
||||
# Installs libvips + required libraries
|
||||
RUN DEBIAN_FRONTEND=noninteractive \
|
||||
|
||||
10
README.md
10
README.md
@@ -53,6 +53,7 @@ To get started, take a look the [installation](#installation) steps, [usage](#co
|
||||
- Crop
|
||||
- SmartCrop (based on [libvips built-in algorithm](https://github.com/jcupitt/libvips/blob/master/libvips/conversion/smartcrop.c))
|
||||
- Rotate (with auto-rotate based on EXIF orientation)
|
||||
- AutoRotate with further image transformations (based on EXIF metadata orientation)
|
||||
- Flip (with auto-flip based on EXIF metadata)
|
||||
- Flop
|
||||
- Zoom
|
||||
@@ -883,6 +884,14 @@ The width and height specify a maximum bounding box for the image.
|
||||
#### GET | POST /rotate
|
||||
Accepts: `image/*, multipart/form-data`. Content-Type: `image/*`
|
||||
|
||||
|
||||
#### GET | POST /autorotate
|
||||
Accepts: `image/*, multipart/form-data`. Content-Type: `image/*`
|
||||
|
||||
Automatically rotate the image with no further image transformations based on EXIF orientation metadata.
|
||||
|
||||
Returns a new image with the same size and format as the input image.
|
||||
|
||||
##### Allowed params
|
||||
|
||||
- rotate `int` `required`
|
||||
@@ -1036,6 +1045,7 @@ Self-documented JSON operation schema:
|
||||
- **enlarge** - Same as [`/enlarge`](#get--post-enlarge) endpoint.
|
||||
- **extract** - Same as [`/extract`](#get--post-extract) endpoint.
|
||||
- **rotate** - Same as [`/rotate`](#get--post-rotate) endpoint.
|
||||
- **autorotate** - Same as [`/autorotate`](#get--post-autorotate) endpoint.
|
||||
- **flip** - Same as [`/flip`](#get--post-flip) endpoint.
|
||||
- **flop** - Same as [`/flop`](#get--post-flop) endpoint.
|
||||
- **thumbnail** - Same as [`/thumbnail`](#get--post-thumbnail) endpoint.
|
||||
|
||||
@@ -145,6 +145,7 @@ func formController(w http.ResponseWriter, r *http.Request) {
|
||||
{"Extract", "extract", "top=100&left=100&areawidth=300&areaheight=150"},
|
||||
{"Enlarge", "enlarge", "width=1440&height=900&quality=95"},
|
||||
{"Rotate", "rotate", "rotate=180"},
|
||||
{"AutoRotate", "autorotate", "quality=90"},
|
||||
{"Flip", "flip", ""},
|
||||
{"Flop", "flop", ""},
|
||||
{"Thumbnail", "thumbnail", "width=100"},
|
||||
|
||||
2
go.mod
2
go.mod
@@ -6,7 +6,7 @@ require (
|
||||
github.com/garyburd/redigo v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad // indirect
|
||||
github.com/rs/cors v0.0.0-20170727213201-7af7a1e09ba3
|
||||
github.com/h2non/bimg v1.1.2
|
||||
github.com/h2non/bimg v1.1.4
|
||||
github.com/h2non/filetype v1.1.0
|
||||
gopkg.in/throttled/throttled.v2 v2.0.3
|
||||
)
|
||||
|
||||
2
go.sum
2
go.sum
@@ -1,6 +1,8 @@
|
||||
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||
github.com/h2non/bimg v1.1.2 h1:J75W2eM5FT0KjcwsL2aiy1Ilu0Xy0ENb0sU+HHUJAvw=
|
||||
github.com/h2non/bimg v1.1.2/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8=
|
||||
github.com/h2non/bimg v1.1.4 h1:6qf7qDo3d9axbNUOcSoQmzleBCMTcQ1PwF3FgGhX4O0=
|
||||
github.com/h2non/bimg v1.1.4/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8=
|
||||
github.com/h2non/filetype v1.1.0 h1:Or/gjocJrJRNK/Cri/TDEKFjAR+cfG6eK65NGYB6gBA=
|
||||
github.com/h2non/filetype v1.1.0/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad h1:eMxs9EL0PvIGS9TTtxg4R+JxuPGav82J8rA+GFnY7po=
|
||||
|
||||
41
image.go
41
image.go
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net/http"
|
||||
@@ -221,6 +222,31 @@ func Rotate(buf []byte, o ImageOptions) (Image, error) {
|
||||
return Process(buf, opts)
|
||||
}
|
||||
|
||||
func AutoRotate(buf []byte, o ImageOptions) (out Image, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
switch value := r.(type) {
|
||||
case error:
|
||||
err = value
|
||||
case string:
|
||||
err = errors.New(value)
|
||||
default:
|
||||
err = errors.New("libvips internal error")
|
||||
}
|
||||
out = Image{}
|
||||
}
|
||||
}()
|
||||
|
||||
// Resize image via bimg
|
||||
ibuf, err := bimg.NewImage(buf).AutoRotate()
|
||||
if err != nil {
|
||||
return Image{}, err
|
||||
}
|
||||
|
||||
mime := GetImageMimeType(bimg.DetermineImageType(ibuf))
|
||||
return Image{Body: ibuf, Mime: mime}, nil
|
||||
}
|
||||
|
||||
func Flip(buf []byte, o ImageOptions) (Image, error) {
|
||||
opts := BimgOptions(o)
|
||||
opts.Flip = true
|
||||
@@ -406,11 +432,20 @@ func Process(buf []byte, opts bimg.Options) (out Image, err error) {
|
||||
}
|
||||
}()
|
||||
|
||||
buf, err = bimg.Resize(buf, opts)
|
||||
// Resize image via bimg
|
||||
ibuf, err := bimg.Resize(buf, opts)
|
||||
|
||||
// Handle specific type encode errors gracefully
|
||||
if err != nil && strings.Contains(err.Error(), "encode") && (opts.Type == bimg.WEBP || opts.Type == bimg.HEIF) {
|
||||
// Always fallback to JPEG
|
||||
opts.Type = bimg.JPEG
|
||||
ibuf, err = bimg.Resize(buf, opts)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return Image{}, err
|
||||
}
|
||||
|
||||
mime := GetImageMimeType(bimg.DetermineImageType(buf))
|
||||
return Image{Body: buf, Mime: mime}, nil
|
||||
mime := GetImageMimeType(bimg.DetermineImageType(ibuf))
|
||||
return Image{Body: ibuf, Mime: mime}, nil
|
||||
}
|
||||
|
||||
@@ -93,6 +93,20 @@ func TestImageFit(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageAutoRotate(t *testing.T) {
|
||||
buf, _ := ioutil.ReadAll(readFile("imaginary.jpg"))
|
||||
img, err := AutoRotate(buf, ImageOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("Cannot process image: %s", err)
|
||||
}
|
||||
if img.Mime != "image/jpeg" {
|
||||
t.Error("Invalid image MIME type")
|
||||
}
|
||||
if assertSize(img.Body, 550, 740) != nil {
|
||||
t.Errorf("Invalid image size, expected: %dx%d", 550, 740)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImagePipelineOperations(t *testing.T) {
|
||||
width, height := 300, 260
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ func NewServerMux(o ServerOptions) http.Handler {
|
||||
mux.Handle(join(o, "/crop"), image(Crop))
|
||||
mux.Handle(join(o, "/smartcrop"), image(SmartCrop))
|
||||
mux.Handle(join(o, "/rotate"), image(Rotate))
|
||||
mux.Handle(join(o, "/autorotate"), image(AutoRotate))
|
||||
mux.Handle(join(o, "/flip"), image(Flip))
|
||||
mux.Handle(join(o, "/flop"), image(Flop))
|
||||
mux.Handle(join(o, "/thumbnail"), image(Thumbnail))
|
||||
|
||||
Reference in New Issue
Block a user