pngscaled

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 25, 2026 License: MIT Imports: 11 Imported by: 0

README

go-scaled-png

A PNG decoder that scales images down while decoding, avoiding the memory cost of allocating a full-size intermediate image.

Installation

go get github.com/m8rge/go-scaled-png

How it works

The standard approach — png.Decode then imaging.Resize — allocates the full-resolution image first, then resamples it. For large PNGs this means holding two images in memory simultaneously.

This package integrates the horizontal resample pass directly into the PNG row-decode loop. Each source row is resampled horizontally as it comes out of the DEFLATE stream. The vertical resample pass runs in-place after all rows are decoded, using the pre-allocated destination buffer.

Peak memory usage is proportional to the output image size, not the input size.

API

import pngscaled "github.com/m8rge/go-scaled-png"

img, err := pngscaled.Decode(r, targetWidth, targetHeight, pngscaled.MitchellNetravali)
  • r — any io.Reader over PNG data.
  • targetWidth, targetHeight — desired output dimensions. Pass 0 to skip resizing on that axis (the original dimension is preserved).
  • Filter — one of the supported kernels (see below).

Filters

MitchellNetravali is the recommended default; CatmullRom and Lanczos are sharper; Linear and Box are faster; and Gaussian, BSpline, Hermite, Bartlett, Hann, Hamming, Blackman, Welch, and Cosine are available for specialized needs.

Limitations

  • Upscaling is not supported. If targetWidth or targetHeight is larger than the source dimension on that axis, the source size is used instead.
  • Interlaced PNG images are not resized. The full image is decoded and returned at its original size.

Benchmarks

Benchmarks for a 3456x2234 source image (16" MBP screen resolution) are in BenchmarkResizeLargePNGScaled and BenchmarkResizeLargeStdlibImaging:

go test -run '^$' -bench 'BenchmarkResizeLarge(PNGScaled|StdlibImaging)' -benchmem -count=5 ./...

These cover 3456x2234 -> 1920x1080 (Full HD) and 3456x2234 -> 32x32.

Reference run (darwin/arm64, Apple M2, averages over -count=5):

Benchmark CPU (ns/op) Memory (B/op) Allocs (allocs/op)
BenchmarkResizeLargePNGScaled/3456x2234_to_1920x1080 74423030 17274031 35.8
BenchmarkResizeLargePNGScaled/3456x2234_to_32x32 55202217 354517 16.0

For baseline comparison (png.Decode + imaging.Resize on the same data):

Benchmark CPU (ns/op) Memory (B/op) Allocs (allocs/op)
BenchmarkResizeLargeStdlibImaging/3456x2234_to_1920x1080 58284645 57329325 63.0
BenchmarkResizeLargeStdlibImaging/3456x2234_to_32x32 45089980 31831211 63.0

The sample visual inspection tool is documented in cmd/shrink-samples/README.md.

Testing

go test ./...
go test -run TestShrinkGolden -update   # regenerate golden reference files

Tests use the public-domain PNG test suite files in testdata/pngsuite/, covering all PNG color types, bit depths, filter types, and tRNS variants.

Documentation

Overview

Package pngscaled implements a PNG image decoder that decodes and scale down image at same time.

The PNG specification is at https://www.w3.org/TR/PNG/.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Decode

func Decode(r io.Reader, targetWidth, targetHeight int, filter ResampleFilter) (image.Image, error)

Decode reads a PNG image from r and returns it as an image.Image. If targetWidth/targetHeight are > 0, the decoder may scale while decoding. MVP: only 8-bit decode paths (cbTC8 / cbTCA8 / cbG8) are supported here. Pass filter for resampling (e.g. ImagingFilter(Lanczos.Support, Lanczos.Kernel)).

func VerticalGray16InPlaceQ15

func VerticalGray16InPlaceQ15(img *image.Gray16, dstH int, f ResampleFilter)

func VerticalGrayInPlaceQ15

func VerticalGrayInPlaceQ15(img *image.Gray, dstH int, f ResampleFilter)

Gray (8-bit)

func VerticalNRGBA64InPlaceQ15

func VerticalNRGBA64InPlaceQ15(img *image.NRGBA64, dstH int, f ResampleFilter)

func VerticalNRGBAInPlaceQ15

func VerticalNRGBAInPlaceQ15(img *image.NRGBA, dstH int, f ResampleFilter)

NRGBA (straight alpha — uses premultiplied accumulation to avoid dark halos)

func VerticalRGBA64InPlaceQ15

func VerticalRGBA64InPlaceQ15(img *image.RGBA64, dstH int, f ResampleFilter)

func VerticalRGBAInPlaceQ15

func VerticalRGBAInPlaceQ15(img *image.RGBA, dstH int, f ResampleFilter)

RGBA (straight alpha)

Types

type Config

type Config struct {
	image.Config
	Interlaced bool
}

func DecodeConfig

func DecodeConfig(r io.Reader) (Config, error)

DecodeConfig returns the color model and dimensions of a PNG image without decoding the entire image.

type FormatError

type FormatError string

A FormatError reports that the input is not a valid PNG.

func (FormatError) Error

func (e FormatError) Error() string

type ResampleFilter

type ResampleFilter struct {
	Support float64
	Kernel  func(float64) float64
}

ResampleFilter specifies a resampling filter to be used for image resizing.

General filter recommendations:

- Lanczos
	A high-quality resampling filter for photographic images yielding sharp results.

- CatmullRom
	A sharp cubic filter that is faster than Lanczos filter while providing similar results.

- MitchellNetravali
	A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.

- Linear
	Bilinear resampling filter, produces a smooth output. Faster than cubic filters.

- Box
	Simple and fast averaging filter appropriate for downscaling.
	When upscaling it's similar to NearestNeighbor.

- NearestNeighbor
	Fastest resampling filter, no antialiasing.
var BSpline ResampleFilter

BSpline is a smooth cubic filter (BC-spline; B=1; C=0).

var Bartlett ResampleFilter

Bartlett is a Bartlett-windowed sinc filter (3 lobes).

var Blackman ResampleFilter

Blackman is a Blackman-windowed sinc filter (3 lobes).

var Box ResampleFilter

Box filter (averaging pixels).

var CatmullRom ResampleFilter

CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).

var Cosine ResampleFilter

Cosine is a Cosine-windowed sinc filter (3 lobes).

var Gaussian ResampleFilter

Gaussian is a Gaussian blurring filter.

var Hamming ResampleFilter

Hamming is a Hamming-windowed sinc filter (3 lobes).

var Hann ResampleFilter

Hann is a Hann-windowed sinc filter (3 lobes).

var Hermite ResampleFilter

Hermite cubic spline filter (BC-spline; B=0; C=0).

var Lanczos ResampleFilter

Lanczos filter (3 lobes).

var Linear ResampleFilter

Linear filter.

var MitchellNetravali ResampleFilter

MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).

var Welch ResampleFilter

Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes).

type UnsupportedError

type UnsupportedError string

An UnsupportedError reports that the input uses a valid but unimplemented PNG feature.

func (UnsupportedError) Error

func (e UnsupportedError) Error() string

Directories

Path Synopsis
cmd
shrink-samples command
shrink-samples decodes PNG files and writes scaled-down versions to an output directory for visual inspection.
shrink-samples decodes PNG files and writes scaled-down versions to an output directory for visual inspection.

Jump to

Keyboard shortcuts

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