imagekit

package
v0.19.0 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: MIT Imports: 11 Imported by: 0

README

imagekit

English | 한국어

imagekit provides bounded pure-Go helpers for resizing one image and encoding it as JPEG or PNG.

imagekit bounded transform flow

Install

go get github.com/bluetape4k/bluetape-go

Supported Formats

Direction Formats
Input JPEG, PNG, GIF
Output JPEG, PNG

The input allowlist is explicit. Process-global image decoders registered by other dependencies are rejected unless they report JPEG, PNG, or GIF.

Default Bounds

Zero limit fields use conservative service defaults:

Limit Default
MaxInputBytes 10 MiB
MaxPixels 16,000,000
MaxWidth 8192
MaxHeight 8192
MaxOutputPixels 16,000,000
MaxOutputWidth 8192
MaxOutputHeight 8192

JPEGQuality defaults to 85. Nonzero JPEG quality must be in 1..100.

Usage

result, err := imagekit.Transform(ctx, reader, imagekit.Request{
    Width:        320,
    Height:       180,
    Mode:         imagekit.ModeFit,
    OutputFormat: imagekit.OutputJPEG,
})

Use TransformTo only when direct writer output is acceptable. It encodes directly to the writer and returns metadata with Result.Bytes == nil, avoiding the extra encoded byte slice returned by Transform. The write is not atomic: a codec or writer failure can leave partial bytes in the writer. For HTTP responses or final storage objects, prefer Transform or write TransformTo into a temporary buffer/object and publish it only after err == nil.

var staged bytes.Buffer
result, err := imagekit.TransformTo(ctx, &staged, reader, imagekit.Request{
    Width:        320,
    Height:       180,
    Mode:         imagekit.ModeFill,
    OutputFormat: imagekit.OutputPNG,
})
if err == nil {
    _, err = writer.Write(staged.Bytes())
}

Modes

Mode Behavior
ModeFit Preserve aspect ratio and fit inside the requested box.
ModeFill Preserve aspect ratio, center-crop, and fill the requested box.
ModeExact Resize exactly to the requested size and allow distortion.

Cancellation

imagekit checks context.Context before the bounded read, after the bounded read, before decode, before resize, and before encode. It cannot preempt a blocked caller-owned io.Reader or io.Writer, nor a standard-library codec call that is already executing. Services that need hard I/O deadlines should enforce them at the I/O boundary.

Errors

Errors support errors.Is and errors.As with imagekit sentinels:

  • ErrInvalidOptions
  • ErrUnsupportedFormat
  • ErrInputTooLarge
  • ErrImageTooLarge
  • ErrDecode
  • ErrEncode

Cancellation preserves context.Canceled and context.DeadlineExceeded. Error messages do not include raw image bytes, caller file paths, or wrapped cause text.

Benchmarks

The pure-Go baseline is recorded in docs/benchmarks/2026-07-01-issue-309-imagekit.md. It exists to support the follow-up libvips evaluation in issue #310 and does not claim libvips-level throughput.

imagekit pure-Go benchmark baseline

Non-Goals

This package does not provide libvips/cgo integration, OCR, CAPTCHA, SVG rasterization, AVIF, HEIC, TIFF, EXIF processing, image effects or filters beyond resize resampling, metadata editing, watermarks, similarity metrics, or framework integration.

Documentation

Overview

Package imagekit provides bounded pure-Go helpers for resizing one image and encoding it as JPEG or PNG.

Supported input formats are JPEG, PNG, and GIF as reported by the standard library image decoders. Supported output formats are JPEG and PNG.

The package checks context cancellation before the bounded read, after the bounded read, before decode, before resize, and before encode. It cannot preempt a blocked caller-owned io.Reader or io.Writer, nor a standard-library codec call that is already executing; callers that need hard I/O deadlines should enforce them at the I/O boundary.

Transform returns encoded bytes for convenience. TransformTo writes directly to a caller-owned writer when partial output is acceptable. For final HTTP responses or storage objects, callers should use Transform or stage TransformTo output in a temporary buffer/object before publishing.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidOptions reports an invalid transform request or nil I/O value.
	ErrInvalidOptions = errors.New("imagekit: invalid options")
	// ErrUnsupportedFormat reports an unsupported input or output format.
	ErrUnsupportedFormat = errors.New("imagekit: unsupported format")
	// ErrInputTooLarge reports that encoded input exceeds MaxInputBytes.
	ErrInputTooLarge = errors.New("imagekit: input too large")
	// ErrImageTooLarge reports that decoded or requested dimensions exceed limits.
	ErrImageTooLarge = errors.New("imagekit: image too large")
	// ErrDecode reports input read, config decode, or full decode failure.
	ErrDecode = errors.New("imagekit: decode failed")
	// ErrEncode reports output encode failure.
	ErrEncode = errors.New("imagekit: encode failed")
)

Functions

This section is empty.

Types

type Error

type Error struct {
	Kind      error
	Operation string
	Format    string
	Cause     error
}

Error preserves imagekit sentinel identity and an optional cause without exposing raw payload bytes, file paths, or cause text through Error().

func (*Error) Error

func (e *Error) Error() string

func (*Error) Is

func (e *Error) Is(target error) bool

Is reports matches against imagekit sentinel errors, context sentinel errors, and the wrapped cause.

func (*Error) Unwrap

func (e *Error) Unwrap() error

type InputFormat

type InputFormat string

InputFormat reports the decoded input format.

const (
	// InputJPEG reports a JPEG input image.
	InputJPEG InputFormat = "jpeg"
	// InputPNG reports a PNG input image.
	InputPNG InputFormat = "png"
	// InputGIF reports a GIF input image.
	InputGIF InputFormat = "gif"
)

type Mode

type Mode int

Mode controls how the source image is mapped into the requested size.

const (
	// ModeFit preserves aspect ratio and fits inside the requested box.
	ModeFit Mode = iota
	// ModeFill preserves aspect ratio, center-crops, and fills the requested box.
	ModeFill
	// ModeExact resizes to the exact requested size and may distort the image.
	ModeExact
)

type OutputFormat

type OutputFormat string

OutputFormat selects the encoded output format.

const (
	// OutputJPEG encodes the result as JPEG.
	OutputJPEG OutputFormat = "jpeg"
	// OutputPNG encodes the result as PNG.
	OutputPNG OutputFormat = "png"
)

type Request

type Request struct {
	Width           int
	Height          int
	Mode            Mode
	OutputFormat    OutputFormat
	ResampleFilter  ResampleFilter
	JPEGQuality     int
	MaxInputBytes   int64
	MaxPixels       int
	MaxWidth        int
	MaxHeight       int
	MaxOutputPixels int
	MaxOutputWidth  int
	MaxOutputHeight int
}

Request describes one bounded image transform.

Zero limit fields use conservative defaults. JPEGQuality defaults to 85.

type ResampleFilter

type ResampleFilter int

ResampleFilter selects the resize algorithm.

const (
	// FilterCubic uses Catmull-Rom resampling.
	FilterCubic ResampleFilter = iota
	// FilterLinear uses approximate bilinear resampling.
	FilterLinear
	// FilterNearest uses nearest-neighbor resampling.
	FilterNearest
)

type Result

type Result struct {
	InputFormat  InputFormat
	OutputFormat OutputFormat
	InputWidth   int
	InputHeight  int
	OutputWidth  int
	OutputHeight int
	Bytes        []byte
}

Result reports transform metadata. Transform populates Bytes; TransformTo writes to the caller-owned writer and leaves Bytes nil.

func Transform

func Transform(ctx context.Context, reader io.Reader, request Request) (Result, error)

Transform reads a bounded image, resizes it, and returns encoded bytes plus metadata.

Example (Exact)
result, err := Transform(context.Background(), bytes.NewReader(examplePNG(400, 200)), Request{
	Width:        100,
	Height:       100,
	Mode:         ModeExact,
	OutputFormat: OutputPNG,
})
if err != nil {
	return
}

fmt.Println(result.OutputFormat, result.OutputWidth, result.OutputHeight)
Output:
png 100 100
Example (Fill)
result, err := Transform(context.Background(), bytes.NewReader(examplePNG(400, 200)), Request{
	Width:        100,
	Height:       100,
	Mode:         ModeFill,
	OutputFormat: OutputPNG,
})
if err != nil {
	return
}

fmt.Println(result.OutputFormat, result.OutputWidth, result.OutputHeight)
Output:
png 100 100
Example (Fit)
result, err := Transform(context.Background(), bytes.NewReader(examplePNG(400, 200)), Request{
	Width:        100,
	Height:       100,
	Mode:         ModeFit,
	OutputFormat: OutputPNG,
})
if err != nil {
	return
}

fmt.Println(result.OutputFormat, result.OutputWidth, result.OutputHeight)
Output:
png 100 50
Example (OutputFormat)
result, err := Transform(context.Background(), bytes.NewReader(examplePNG(32, 32)), Request{
	Width:        16,
	Height:       16,
	OutputFormat: OutputJPEG,
	JPEGQuality:  90,
})
if err != nil {
	return
}

fmt.Println(result.OutputFormat, len(result.Bytes) > 0)
Output:
jpeg true
Example (ZeroValueDefaults)
result, err := Transform(context.Background(), bytes.NewReader(examplePNG(32, 16)), Request{
	Width:  16,
	Height: 16,
})
if err != nil {
	return
}

fmt.Println(result.OutputFormat, result.OutputWidth, result.OutputHeight)
Output:
jpeg 16 8

func TransformTo

func TransformTo(ctx context.Context, writer io.Writer, reader io.Reader, request Request) (Result, error)

TransformTo reads a bounded image, resizes it, and encodes directly to writer. The write is not atomic: a codec or writer failure can leave partial bytes in the writer. Use Transform or write to a caller-owned temporary buffer/object before publishing when final response or storage writes must be all-or-nothing.

Example
var staged bytes.Buffer
result, err := TransformTo(context.Background(), &staged, bytes.NewReader(examplePNG(32, 32)), Request{
	Width:        16,
	Height:       16,
	OutputFormat: OutputPNG,
})
if err != nil {
	return
}

var final bytes.Buffer
if _, err := final.Write(staged.Bytes()); err != nil {
	return
}

fmt.Println(result.OutputFormat, result.OutputWidth, result.OutputHeight, len(result.Bytes), final.Len() > 0)
Output:
png 16 16 0 true

Jump to

Keyboard shortcuts

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