func (processor *Processor) Execute(src *Image, dst io.Writer, query *Query) { processor.gift.Empty() quality := 100 if query.Count() > 0 { // resize if query.Has("w") || query.Has("h") { width := query.GetInt("w") height := query.GetInt("h") if width > 0 || height > 0 { processor.gift.Add(gift.Resize(width, height, gift.LanczosResampling)) } } // crop if query.Has("c") { c := query.GetIntArray("c") if len(c) == 4 { processor.gift.Add(gift.Crop(image.Rect(c[0], c[1], c[2], c[3]))) } } // grayscale if query.Has("grayscale") { processor.gift.Add(gift.Grayscale()) } // sepia if query.Has("sepia") { sepia := query.GetInt("sepia") if sepia <= 100 { processor.gift.Add(gift.Sepia(float32(sepia))) } } // contrast if query.Has("contrast") { contrast := query.GetInt("contrast") processor.gift.Add(gift.Contrast(float32(contrast))) } // brightness if query.Has("brightness") { brightness := query.GetInt("brightness") processor.gift.Add(gift.Brightness(float32(brightness))) } // saturation if query.Has("saturation") { saturation := query.GetInt("saturation") processor.gift.Add(gift.Saturation(float32(saturation))) } // colorize if query.Has("colorize") { colorize := query.GetIntArray("colorize") if len(colorize) == 3 { processor.gift.Add(gift.Colorize(float32(colorize[0]), float32(colorize[1]), float32(colorize[2]))) } } // colorbalance if query.Has("colorbalance") { colorbalance := query.GetIntArray("colorbalance") if len(colorbalance) == 3 { processor.gift.Add(gift.ColorBalance(float32(colorbalance[0]), float32(colorbalance[1]), float32(colorbalance[2]))) } } // quality if query.Has("q") { q := query.GetInt("q") if q > 0 && q < 100 { quality = q } } // Draw if len(processor.gift.Filters) > 0 { rgba := image.NewRGBA(processor.gift.Bounds(src.Object.Bounds())) processor.gift.Draw(rgba, src.Object) jpeg.Encode(dst, rgba, &jpeg.Options{Quality: quality}) return } } // default jpeg.Encode(dst, src.Object, &jpeg.Options{Quality: quality}) }
func (r *FilesResource) getImageReader(registry kit.Registry, tmpDir string, file kit.File, width, height int64, filters []string, ip string) (reader kit.ReadSeekerCloser, size int64, err apperror.Error) { if width == 0 && height == 0 && len(filters) == 0 { reader, err = file.Reader() return } // Dimensions specified. // Check if the thumbnail was already created. // If so, serve it. Otherwise, create it first. if (width == 0 || height == 0) && (file.GetWidth() == 0 || file.GetHeight() == 0) { err = &apperror.Err{ Code: "image_dimensions_not_determined", Message: fmt.Sprintf("The file with id %v does not have width/height", file.GetId()), } return } if width < 0 || height < 0 { err = apperror.New("invalid_dimensions") return } // If either height or width is 0, determine proper values to presserve aspect ratio. if width == 0 { ratio := float64(file.GetWidth()) / float64(file.GetHeight()) width = int64(float64(height) * ratio) } else if height == 0 { ratio := float64(file.GetHeight()) / float64(file.GetWidth()) height = int64(float64(width) * ratio) } maxWidth := registry.Config().UInt("files.thumbGenerator.maxWidth", 2000) maxHeight := registry.Config().UInt("files.thumbGenerator.maxHeight", 2000) if width > int64(maxWidth) || height > int64(maxHeight) { err = &apperror.Err{ Code: "dimensions_exceed_maximum_limits", Message: "The specified dimensions exceed the maximum limits", } return } thumbId := fmt.Sprintf("%v_%v_%v_%v_%v_%v.%v", file.GetId(), file.GetBucket(), file.GetName(), strconv.FormatInt(width, 10), strconv.FormatInt(height, 10), strings.Replace(strings.Join(filters, "_"), ":", "_", -1), "jpeg") if ok, _ := file.GetBackend().HasFileById("thumbs", thumbId); !ok { var channel chan bool channel, err = r.thumbnailRateLimiter.Start(ip) if err != nil { return } if channel != nil { <-channel } // Thumb does not exist yet, so create it. reader, err = file.Reader() if err != nil { return } defer reader.Close() img, _, err2 := image.Decode(reader) if err2 != nil { err = apperror.Wrap(err2, "image_decode_error") return } var giftFilters []gift.Filter if !(height == 0 && width == 0) { giftFilters = append(giftFilters, gift.ResizeToFill(int(width), int(height), gift.LanczosResampling, gift.CenterAnchor)) } for _, filter := range filters { if filter == "" { continue } parts := strings.Split(filter, ":") if len(parts) > 1 { filter = parts[0] } switch filter { case "sepia": n := float32(100) if len(parts) == 2 { x, err2 := strconv.ParseFloat(parts[1], 64) if err2 == nil { n = float32(x) } else { err = apperror.New("invalid_sepia_filter_value", true) return } } giftFilters = append(giftFilters, gift.Sepia(n)) case "grayscale": giftFilters = append(giftFilters, gift.Grayscale()) case "brightness": n := float32(0) if len(parts) == 2 { x, err2 := strconv.ParseFloat(parts[1], 64) if err2 == nil { n = float32(x) } else { err = apperror.New("invalid_brightness_filter_value", true) return } } giftFilters = append(giftFilters, gift.Brightness(n)) default: err = apperror.New("unknown_filter", fmt.Sprintf("Unknown filter: %v", filter), true) return } } gift := gift.New(giftFilters...) thumb := image.NewRGBA(gift.Bounds(img.Bounds())) gift.Draw(thumb, img) var writer io.WriteCloser _, writer, err = file.GetBackend().WriterById("thumbs", thumbId, true) if err != nil { return } defer writer.Close() jpeg.Encode(writer, thumb, &jpeg.Options{Quality: 90}) r.thumbnailRateLimiter.Finish() } backend := file.GetBackend() size, err = backend.FileSizeById("thumbs", thumbId) if err != nil { return } reader, err = file.GetBackend().ReaderById("thumbs", thumbId) return }