diff --git a/download.go b/download.go index bd0c677b..51971601 100644 --- a/download.go +++ b/download.go @@ -80,16 +80,16 @@ func checkTypeAndDimensions(r io.Reader) (imageType, error) { imgtype, imgtypeOk := imageTypes[imgtypeStr] if err != nil { - return UNKNOWN, err + return imageTypeUnknown, err } if imgconf.Width > conf.MaxSrcDimension || imgconf.Height > conf.MaxSrcDimension { - return UNKNOWN, errors.New("Source image is too big") + return imageTypeUnknown, errors.New("Source image is too big") } if imgconf.Width*imgconf.Height > conf.MaxSrcResolution { - return UNKNOWN, errors.New("Source image is too big") + return imageTypeUnknown, errors.New("Source image is too big") } if !imgtypeOk || !vipsTypeSupportLoad[imgtype] { - return UNKNOWN, errors.New("Source image type not supported") + return imageTypeUnknown, errors.New("Source image type not supported") } return imgtype, nil @@ -100,7 +100,7 @@ func readAndCheckImage(res *http.Response) ([]byte, imageType, error) { imgtype, err := checkTypeAndDimensions(nr) if err != nil { - return nil, UNKNOWN, err + return nil, imageTypeUnknown, err } if res.ContentLength > 0 { @@ -117,13 +117,13 @@ func downloadImage(url string) ([]byte, imageType, error) { res, err := downloadClient.Get(fullURL) if err != nil { - return nil, UNKNOWN, err + return nil, imageTypeUnknown, err } defer res.Body.Close() if res.StatusCode != 200 { body, _ := ioutil.ReadAll(res.Body) - return nil, UNKNOWN, fmt.Errorf("Can't download image; Status: %d; %s", res.StatusCode, string(body)) + return nil, imageTypeUnknown, fmt.Errorf("Can't download image; Status: %d; %s", res.StatusCode, string(body)) } return readAndCheckImage(res) diff --git a/image_types.h b/image_types.h new file mode 100644 index 00000000..917fc55f --- /dev/null +++ b/image_types.h @@ -0,0 +1,7 @@ +enum types { + UNKNOWN = 0, + JPEG, + PNG, + WEBP, + GIF +}; diff --git a/process.go b/process.go index a86f640a..e1fad9bf 100644 --- a/process.go +++ b/process.go @@ -16,52 +16,6 @@ import ( "unsafe" ) -type imageType int - -const ( - UNKNOWN = C.UNKNOWN - JPEG = C.JPEG - PNG = C.PNG - WEBP = C.WEBP - GIF = C.GIF -) - -var imageTypes = map[string]imageType{ - "jpeg": JPEG, - "jpg": JPEG, - "png": PNG, - "webp": WEBP, - "gif": GIF, -} - -type gravityType int - -const ( - CENTER gravityType = iota - NORTH - EAST - SOUTH - WEST - SMART -) - -var gravityTypes = map[string]gravityType{ - "ce": CENTER, - "no": NORTH, - "ea": EAST, - "so": SOUTH, - "we": WEST, - "sm": SMART, -} - -type resizeType int - -const ( - FIT resizeType = iota - FILL - CROP -) - var vipsSupportSmartcrop bool var vipsTypeSupportLoad = make(map[imageType]bool) var vipsTypeSupportSave = make(map[imageType]bool) @@ -98,27 +52,27 @@ func initVips() { vipsSupportSmartcrop = C.vips_support_smartcrop() == 1 - if int(C.vips_type_find_load_go(C.JPEG)) != 0 { - vipsTypeSupportLoad[JPEG] = true + if int(C.vips_type_find_load_go(imageTypeJPEG)) != 0 { + vipsTypeSupportLoad[imageTypeJPEG] = true } - if int(C.vips_type_find_load_go(C.PNG)) != 0 { - vipsTypeSupportLoad[PNG] = true + if int(C.vips_type_find_load_go(imageTypePNG)) != 0 { + vipsTypeSupportLoad[imageTypePNG] = true } - if int(C.vips_type_find_load_go(C.WEBP)) != 0 { - vipsTypeSupportLoad[WEBP] = true + if int(C.vips_type_find_load_go(imageTypeWEBP)) != 0 { + vipsTypeSupportLoad[imageTypeWEBP] = true } - if int(C.vips_type_find_load_go(C.GIF)) != 0 { - vipsTypeSupportLoad[GIF] = true + if int(C.vips_type_find_load_go(imageTypeGIF)) != 0 { + vipsTypeSupportLoad[imageTypeGIF] = true } - if int(C.vips_type_find_save_go(C.JPEG)) != 0 { - vipsTypeSupportSave[JPEG] = true + if int(C.vips_type_find_save_go(imageTypeJPEG)) != 0 { + vipsTypeSupportSave[imageTypeJPEG] = true } - if int(C.vips_type_find_save_go(C.PNG)) != 0 { - vipsTypeSupportSave[PNG] = true + if int(C.vips_type_find_save_go(imageTypePNG)) != 0 { + vipsTypeSupportSave[imageTypePNG] = true } - if int(C.vips_type_find_save_go(C.WEBP)) != 0 { - vipsTypeSupportSave[WEBP] = true + if int(C.vips_type_find_save_go(imageTypeWEBP)) != 0 { + vipsTypeSupportSave[imageTypeWEBP] = true } cConf.Quality = C.int(conf.Quality) @@ -137,7 +91,7 @@ func shutdownVips() { } func randomAccessRequired(po processingOptions) int { - if po.Gravity == SMART { + if po.Gravity == gravitySmart { return 1 } return 0 @@ -175,7 +129,7 @@ func extractMeta(img *C.VipsImage) (int, int, int, bool) { } func calcScale(width, height int, po processingOptions) float64 { - if (po.Width == width && po.Height == height) || (po.Resize != FILL && po.Resize != FIT) { + if (po.Width == width && po.Height == height) || (po.Resize != resizeFill && po.Resize != resizeFit) { return 1 } @@ -184,7 +138,7 @@ func calcScale(width, height int, po processingOptions) float64 { wr := fow / fsw hr := foh / fsh - if po.Resize == FIT { + if po.Resize == resizeFit { return math.Min(wr, hr) } @@ -194,7 +148,7 @@ func calcScale(width, height int, po processingOptions) float64 { func calcShink(scale float64, imgtype imageType) int { shrink := int(1.0 / scale) - if imgtype != JPEG { + if imgtype != imageTypeJPEG { return shrink } @@ -214,19 +168,19 @@ func calcCrop(width, height int, po processingOptions) (left, top int) { left = (width - po.Width + 1) / 2 top = (height - po.Height + 1) / 2 - if po.Gravity == NORTH { + if po.Gravity == gravityNorth { top = 0 } - if po.Gravity == EAST { + if po.Gravity == gravityEast { left = width - po.Width } - if po.Gravity == SOUTH { + if po.Gravity == gravitySouth { top = height - po.Height } - if po.Gravity == WEST { + if po.Gravity == gravityWest { left = 0 } @@ -237,7 +191,7 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer defer C.vips_cleanup() defer runtime.KeepAlive(data) - if po.Gravity == SMART && !vipsSupportSmartcrop { + if po.Gravity == gravitySmart && !vipsSupportSmartcrop { return nil, errors.New("Smart crop is not supported by used version of libvips") } @@ -252,7 +206,7 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer imgWidth, imgHeight, angle, flip := extractMeta(img) // Ensure we won't crop out of bounds - if !po.Enlarge || po.Resize == CROP { + if !po.Enlarge || po.Resize == resizeCrop { if imgWidth < po.Width { po.Width = imgWidth } @@ -263,12 +217,12 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer } if po.Width != imgWidth || po.Height != imgHeight { - if po.Resize == FILL || po.Resize == FIT { + if po.Resize == resizeFill || po.Resize == resizeFit { scale := calcScale(imgWidth, imgHeight, po) // Do some shrink-on-load if scale < 1.0 { - if imgtype == JPEG || imgtype == WEBP { + if imgtype == imageTypeJPEG || imgtype == imageTypeWEBP { shrink := calcShink(scale, imgtype) scale = scale * float64(shrink) @@ -332,8 +286,8 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer t.Check() - if (po.Width != imgWidth || po.Height != imgHeight) && (po.Resize == FILL || po.Resize == CROP) { - if po.Gravity == SMART { + if (po.Width != imgWidth || po.Height != imgHeight) && (po.Resize == resizeFill || po.Resize == resizeCrop) { + if po.Gravity == gravitySmart { if err = vipsImageCopyMemory(&img); err != nil { return nil, err } @@ -370,11 +324,11 @@ func vipsSaveImage(img *C.struct__VipsImage, imgtype imageType) ([]byte, error) imgsize := C.size_t(0) switch imgtype { - case JPEG: + case imageTypeJPEG: err = C.vips_jpegsave_go(img, &ptr, &imgsize, 1, cConf.Quality, cConf.JpegProgressive) - case PNG: + case imageTypePNG: err = C.vips_pngsave_go(img, &ptr, &imgsize, cConf.PngInterlaced) - case WEBP: + case imageTypeWEBP: err = C.vips_webpsave_go(img, &ptr, &imgsize, 1, cConf.Quality) } if err != 0 { diff --git a/processing_options.go b/processing_options.go index a2f3338f..7d8cd316 100644 --- a/processing_options.go +++ b/processing_options.go @@ -1,7 +1,12 @@ package main +/* +#cgo LDFLAGS: -s -w +#include +*/ +import "C" + import ( - "C" "encoding/base64" "errors" "fmt" @@ -10,10 +15,56 @@ import ( "strings" ) +type imageType int + +const ( + imageTypeUnknown = C.UNKNOWN + imageTypeJPEG = C.JPEG + imageTypePNG = C.PNG + imageTypeWEBP = C.WEBP + imageTypeGIF = C.GIF +) + +var imageTypes = map[string]imageType{ + "jpeg": imageTypeJPEG, + "jpg": imageTypeJPEG, + "png": imageTypePNG, + "webp": imageTypeWEBP, + "gif": imageTypeGIF, +} + +type gravityType int + +const ( + gravityCenter gravityType = iota + gravityNorth + gravityEast + gravitySouth + gravityWest + gravitySmart +) + +var gravityTypes = map[string]gravityType{ + "ce": gravityCenter, + "no": gravityNorth, + "ea": gravityEast, + "so": gravitySouth, + "we": gravityWest, + "sm": gravitySmart, +} + +type resizeType int + +const ( + resizeFit resizeType = iota + resizeFill + resizeCrop +) + var resizeTypes = map[string]resizeType{ - "fit": FIT, - "fill": FILL, - "crop": CROP, + "fit": resizeFit, + "fill": resizeFill, + "crop": resizeCrop, } type processingOptions struct { @@ -23,21 +74,25 @@ type processingOptions struct { Gravity gravityType Enlarge bool Format imageType + Blur float32 + Sharpen float32 } func defaultProcessingOptions() processingOptions { return processingOptions{ - Resize: FIT, + Resize: resizeFit, Width: 0, Height: 0, - Gravity: CENTER, + Gravity: gravityCenter, Enlarge: false, - Format: JPEG, + Format: imageTypeJPEG, + Blur: 0, + Sharpen: 0, } } -func decodeUrl(parts []string) (string, imageType, error) { - var imgType imageType = JPEG +func decodeURL(parts []string) (string, imageType, error) { + var imgType imageType = imageTypeJPEG urlParts := strings.Split(strings.Join(parts, ""), ".") @@ -218,7 +273,7 @@ func parsePathAdvanced(parts []string) (string, processingOptions, error) { } } - url, imgType, err := decodeUrl(parts[urlStart:]) + url, imgType, err := decodeURL(parts[urlStart:]) if err != nil { return "", po, err } @@ -256,7 +311,7 @@ func parsePathSimple(parts []string) (string, processingOptions, error) { return "", po, err } - url, imgType, err := decodeUrl(parts[5:]) + url, imgType, err := decodeURL(parts[5:]) if err != nil { return "", po, err } diff --git a/server.go b/server.go index 63762965..21d7121d 100644 --- a/server.go +++ b/server.go @@ -19,9 +19,9 @@ import ( ) var mimes = map[imageType]string{ - JPEG: "image/jpeg", - PNG: "image/png", - WEBP: "image/webp", + imageTypeJPEG: "image/jpeg", + imageTypePNG: "image/png", + imageTypeWEBP: "image/webp", } type httpHandler struct { diff --git a/vips.h b/vips.h index a5996b83..5e90c1db 100644 --- a/vips.h +++ b/vips.h @@ -1,6 +1,7 @@ #include #include #include +#include #define VIPS_SUPPORT_SMARTCROP \ (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 5)) @@ -13,14 +14,6 @@ #define EXIF_ORIENTATION "exif-ifd0-Orientation" -enum types { - UNKNOWN = 0, - JPEG, - PNG, - WEBP, - GIF -}; - int vips_initialize() { return vips_init("imgproxy");