imagefield

package
v0.71.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package imagefield connects the image pipeline to the upload path: it turns a framework/image.VariantSet into the file.ImageDeriver that ProcessFileField and the CRUD upload handler call, so declaring a schema.Image field is what makes uploads produce renditions and a BlurHash, no per-entity upload handler.

It is a separate package on purpose. framework/file is a leaf that framework/crud imports, so an edge from there to framework/image would link every image decoder plus the WebP encoder into every application with a CRUD handler. Keeping the adapter here means only applications that actually want the pipeline pay for it.

Typical wiring, one option on the app:

framework.NewApp(
    framework.WithFileStorage(store),
    framework.WithImagePipeline(imagefield.MustNew(imagefield.Config{
        Variants: []image.Variant{
            {Width: 480, Format: image.FormatWebP, Suffix: "sm"},
            {Width: 960, Format: image.FormatWebP, Suffix: "md"},
            {Width: 480, Format: image.FormatJPEG, Quality: 82, Suffix: "sm"},
            {Width: 960, Format: image.FormatJPEG, Quality: 82, Suffix: "md"},
        },
        BlurHashX: 4, BlurHashY: 3,
    })),
)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Variants are the renditions to produce and store. Each entry's
	// Suffix (or width, when Suffix is empty) distinguishes its storage
	// key from the original's.
	Variants []fwimage.Variant

	// BlurHashX and BlurHashY are the BlurHash component counts (1..9).
	// Both zero means no BlurHash; setting only one is an error. 4x3 suits
	// landscape images, 3x4 portrait.
	BlurHashX int
	BlurHashY int

	// Placeholder, when non-nil, also stores an LQIP data URL. Redundant
	// alongside a BlurHash for most callers, a BlurHash costs ~28 bytes
	// in the column against a few hundred, and framework/image renders
	// either one the same way.
	Placeholder *fwimage.PlaceholderOptions

	// RejectAnimated fails the upload when the source has more than one
	// frame instead of silently flattening to the first. Worth setting on
	// avatar and profile-photo fields, where a surprise still frame is
	// worse than a rejection the user can act on.
	RejectAnimated bool

	// AllowUpscale opts back in to renditions wider than the source. The
	// default clamps each rendition to the source width, so a small upload
	// does not fan out into pixel-multiplied storage waste.
	AllowUpscale bool

	// MaxPixels overrides the decompression-bomb guard for this pipeline
	// (default framework/image.DefaultMaxPixels, 64 MP).
	MaxPixels int64
}

Config declares what to derive from each uploaded image. The zero value derives nothing and New rejects it, an image pipeline that produces no renditions, no hash, and no placeholder is a configuration mistake, not a no-op worth honouring silently.

type Deriver

type Deriver struct {
	// contains filtered or unexported fields
}

Deriver implements file.ImageDeriver over a VariantSet.

func MustNew

func MustNew(cfg Config) *Deriver

MustNew is New for package-level wiring, panicking on a bad config.

func New

func New(cfg Config) (*Deriver, error)

New builds a Deriver from cfg. It returns an error for a configuration that could not produce anything, or that framework/image would reject at process time anyway, better at wiring time than on the first upload.

func (*Deriver) DeriveImage

func (d *Deriver) DeriveImage(ctx context.Context, store upload.Storage, data []byte, primaryRef string) (*file.ImageDerivatives, error)

DeriveImage decodes the upload, produces every configured rendition, stores them beside the original, and returns their references plus the placeholder metadata.

Renditions stream one at a time through VariantSet.ProcessTo, so peak memory stays near a single rendition rather than all of them summed, this runs inside a request, on bytes a client chose.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL