Esempio n. 1
0
// 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
}