Skip to content

15-minute quickstart

Copy page

This exercise turns the older Chinese notes’ “read → process → export” outline into one comparable task for four bindings: shrink input.jpg to fit within 640 × 640, never enlarge it, and write output.webp at quality 82.

To run the example, name your own JPEG input.jpg; different dimensions and image content will produce different output measurements.

Gate of the Orient outlined in red lights above a park walkway at night
Input: JPEG1938 × 1292, 610,191 bytes
The same night scene resized to fit within 640 pixels and encoded as WebP
Reference output: WebP640 × 427, 36,172 bytes, quality 82

The reference output was generated with govips v2.19.0 and libvips 8.17.3.

Run command

go run . input.jpg output/

Complete source

package main

import (
	"fmt"
	"os"

	"github.com/davidbyttow/govips/v2/vips"
	"github.com/webp-sh/vips-handbook/examples/internal/recipeutil"
)

func main() {
	if err := run(os.Args); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run(args []string) error {
	if len(args) != 3 {
		return fmt.Errorf("usage: quickstart-thumbnail <input.jpg> <output-directory>")
	}
	inputPath, outputDir := args[1], args[2]
	if err := os.MkdirAll(outputDir, 0o755); err != nil {
		return err
	}

	if err := vips.Startup(nil); err != nil {
		return fmt.Errorf("start libvips: %w", err)
	}
	defer vips.Shutdown()

	image, err := vips.NewThumbnailFromFile(inputPath, 640, 640, vips.InterestingNone)
	if err != nil {
		return fmt.Errorf("create thumbnail: %w", err)
	}
	defer image.Close()

	output, err := recipeutil.ExportWebp(image, outputDir, "output.webp", 82, map[string]any{
		"width": 640, "height": 640, "crop": "none", "withoutEnlargement": true,
	})
	if err != nil {
		return err
	}
	if output.Width > 640 || output.Height > 640 {
		return fmt.Errorf("unexpected thumbnail dimensions: %dx%d", output.Width, output.Height)
	}
	if err := recipeutil.WriteResult(outputDir, "quickstart-thumbnail", inputPath, []recipeutil.Output{output}); err != nil {
		return err
	}

	fmt.Printf("quickstart-thumbnail: %dx%d, %d bytes\n", output.Width, output.Height, output.Size)
	return nil
}

At minimum, confirm that output.webp exists and can be opened again; neither dimension is greater than 640; an input smaller than the target was not enlarged; and the output is WebP data, not a renamed file.

  • Format: WEBP
  • Dimensions: 640 × 427
  • Bands: 3
  • Alpha: No
  • File size: 36,172 bytes
  • Generated with: govips v2.19.0 / libvips 8.17.3

The four snippets target the same product behavior, but they are not line-for-line equivalents. govips and pyvips call thumbnail operations directly, sharp expresses the boundary with resize({ fit: 'inside' }), and the CLI passes saver options through the filename.

Continue to build a complete image pipeline and make input checks, orientation normalization, encoding, and result verification explicit stages.