1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2024-11-24 08:12:38 +02:00

rotate processing option

This commit is contained in:
DarthSim 2021-01-13 20:51:19 +06:00
parent 6da8885605
commit e48c557fc4
5 changed files with 59 additions and 29 deletions

View File

@ -7,6 +7,7 @@
- `IMGPROXY_STRIP_COLOR_PROFILE` config and [strip_color_profile](https://docs.imgproxy.net/#/generating_the_url_advanced?id=strip-color-profile) processing option.
- `IMGPROXY_FORMAT_QUALITY` config.
- `IMGPROXY_AUTO_ROTATE` config and [auto_rotate](https://docs.imgproxy.net/#/generating_the_url_advanced?id=auto-rotate) processing option.
- [rotate](https://docs.imgproxy.net/#/generating_the_url_advanced?id=rotate) processing option.
- (pro) Remove Adobe Illustrator garbage from SVGs.
### Changed

View File

@ -208,6 +208,19 @@ Removes surrounding background.
**📝Note:** Trimming of animated images is not supported.
#### Rotate
```
rotate:%angle
rot:%angle
```
Rotates the image on the specified angle. The orientation from the image metadata is applied before the rotation unless autorotation is disabled.
**📝Note:** Only 0/90/180/270/etc degrees angles are supported.
Default: 0.
#### Quality
```

View File

@ -34,34 +34,33 @@ func imageTypeGoodForWeb(imgtype imageType) bool {
imgtype != imageTypeBMP
}
func extractMeta(img *vipsImage, useOrientation bool) (int, int, int, bool) {
func extractMeta(img *vipsImage, baseAngle int, useOrientation bool) (int, int, int, bool) {
width := img.Width()
height := img.Height()
angle := vipsAngleD0
angle := 0
flip := false
if !useOrientation {
return width, height, angle, flip
if useOrientation {
orientation := img.Orientation()
if orientation == 3 || orientation == 4 {
angle = 180
}
if orientation == 5 || orientation == 6 {
angle = 90
}
if orientation == 7 || orientation == 8 {
angle = 270
}
if orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7 {
flip = true
}
}
orientation := img.Orientation()
if orientation >= 5 && orientation <= 8 {
if (angle+baseAngle)%180 != 0 {
width, height = height, width
}
if orientation == 3 || orientation == 4 {
angle = vipsAngleD180
}
if orientation == 5 || orientation == 6 {
angle = vipsAngleD90
}
if orientation == 7 || orientation == 8 {
angle = vipsAngleD270
}
if orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7 {
flip = true
}
return width, height, angle, flip
}
@ -325,7 +324,7 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces
trimmed = true
}
srcWidth, srcHeight, angle, flip := extractMeta(img, po.AutoRotate)
srcWidth, srcHeight, angle, flip := extractMeta(img, po.Rotate, po.AutoRotate)
cropWidth, cropHeight := po.Crop.Width, po.Crop.Height
cropGravity := po.Crop.Gravity
@ -356,7 +355,7 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces
}
// Update scale after scale-on-load
newWidth, newHeight, _, _ := extractMeta(img, po.AutoRotate)
newWidth, newHeight, _, _ := extractMeta(img, po.Rotate, po.AutoRotate)
if srcWidth > srcHeight {
scale = float64(srcWidth) * scale / float64(newWidth)
} else {
@ -413,6 +412,10 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces
}
}
if err = img.Rotate(po.Rotate); err != nil {
return err
}
dprWidth := scaleInt(po.Width, po.Dpr)
dprHeight := scaleInt(po.Height, po.Dpr)

View File

@ -136,6 +136,7 @@ type processingOptions struct {
Crop cropOptions
Padding paddingOptions
Trim trimOptions
Rotate int
Format imageType
Quality int
MaxBytes int
@ -222,6 +223,7 @@ func newProcessingOptions() *processingOptions {
Extend: extendOptions{Enabled: false, Gravity: gravityOptions{Type: gravityCenter}},
Padding: paddingOptions{Enabled: false},
Trim: trimOptions{Enabled: false, Threshold: 10, Smart: true},
Rotate: 0,
Quality: 0,
MaxBytes: 0,
Format: imageTypeUnknown,
@ -664,6 +666,20 @@ func applyTrimOption(po *processingOptions, args []string) error {
return nil
}
func applyRotateOption(po *processingOptions, args []string) error {
if len(args) > 1 {
return fmt.Errorf("Invalid rotate arguments: %v", args)
}
if r, err := strconv.Atoi(args[0]); err == nil && r%90 == 0 {
po.Rotate = r
} else {
return fmt.Errorf("Invalid rotation angle: %s", args[0])
}
return nil
}
func applyQualityOption(po *processingOptions, args []string) error {
if len(args) > 1 {
return fmt.Errorf("Invalid quality arguments: %v", args)
@ -924,6 +940,8 @@ func applyProcessingOption(po *processingOptions, name string, args []string) er
return applyCropOption(po, args)
case "trim", "t":
return applyTrimOption(po, args)
case "rotate", "rot":
return applyRotateOption(po, args)
case "padding", "pd":
return applyPaddingOption(po, args)
case "quality", "q":

11
vips.go
View File

@ -38,13 +38,6 @@ var vipsConf struct {
WatermarkOpacity C.double
}
const (
vipsAngleD0 = C.VIPS_ANGLE_D0
vipsAngleD90 = C.VIPS_ANGLE_D90
vipsAngleD180 = C.VIPS_ANGLE_D180
vipsAngleD270 = C.VIPS_ANGLE_D270
)
func initVips() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@ -392,7 +385,9 @@ func (img *vipsImage) Orientation() C.int {
func (img *vipsImage) Rotate(angle int) error {
var tmp *C.VipsImage
if C.vips_rot_go(img.VipsImage, &tmp, C.VipsAngle(angle)) != 0 {
vipsAngle := (angle / 90) % 4
if C.vips_rot_go(img.VipsImage, &tmp, C.VipsAngle(vipsAngle)) != 0 {
return vipsError()
}