|
|
|
@ -16,11 +16,8 @@ import (
|
|
|
|
func Resize(buf []byte, o Options) ([]byte, error) {
|
|
|
|
func Resize(buf []byte, o Options) ([]byte, error) {
|
|
|
|
defer C.vips_thread_shutdown()
|
|
|
|
defer C.vips_thread_shutdown()
|
|
|
|
|
|
|
|
|
|
|
|
if len(buf) == 0 {
|
|
|
|
image, imageType, err := loadImage(buf)
|
|
|
|
return nil, errors.New("Image buffer is empty")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
image, imageType, err := vipsRead(buf)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -107,7 +104,13 @@ func Resize(buf []byte, o Options) ([]byte, error) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add watermark, if necessary
|
|
|
|
// Add watermark, if necessary
|
|
|
|
image, err = watermakImage(image, o.Watermark)
|
|
|
|
image, err = watermarkImageWithText(image, o.Watermark)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add watermark, if necessary
|
|
|
|
|
|
|
|
image, err = watermarkImageWithAnotherImage(image, o.WatermarkImage)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -118,17 +121,20 @@ func Resize(buf []byte, o Options) ([]byte, error) {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
saveOptions := vipsSaveOptions{
|
|
|
|
return saveImage(image, o)
|
|
|
|
Quality: o.Quality,
|
|
|
|
|
|
|
|
Type: o.Type,
|
|
|
|
|
|
|
|
Compression: o.Compression,
|
|
|
|
|
|
|
|
Interlace: o.Interlace,
|
|
|
|
|
|
|
|
NoProfile: o.NoProfile,
|
|
|
|
|
|
|
|
Interpretation: o.Interpretation,
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Finally get the resultant buffer
|
|
|
|
func loadImage(buf []byte) (*C.VipsImage, ImageType, error) {
|
|
|
|
return vipsSave(image, saveOptions)
|
|
|
|
if len(buf) == 0 {
|
|
|
|
|
|
|
|
return nil, JPEG, errors.New("Image buffer is empty")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
image, imageType, err := vipsRead(buf)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, JPEG, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return image, imageType, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func applyDefaults(o Options, imageType ImageType) Options {
|
|
|
|
func applyDefaults(o Options, imageType ImageType) Options {
|
|
|
|
@ -147,6 +153,19 @@ func applyDefaults(o Options, imageType ImageType) Options {
|
|
|
|
return o
|
|
|
|
return o
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func saveImage(image *C.VipsImage, o Options) ([]byte, error) {
|
|
|
|
|
|
|
|
saveOptions := vipsSaveOptions{
|
|
|
|
|
|
|
|
Quality: o.Quality,
|
|
|
|
|
|
|
|
Type: o.Type,
|
|
|
|
|
|
|
|
Compression: o.Compression,
|
|
|
|
|
|
|
|
Interlace: o.Interlace,
|
|
|
|
|
|
|
|
NoProfile: o.NoProfile,
|
|
|
|
|
|
|
|
Interpretation: o.Interpretation,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally get the resultant buffer
|
|
|
|
|
|
|
|
return vipsSave(image, saveOptions)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func normalizeOperation(o *Options, inWidth, inHeight int) {
|
|
|
|
func normalizeOperation(o *Options, inWidth, inHeight int) {
|
|
|
|
if !o.Force && !o.Crop && !o.Embed && !o.Enlarge && o.Rotate == 0 && (o.Width > 0 || o.Height > 0) {
|
|
|
|
if !o.Force && !o.Crop && !o.Embed && !o.Enlarge && o.Rotate == 0 && (o.Width > 0 || o.Height > 0) {
|
|
|
|
o.Force = true
|
|
|
|
o.Force = true
|
|
|
|
@ -164,7 +183,6 @@ func shouldApplyEffects(o Options) bool {
|
|
|
|
|
|
|
|
|
|
|
|
func transformImage(image *C.VipsImage, o Options, shrink int, residual float64) (*C.VipsImage, error) {
|
|
|
|
func transformImage(image *C.VipsImage, o Options, shrink int, residual float64) (*C.VipsImage, error) {
|
|
|
|
var err error
|
|
|
|
var err error
|
|
|
|
|
|
|
|
|
|
|
|
// Use vips_shrink with the integral reduction
|
|
|
|
// Use vips_shrink with the integral reduction
|
|
|
|
if shrink > 1 {
|
|
|
|
if shrink > 1 {
|
|
|
|
image, residual, err = shrinkImage(image, o, residual, shrink)
|
|
|
|
image, residual, err = shrinkImage(image, o, residual, shrink)
|
|
|
|
@ -242,6 +260,7 @@ func extractOrEmbedImage(image *C.VipsImage, o Options) (*C.VipsImage, error) {
|
|
|
|
left, top := (o.Width-inWidth)/2, (o.Height-inHeight)/2
|
|
|
|
left, top := (o.Width-inWidth)/2, (o.Height-inHeight)/2
|
|
|
|
image, err = vipsEmbed(image, left, top, o.Width, o.Height, o.Extend, o.Background)
|
|
|
|
image, err = vipsEmbed(image, left, top, o.Width, o.Height, o.Extend, o.Background)
|
|
|
|
break
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
case o.Top != 0 || o.Left != 0 || o.AreaWidth != 0 || o.AreaHeight != 0:
|
|
|
|
case o.Top != 0 || o.Left != 0 || o.AreaWidth != 0 || o.AreaHeight != 0:
|
|
|
|
if o.AreaWidth == 0 {
|
|
|
|
if o.AreaWidth == 0 {
|
|
|
|
o.AreaHeight = o.Width
|
|
|
|
o.AreaHeight = o.Width
|
|
|
|
@ -293,7 +312,7 @@ func rotateAndFlipImage(image *C.VipsImage, o Options) (*C.VipsImage, bool, erro
|
|
|
|
return image, rotated, err
|
|
|
|
return image, rotated, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func watermakImage(image *C.VipsImage, w Watermark) (*C.VipsImage, error) {
|
|
|
|
func watermarkImageWithText(image *C.VipsImage, w Watermark) (*C.VipsImage, error) {
|
|
|
|
if w.Text == "" {
|
|
|
|
if w.Text == "" {
|
|
|
|
return image, nil
|
|
|
|
return image, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -325,6 +344,31 @@ func watermakImage(image *C.VipsImage, w Watermark) (*C.VipsImage, error) {
|
|
|
|
return image, nil
|
|
|
|
return image, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func watermarkImageWithAnotherImage(image *C.VipsImage, w WatermarkImage) (*C.VipsImage, error) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(w.Buf) == 0 {
|
|
|
|
|
|
|
|
return image, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if w.Opacity == 0.0 {
|
|
|
|
|
|
|
|
w.Opacity = 1.0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watermark, _, err := loadImage(w.Buf)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
image, err = vipsDrawWatermark(image, watermark, w)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return image, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func imageFlatten(image *C.VipsImage, imageType ImageType, o Options) (*C.VipsImage, error) {
|
|
|
|
func imageFlatten(image *C.VipsImage, imageType ImageType, o Options) (*C.VipsImage, error) {
|
|
|
|
// Only PNG images are supported for now
|
|
|
|
// Only PNG images are supported for now
|
|
|
|
if imageType != PNG || o.Background == ColorBlack {
|
|
|
|
if imageType != PNG || o.Background == ColorBlack {
|
|
|
|
|