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 New ¶
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.