// ServeArt provides a common method for serving and resizing Art, based on // an input HTTP request. func ServeArt(w http.ResponseWriter, r *http.Request, art *data.Art) error { // Attempt to access art data stream stream, err := art.Stream() if err != nil { return err } // Check for resize request, if none, serve directly size := r.URL.Query().Get("size") if size == "" { // Serve content directly, account for range headers, and enabling caching. http.ServeContent(w, r, art.FileName, time.Unix(art.LastModified, 0), stream) return nil } // Ensure size is a valid integer sizeInt, err := strconv.Atoi(size) if err != nil { return ErrInvalidIntegerSize } // Verify positive integer if sizeInt < 1 { return ErrNegativeIntegerSize } // Decode input image stream img, imgFormat, err := image.Decode(stream) if err != nil { return err } // Generate a thumbnail image of the specified size img = resize.Resize(uint(sizeInt), 0, img, resize.NearestNeighbor) // Encode to original format for output buffer := bytes.NewBuffer(nil) if imgFormat == "jpeg" { // JPEG, lossy encoding, default quality if err := jpeg.Encode(buffer, img, nil); err != nil { return err } } else { // Always send PNG as a backup // PNG, lossless encoding if err := png.Encode(buffer, img); err != nil { return err } } // Serve content directly, account for range headers, and enabling caching. http.ServeContent(w, r, art.FileName, time.Unix(art.LastModified, 0), bytes.NewReader(buffer.Bytes())) return nil }