func (e *GoImageEngine) Transform(img *imagefile.ImageFile, operation *Operation, qs map[string]string) (*imagefile.ImageFile, error) { params := map[string]string{ "upscale": "1", "h": "0", "w": "0", "deg": "90", } err := mergo.Merge(&qs, params) if err != nil { return nil, err } var quality int var format string q, ok := qs["q"] if ok { quality, err := strconv.Atoi(q) if err != nil { return nil, err } if quality > 100 { return nil, fmt.Errorf("Quality should be <= 100") } } else { quality = e.DefaultQuality } format, ok = qs["fmt"] filepath := img.Filepath if ok { if _, ok := ContentTypes[format]; !ok { return nil, fmt.Errorf("Unknown format %s", format) } } if format == "" && e.Format != "" { format = e.Format } if format == "" { format = img.Format() } if format == "" { format = e.DefaultFormat } if format != img.Format() { index := len(filepath) - len(img.Format()) filepath = filepath[:index] + format } file := &imagefile.ImageFile{ Source: img.Source, Key: img.Key, Headers: img.Headers, Filepath: filepath, } options := &Options{ Quality: quality, Format: Formats[format], } switch operation { case Flip: pos, ok := qs["pos"] if !ok { return nil, fmt.Errorf("Parameter \"pos\" not found in query string") } content, err := e.Flip(img, pos, options) if err != nil { return nil, err } file.Processed = content return file, err case Rotate: deg, err := strconv.Atoi(qs["deg"]) if err != nil { return nil, err } content, err := e.Rotate(img, deg, options) if err != nil { return nil, err } file.Processed = content return file, err case Thumbnail, Resize, Fit: var upscale bool var w int var h int if upscale, err = strconv.ParseBool(qs["upscale"]); err != nil { return nil, err } if w, err = strconv.Atoi(qs["w"]); err != nil { return nil, err } if h, err = strconv.Atoi(qs["h"]); err != nil { return nil, err } options.Upscale = upscale switch operation { case Resize: content, err := e.Resize(img, w, h, options) if err != nil { return nil, err } file.Processed = content return file, err case Thumbnail: content, err := e.Thumbnail(img, w, h, options) if err != nil { return nil, err } file.Processed = content return file, err case Fit: content, err := e.Fit(img, w, h, options) if err != nil { return nil, err } file.Processed = content return file, err } case Original: file.Processed = img.Source return file, err } return nil, fmt.Errorf("Operation not found for %s", operation) }
func (a *Application) ImageFileFromRequest(req *Request, async bool, load bool) (*image.ImageFile, error) { var file *image.ImageFile = &image.ImageFile{ Key: req.Key, Storage: a.DestStorage, Headers: map[string]string{}, } var err error key := a.WithPrefix(req.Key) // Image from the KVStore found stored, err := gokvstores.String(req.Connection.Get(key)) file.Filepath = stored if stored != "" { a.Logger.Infof("Key %s found in kvstore: %s", key, stored) if load { file, err = image.FromStorage(a.DestStorage, stored) if err != nil { return nil, err } } } else { a.Logger.Infof("Key %s not found in kvstore", key) // Image not found from the KVStore, we need to process it // URL available in Query String if req.URL != nil { file, err = image.FromURL(req.URL) } else { // URL provided we use http protocol to retrieve it file, err = image.FromStorage(a.SourceStorage, req.Filepath) } if err != nil { return nil, err } file, err = a.Engine.Transform(file, req.Operation, req.QueryString) if err != nil { return nil, err } file.Filepath = fmt.Sprintf("%s.%s", a.ShardFilename(req.Key), file.Format()) } file.Key = req.Key file.Storage = a.DestStorage file.Headers["Content-Type"] = file.ContentType() file.Headers["ETag"] = req.Key if stored == "" { if async == true { go a.Store(req.Filepath, file) } else { err = a.Store(req.Filepath, file) } } return file, err }