gif

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2026 License: BSD-3-Clause Imports: 12 Imported by: 0

README

gif

A fork of Go's image/gif, under the same BSD-3-Clause licence. The import path is github.com/go-images/gif. Every change is stated in NOTICE, and Go's own test suite passes here unaltered in substance.

What differs: DecodePartial says what a stream that stopped early did decode.

img, rows, err := gif.DecodePartial(r)

The first frame at its full declared size, the number of pixel rows that are complete counting from the top, and the error that stopped the decode — nil when the frame arrived whole. Rows past the count hold whatever the frame was allocated with, so a caller draws the first rows and nothing else.

Decode is all-or-nothing, and for a file still arriving that is the same as having nothing. image/jpeg and image/png answer the same way, so this is a gap in the shape of every decoder rather than in one of them.

For a 150×103 picture:

bytes given rows offered
20% 21 20.4%
40% 43 41.7%
60% 61 59.2%
80% 79 76.7%
100% 103 100%

The change is small because the decoder already did the work

A frame's pixels are read with one readFull, which writes what arrived before reporting that it ran out. The rows were already in the buffer; only the count and the frame were being discarded.

The count is exact, in both directions

It never names more than arrived, and it never names less. Under-claiming is invisible to a check that only verifies the rows it offers, and it shows a caller less of the picture than it has. Over every fixture here the first row that differs from the complete decode is the count — measured before it was asserted, and the test asserts the equality rather than a tolerance.

What is refused, and what is not

An interlaced frame is refused, with a nil image and zero rows: its rows arrive in passes covering the whole frame — every eighth row, then the gaps between them — and uninterlace has not run, so what is in the buffer is not "the first n rows" of anything.

An animation is not a special case. Only the first frame is ever reported, which costs nothing: the decoder returns as soon as one frame is whole, so a truncated animation whose first frame arrived decodes successfully with every row. Each frame after the first is a patch over the one before with its own disposal rule, so a later frame's rows are not something a caller could draw alone.

Everything else

Identical to the standard library, including Encode and EncodeAll. Use it exactly as you would use image/gif.

Documentation

Overview

Package gif implements a GIF image decoder and encoder.

The GIF specification is at https://www.w3.org/Graphics/GIF/spec-gif89a.txt.

Index

Constants

View Source
const (
	DisposalNone       = 0x01
	DisposalBackground = 0x02
	DisposalPrevious   = 0x03
)

Disposal Methods.

Variables

This section is empty.

Functions

func Decode

func Decode(r io.Reader) (image.Image, error)

Decode reads a GIF image from r and returns the first embedded image as an image.Image.

func DecodeConfig

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

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

func DecodePartial

func DecodePartial(r io.Reader) (image.Image, int, error)

DecodePartial decodes as much of a GIF's FIRST frame as r holds, and says how much is real. DecodePartial decodes as much of a GIF's FIRST frame as r holds, and says how much of it is real.

It returns the frame at its full declared size, the number of pixel rows that are complete counting from the top, and the error that stopped the decode — nil when the frame arrived whole. Rows past the count hold whatever the frame was allocated with, so a caller draws the first rows and nothing else.

⛔ Decode is all-or-nothing, and for a file still arriving that is the same as having nothing. Measured on real fixtures cut at four fractions: a nil image and "not enough image data" every time. image/jpeg and image/png answer the same way, so this is a gap in the shape of every decoder rather than in one of them.

⛔ The FIRST frame, and only ever the first — which costs nothing, because that is where an animation's picture is. Each frame after it is a patch over the one before with its own disposal rule, so a later frame's rows are not something a caller can draw on their own. The decoder stops once one frame is whole, so a truncated animation whose first frame arrived reports SUCCESS with every row.

⛔ An INTERLACED frame is refused, with a nil image and zero rows. Its rows arrive in passes covering the whole frame — every eighth row, then the gaps — and uninterlace has not run, so "rows from the top" describes nothing about what is in the buffer.

func Encode

func Encode(w io.Writer, m image.Image, o *Options) error

Encode writes the Image m to w in GIF format.

func EncodeAll

func EncodeAll(w io.Writer, g *GIF) error

EncodeAll writes the images in g to w in GIF format with the given loop count and delay between frames.

Types

type GIF

type GIF struct {
	Image []*image.Paletted // The successive images.
	Delay []int             // The successive delay times, one per frame, in 100ths of a second.
	// LoopCount controls the number of times an animation will be
	// restarted during display.
	// A LoopCount of 0 means to loop forever.
	// A LoopCount of -1 means to show each frame only once.
	// Otherwise, the animation is looped LoopCount+1 times.
	LoopCount int
	// Disposal is the successive disposal methods, one per frame. For
	// backwards compatibility, a nil Disposal is valid to pass to EncodeAll,
	// and implies that each frame's disposal method is 0 (no disposal
	// specified).
	Disposal []byte
	// Config is the global color table (palette), width and height. A nil or
	// empty-color.Palette Config.ColorModel means that each frame has its own
	// color table and there is no global color table. Each frame's bounds must
	// be within the rectangle defined by the two points (0, 0) and
	// (Config.Width, Config.Height).
	//
	// For backwards compatibility, a zero-valued Config is valid to pass to
	// EncodeAll, and implies that the overall GIF's width and height equals
	// the first frame's bounds' Rectangle.Max point.
	Config image.Config
	// BackgroundIndex is the background index in the global color table, for
	// use with the DisposalBackground disposal method.
	BackgroundIndex byte
}

GIF represents the possibly multiple images stored in a GIF file.

func DecodeAll

func DecodeAll(r io.Reader) (*GIF, error)

DecodeAll reads a GIF image from r and returns the sequential frames and timing information.

type Options

type Options struct {
	// NumColors is the maximum number of colors used in the image.
	// It ranges from 1 to 256.
	NumColors int

	// Quantizer is used to produce a palette with size NumColors.
	// palette.Plan9 is used in place of a nil Quantizer.
	Quantizer draw.Quantizer

	// Drawer is used to convert the source image to the desired palette.
	// draw.FloydSteinberg is used in place of a nil Drawer.
	Drawer draw.Drawer
}

Options are the encoding parameters.

Jump to

Keyboard shortcuts

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