lowleveljpeg

package
v0.4.0-alpha.10 Latest Latest
Warning

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

Go to latest
Published: Jun 23, 2026 License: Apache-2.0, MIT, Apache-2.0, + 1 more Imports: 4 Imported by: 0

Documentation

Overview

Package lowleveljpeg provides a JPEG encoder that takes in-DCT-space coefficients instead of in-XY-space pixels.

It can be useful for experimenting with or visualizing in-DCT-space transformations, such as quantization, extrapolation and progressive-like reduction. Or for learning about how the JPEG file format works. But most programmers should use the Go standard library's image/jpeg package instead.

Example (Basic)

Example_basic demonstrates creating an opaque RGBA image and saving it as a JPEG. It uses 4:2:0 chroma subsampling, the most popular choice for colorful (not gray) JPEG images.

package main

import (
	"bytes"
	"fmt"
	"image"
	"image/color"
	"log"
	"os"

	"github.com/google/wuffs/lib/lowleveljpeg"
)

func main() {
	const width, height = 40, 30
	src := image.NewRGBA(image.Rect(0, 0, width, height))

	// Fill src with a red/blue gradient.
	for y := 0; y < height; y++ {
		blue := uint8((float64(y) * 0xFF) / (height - 1))
		for x := 0; x < width; x++ {
			red := uint8((float64(x) * 0xFF) / (width - 1))
			src.SetRGBA(x, y, color.RGBA{red, 0x00, blue, 0xFF})
		}
	}

	// Initialize the encoder.
	bounds := src.Bounds()
	colorType := lowleveljpeg.ColorTypeYCbCr420
	buf := &bytes.Buffer{}
	enc := lowleveljpeg.Encoder{}
	if err := enc.Reset(buf, colorType, bounds.Dx(), bounds.Dy(), nil); err != nil {
		log.Fatalf("enc.Reset: %v", err)
	}

	// Extract, DCT-transform and add each MCU (Mininum Coded Unit). For 4:2:0
	// Chroma subsampling, each MCU is 16×16 and contains 6 blocks: 4 Y, 1 Cb,
	// 1 Cr.
	dx, dy := colorType.MCUDimensions()
	fmt.Printf("MCU Dimensions: %d, %d.\n", dx, dy)
	srcU8s := lowleveljpeg.Array6BlockU8{}
	srcI16s := lowleveljpeg.Array6BlockI16{}
	for y := bounds.Min.Y; y < bounds.Max.Y; y += dy {
		for x := bounds.Min.X; x < bounds.Max.X; x += dx {
			srcU8s.ExtractYCbCrFrom(src, x, y)
			srcI16s.ForwardDCTFrom(&srcU8s)
			if err := enc.Add6(buf, &srcI16s); err != nil {
				log.Fatalf("enc.Add6: %v", err)
			}
		}
	}

	// Change writeTmpFiles to true if you want to visually inspect the output.
	const writeTmpFiles = false
	const dstFilename = "/tmp/lowleveljpeg_example_basic.jpeg"
	if writeTmpFiles {
		if err := os.WriteFile(dstFilename, buf.Bytes(), 0644); err != nil {
			log.Fatalf("os.WriteFile: %v", err)
		}
		fmt.Println("Wrote  ", dstFilename)
	} else {
		fmt.Println("Skipped", dstFilename)
	}

}
Output:
MCU Dimensions: 16, 16.
Skipped /tmp/lowleveljpeg_example_basic.jpeg
Example (YCbCr444)

Example_yCbCr444 demonstrates loading an RGB PNG, converting to YCbCr and to DCT space and saving as a 4:4:4 JPEG. Multiple JPEG outputs from the one PNG input demonstrate making further transforms during conversion.

package main

import (
	"bytes"
	"fmt"
	"image/jpeg"
	"image/png"
	"log"
	"os"

	"github.com/google/wuffs/lib/lowleveljpeg"
)

func main() {
	// levels holds a rough, ad hoc measure of a coefficient's frequency, in
	// DCT space. Low (or high) levels[i] mean low (or high) frequency.
	//
	// levels[0] == 0 is the DC coefficient. The others are AC coefficients.
	levels := [64]uint8{
		0, 1, 2, 3, 4, 5, 6, 7,
		1, 1, 2, 3, 4, 5, 6, 7,
		2, 2, 2, 3, 4, 5, 6, 7,
		3, 3, 3, 3, 4, 5, 6, 7,
		4, 4, 4, 4, 4, 5, 6, 7,
		5, 5, 5, 5, 5, 5, 6, 7,
		6, 6, 6, 6, 6, 6, 6, 7,
		7, 7, 7, 7, 7, 7, 7, 7,
	}

	// Load the source PNG. We will make numerous JPEG encodings of transformed
	// versions of this PNG image.
	f, err := os.Open("../../test/data/hippopotamus.regular.png")
	if err != nil {
		log.Fatalf("os.Open: %v", err)
	}
	defer f.Close()
	src, err := png.Decode(f)
	if err != nil {
		log.Fatalf("png.Decode: %v", err)
	}

	// Each example (each output JPEG) has a name fragment and a transform from
	// source BlockU8 values to destination BlockI16 values.
	examples := []struct {
		nameFragment string
		quality      int
		transform    func(dst *lowleveljpeg.Array3BlockI16, src *lowleveljpeg.Array3BlockU8)
	}{{

		// Apply the ForwardDCT with no further changes. The resultant JPEG is
		// a low quality (but small in file size) version of the source PNG.
		nameFragment: "0_quality25",
		quality:      25,
		transform: func(dst *lowleveljpeg.Array3BlockI16, src *lowleveljpeg.Array3BlockU8) {
			dst[0].ForwardDCTFrom(&src[0])
			dst[1].ForwardDCTFrom(&src[1])
			dst[2].ForwardDCTFrom(&src[2])
		},
	}, {

		// Ditto, with default quality.
		nameFragment: "1_quality75",
		quality:      75,
		transform: func(dst *lowleveljpeg.Array3BlockI16, src *lowleveljpeg.Array3BlockU8) {
			dst[0].ForwardDCTFrom(&src[0])
			dst[1].ForwardDCTFrom(&src[1])
			dst[2].ForwardDCTFrom(&src[2])
		},
	}, {

		// Ditto, with high quality.
		nameFragment: "2_quality100",
		quality:      100,
		transform: func(dst *lowleveljpeg.Array3BlockI16, src *lowleveljpeg.Array3BlockU8) {
			dst[0].ForwardDCTFrom(&src[0])
			dst[1].ForwardDCTFrom(&src[1])
			dst[2].ForwardDCTFrom(&src[2])
		},
	}, {

		// Like 2_quality100 but swap the Chroma-blue and Chroma-red channels.
		nameFragment: "3_swap_cb_cr",
		quality:      100,
		transform: func(dst *lowleveljpeg.Array3BlockI16, src *lowleveljpeg.Array3BlockU8) {
			dst[0].ForwardDCTFrom(&src[0])
			dst[1].ForwardDCTFrom(&src[2]) // Note the "1" and "2".
			dst[2].ForwardDCTFrom(&src[1]) // Note the "2" and "1".
		},
	}, {

		// Set the 8×8 blocks of the Luma channel to neutral (0x80) except for
		// each top-left corner, which is black (0x00). Chromas are unchanged.
		nameFragment: "4_chroma_only",
		quality:      100,
		transform: func(dst *lowleveljpeg.Array3BlockI16, src *lowleveljpeg.Array3BlockU8) {
			s0 := lowleveljpeg.BlockU8{}
			s0[0] = 0x00
			for i := 1; i < 64; i++ {
				s0[i] = lowleveljpeg.BlockU8NeutralValue
			}
			dst[0].ForwardDCTFrom(&s0)
			dst[1].ForwardDCTFrom(&src[1])
			dst[2].ForwardDCTFrom(&src[2])
		},
	}, {

		// Set the Chroma channels to neutral, as well as any Luma coefficients
		// that have any horizontal variation (within an 8×8 block). What
		// remains are the DC and vertical-only Luma coefficients.
		nameFragment: "5_vertical_luma",
		quality:      100,
		transform: func(dst *lowleveljpeg.Array3BlockI16, src *lowleveljpeg.Array3BlockU8) {
			dst[0].ForwardDCTFrom(&src[0])
			for i := 0; i < 64; i++ {
				if (i & 7) != 0 {
					dst[0][i] = lowleveljpeg.BlockI16NeutralValue
				}
			}
			dst[1] = lowleveljpeg.BlockI16{}
			dst[2] = lowleveljpeg.BlockI16{}
		},
	}, {

		// Set the Chroma channels to neutral, as well as any medium- or
		// high-frequency Luma coefficients.
		nameFragment: "6_low_frequency_luma",
		quality:      100,
		transform: func(dst *lowleveljpeg.Array3BlockI16, src *lowleveljpeg.Array3BlockU8) {
			dst[0] = src[0].ForwardDCT()
			for i := 0; i < 64; i++ {
				if levels[i] > 2 {
					dst[0][i] = 0
				}
			}
			dst[1] = lowleveljpeg.BlockI16{}
			dst[2] = lowleveljpeg.BlockI16{}
		},
	}}

	// Process each example.
	for _, example := range examples {
		// Initialize the encoder.
		quants := lowleveljpeg.Array2QuantizationFactors{}
		quants.SetToStandardValues(example.quality)
		opts := &lowleveljpeg.EncoderOptions{
			QuantizationFactors: &quants,
		}
		bounds := src.Bounds()
		buf := &bytes.Buffer{}
		enc := lowleveljpeg.Encoder{}
		if err := enc.Reset(buf, lowleveljpeg.ColorTypeYCbCr444, bounds.Dx(), bounds.Dy(), opts); err != nil {
			log.Fatalf("enc.Reset: %v", err)
		}

		// Extract, transform and add each MCU (Mininum Coded Unit). For 4:4:4
		// Chroma subsampling, each MCU is 8×8 and contains 3 blocks: 1 Y, 1
		// Cb, 1 Cr.
		srcU8s := lowleveljpeg.Array3BlockU8{}
		srcI16s := lowleveljpeg.Array3BlockI16{}
		for y := bounds.Min.Y; y < bounds.Max.Y; y += 8 {
			for x := bounds.Min.X; x < bounds.Max.X; x += 8 {
				srcU8s.ExtractYCbCrFrom(src, x, y)
				example.transform(&srcI16s, &srcU8s)
				if err := enc.Add3(buf, &srcI16s); err != nil {
					log.Fatalf("enc.Add3: %v", err)
				}
			}
		}

		// As a basic consistency check, confirm that the resultant bytes are a
		// valid JPEG. When copy/pasting this code, you can omit this step.
		dstBytes := buf.Bytes()
		if _, err := jpeg.Decode(bytes.NewReader(dstBytes)); err != nil {
			log.Fatalf("jpeg.Decode: %v", err)
		}

		// Change writeTmpFiles to true if you want to visually inspect the output.
		const writeTmpFiles = false
		dstFilename := fmt.Sprintf("/tmp/lowleveljpeg_example_%s.jpeg", example.nameFragment)
		if writeTmpFiles {
			if err := os.WriteFile(dstFilename, dstBytes, 0644); err != nil {
				log.Fatalf("os.WriteFile: %v", err)
			}
			fmt.Println("Wrote  ", dstFilename)
		} else {
			fmt.Println("Skipped", dstFilename)
		}
	}

}
Output:
Skipped /tmp/lowleveljpeg_example_0_quality25.jpeg
Skipped /tmp/lowleveljpeg_example_1_quality75.jpeg
Skipped /tmp/lowleveljpeg_example_2_quality100.jpeg
Skipped /tmp/lowleveljpeg_example_3_swap_cb_cr.jpeg
Skipped /tmp/lowleveljpeg_example_4_chroma_only.jpeg
Skipped /tmp/lowleveljpeg_example_5_vertical_luma.jpeg
Skipped /tmp/lowleveljpeg_example_6_low_frequency_luma.jpeg

Index

Examples

Constants

View Source
const (
	// BlockU8NeutralValue is the neutral value for a BlockU8, which holds
	// unsigned uint8 values in the range [0x00, 0xFF].
	BlockU8NeutralValue = 0x80

	// BlockI16NeutralValue is the neutral value for a BlockI16, which holds
	// signed int16 values in the range [-0x8000, +0x7FFF].
	BlockI16NeutralValue = 0
)
View Source
const (
	// ColorTypeInvalid, the zero value, is invalid.
	ColorTypeInvalid = ColorType(0)

	// ColorTypeGray means a single channel (Gray).
	ColorTypeGray = ColorType(1)

	// ColorTypeYCbCr444 means three channels (Luma, Chroma-blue, Chroma-red),
	// using 4:4:4 Chroma subsampling.
	ColorTypeYCbCr444 = ColorType(3)

	// ColorTypeYCbCr420 means three channels (Luma, Chroma-blue, Chroma-red),
	// using 4:2:0 Chroma subsampling.
	//
	// This is the most popular color type for colorful (not gray) JPEG images.
	ColorTypeYCbCr420 = ColorType(6)
)
View Source
const (
	// QuantizationStandardValuesTypeLuma means to use table K.1 from the JPEG
	// spec.
	QuantizationStandardValuesTypeLuma = QuantizationStandardValuesType(0)

	// QuantizationStandardValuesTypeChroma means to use table K.2 from the
	// JPEG spec.
	QuantizationStandardValuesTypeChroma = QuantizationStandardValuesType(1)
)
View Source
const (
	// MinimumQuality and MaximumQuality are the minimum and maximum
	// (inclusive) values for SetToStandardValues' quality parameter.
	MinimumQuality = 1
	MaximumQuality = 100

	// DefaultQuality is the default value used by EncoderOptions for
	// SetToStandardValues' quality parameter. It matches libjpeg's default
	// both in terms of numerical value and in behavior.
	DefaultQuality = 75

	// MinimumBaselineQuality is lowest quality level where both the cjpeg
	// program (from the libjpeg C project) and this Go package will agree on
	// the exact quantization factors.
	//
	// It's still valid to pass a SetToStandardValues quality parameter value
	// below 24. But when doing so, passing the equivalent to cjpeg will print
	// a JTRC_16BIT_TABLES warning: "quantization tables are too coarse for
	// baseline JPEG". cjpeg will therefore produce extended (instead of
	// baseline) JPEGs, using 2 bytes (instead of 1 byte) per quantization
	// factor, allowing factors above 0xFF.
	//
	// This Go package will instead clamp such quantization factors to 0xFF.
	//
	// Both approaches are viable, producing valid JPEGs. This Go package, like
	// the Go standard library's image/jpeg package, simply chooses to always
	// produce baseline (instead of extended) JPEGs, for best compatibility
	// with other JPEG decoders.
	MinimumBaselineQuality = 24
)

Variables

View Source
var (
	ErrBadAddNForColorType     = errors.New("lowleveljpeg: bad AddN for ColorType")
	ErrBadArgument             = errors.New("lowleveljpeg: bad argument")
	ErrInvalidBlockI16         = errors.New("lowleveljpeg: invalid BlockI16")
	ErrNilReceiver             = errors.New("lowleveljpeg: nil receiver")
	ErrPreviouslyReturnedError = errors.New("lowleveljpeg: previously returned error")
	ErrTooManyAddNCalls        = errors.New("lowleveljpeg: too many AddN calls")
)

Functions

func RGBToYCoCg

func RGBToYCoCg(r, g, b uint8) (uint8, uint8, uint8)

RGBToYCoCg converts an RGB triple to a YCoCg triple.

JPEG uses YCbCr, not YCoCg, but this function allows for experimenting with JPEG-inspired color transformations.

func YCoCgToRGB

func YCoCgToRGB(yy, co, cg uint8) (uint8, uint8, uint8)

YCoCgToRGB converts a YCoCg triple to an RGB triple.

JPEG uses YCbCr, not YCoCg, but this function allows for experimenting with JPEG-inspired color transformations.

Types

type Array1BlockI16

type Array1BlockI16 [1]BlockI16

ArrayNBlockT are arrays of N BlockT values. N is the number of blocks in a JPEG MCU (Mininum Coded Unit).

  • N = 1 is for ColorTypeGray.
  • N = 3 is for ColorTypeYCbCr444.
  • N = 6 is for ColorTypeYCbCr420.

func (*Array1BlockI16) ForwardDCTFrom

func (dst *Array1BlockI16) ForwardDCTFrom(src *Array1BlockU8)

ForwardDCTFrom calls ForwardDCTFrom pairwise on dst and src elements.

func (*Array1BlockI16) SetToNeutral

func (b *Array1BlockI16) SetToNeutral()

SetToNeutral calls SetToNeutral on each element.

type Array1BlockU8

type Array1BlockU8 [1]BlockU8

ArrayNBlockT are arrays of N BlockT values. N is the number of blocks in a JPEG MCU (Mininum Coded Unit).

  • N = 1 is for ColorTypeGray.
  • N = 3 is for ColorTypeYCbCr444.
  • N = 6 is for ColorTypeYCbCr420.

func (*Array1BlockU8) ExtractYCbCrFrom

func (dst *Array1BlockU8) ExtractYCbCrFrom(m image.Image, topLeftX int, topLeftY int)

ExtractYCbCrFrom sets dst to a single channel (Gray) 8×8 MCU (Minimum Coded Unit), with the given top-left corner, from the image m.

func (*Array1BlockU8) ExtractYCoCgFrom

func (dst *Array1BlockU8) ExtractYCoCgFrom(m image.Image, topLeftX int, topLeftY int)

ExtractYCoCgFrom is like ExtractYCbCrFrom but produces Gray (Luma) values according to the (Luma, Chroma-orange, Chroma-green) formulae instead of (Luma, Chroma-blue, Chroma-red).

JPEG uses YCbCr, not YCoCg, but this method allows for experimenting with JPEG-inspired image transformations.

func (*Array1BlockU8) InverseDCTFrom

func (dst *Array1BlockU8) InverseDCTFrom(src *Array1BlockI16)

InverseDCTFrom calls InverseDCTFrom pairwise on dst and src elements.

func (*Array1BlockU8) SetToNeutral

func (b *Array1BlockU8) SetToNeutral()

SetToNeutral calls SetToNeutral on each element.

type Array2QuantizationFactors

type Array2QuantizationFactors [2]QuantizationFactors

Array2QuantizationFactors is an array of 2 QuantizationFactors. The first one is for Luma and the second one is for Chroma.

func (*Array2QuantizationFactors) SetToStandardValues

func (b *Array2QuantizationFactors) SetToStandardValues(quality int)

SetToStandardValues calls SetToStandardValues on each element.

type Array3BlockI16

type Array3BlockI16 [3]BlockI16

ArrayNBlockT are arrays of N BlockT values. N is the number of blocks in a JPEG MCU (Mininum Coded Unit).

  • N = 1 is for ColorTypeGray.
  • N = 3 is for ColorTypeYCbCr444.
  • N = 6 is for ColorTypeYCbCr420.

func (*Array3BlockI16) ForwardDCTFrom

func (dst *Array3BlockI16) ForwardDCTFrom(src *Array3BlockU8)

ForwardDCTFrom calls ForwardDCTFrom pairwise on dst and src elements.

func (*Array3BlockI16) SetToNeutral

func (b *Array3BlockI16) SetToNeutral()

SetToNeutral calls SetToNeutral on each element.

type Array3BlockU8

type Array3BlockU8 [3]BlockU8

ArrayNBlockT are arrays of N BlockT values. N is the number of blocks in a JPEG MCU (Mininum Coded Unit).

  • N = 1 is for ColorTypeGray.
  • N = 3 is for ColorTypeYCbCr444.
  • N = 6 is for ColorTypeYCbCr420.

func (*Array3BlockU8) ExtractYCbCrFrom

func (dst *Array3BlockU8) ExtractYCbCrFrom(m image.Image, topLeftX int, topLeftY int)

ExtractYCbCrFrom sets dst to a three channel (Luma, Chroma-blue, Chroma-red) 8×8 4:4:4 MCU (Minimum Coded Unit), with the given top-left corner, from the image m.

func (*Array3BlockU8) ExtractYCoCgFrom

func (dst *Array3BlockU8) ExtractYCoCgFrom(m image.Image, topLeftX int, topLeftY int)

ExtractYCoCgFrom is like ExtractYCbCrFrom but produces (Luma, Chroma-orange, Chroma-green) instead of (Luma, Chroma-blue, Chroma-red).

JPEG uses YCbCr, not YCoCg, but this method allows for experimenting with JPEG-inspired image transformations.

func (*Array3BlockU8) InverseDCTFrom

func (dst *Array3BlockU8) InverseDCTFrom(src *Array3BlockI16)

InverseDCTFrom calls InverseDCTFrom pairwise on dst and src elements.

func (*Array3BlockU8) SetToNeutral

func (b *Array3BlockU8) SetToNeutral()

SetToNeutral calls SetToNeutral on each element.

type Array6BlockI16

type Array6BlockI16 [6]BlockI16

ArrayNBlockT are arrays of N BlockT values. N is the number of blocks in a JPEG MCU (Mininum Coded Unit).

  • N = 1 is for ColorTypeGray.
  • N = 3 is for ColorTypeYCbCr444.
  • N = 6 is for ColorTypeYCbCr420.

func (*Array6BlockI16) ForwardDCTFrom

func (dst *Array6BlockI16) ForwardDCTFrom(src *Array6BlockU8)

ForwardDCTFrom calls ForwardDCTFrom pairwise on dst and src elements.

func (*Array6BlockI16) SetToNeutral

func (b *Array6BlockI16) SetToNeutral()

SetToNeutral calls SetToNeutral on each element.

type Array6BlockU8

type Array6BlockU8 [6]BlockU8

ArrayNBlockT are arrays of N BlockT values. N is the number of blocks in a JPEG MCU (Mininum Coded Unit).

  • N = 1 is for ColorTypeGray.
  • N = 3 is for ColorTypeYCbCr444.
  • N = 6 is for ColorTypeYCbCr420.

func (*Array6BlockU8) ExtractYCbCrFrom

func (dst *Array6BlockU8) ExtractYCbCrFrom(m image.Image, topLeftX int, topLeftY int)

ExtractYCbCrFrom sets dst to a three channel (Luma, Chroma-blue, Chroma-red) 16×16 4:2:0 MCU (Minimum Coded Unit, with the given top-left corner, from the image m.

The 6 elements are:

  • Luma top left
  • Luma top right
  • Luma bottom left
  • Luma bottom right
  • Chroma-blue
  • Chroma-red

func (*Array6BlockU8) ExtractYCoCgFrom

func (dst *Array6BlockU8) ExtractYCoCgFrom(m image.Image, topLeftX int, topLeftY int)

ExtractYCoCgFrom is like ExtractYCbCrFrom but produces (Luma, Chroma-orange, Chroma-green) instead of (Luma, Chroma-blue, Chroma-red).

JPEG uses YCbCr, not YCoCg, but this method allows for experimenting with JPEG-inspired image transformations.

func (*Array6BlockU8) InverseDCTFrom

func (dst *Array6BlockU8) InverseDCTFrom(src *Array6BlockI16)

InverseDCTFrom calls InverseDCTFrom pairwise on dst and src elements.

func (*Array6BlockU8) SetToNeutral

func (b *Array6BlockU8) SetToNeutral()

SetToNeutral calls SetToNeutral on each element.

type BlockI16

type BlockI16 [64]int16

BlockI16 is an 8×8 block of int16 values, such as a block of JPEG coefficients.

It is indexed in DCT (not XY) space. If b is a BlockI16 then b[0] is the DC coefficient and every other element is an AC coefficient.

The horizontal-only AC coefficients are b[1], b[2], ..., b[7], in order from low-frequency to high-frequency.

The vertical-only AC coefficients are b[8], b[16], ..., b[56], in order from low-frequency to high-frequency.

func (*BlockI16) Abs

func (b *BlockI16) Abs() (ret BlockI16)

Abs returns the elementwise absolute value of b.

func (*BlockI16) ForwardDCTFrom

func (dst *BlockI16) ForwardDCTFrom(src *BlockU8)

ForwardDCTFrom sets *dst to src.ForwardDCT().

func (*BlockI16) InverseDCT

func (b *BlockI16) InverseDCT() (ret BlockU8)

InverseDCT returns the IDCT (Inverse Discrete Cosine Transform) of b.

func (*BlockI16) IsValid

func (b *BlockI16) IsValid() bool

IsValid returns whether b does not contain unexpectedly extreme values for an 8-bit-depth JPEG - one that is invalid to pass to AddN. ForwardDCT or ForwardDCTFrom always returns or sets a BlockI16 that IsValid.

Specifically:

  • a DC element is out of range when outside [-1024, +1023].
  • an AC element is out of range when outside [-1023, +1023].

A BlockI16 is valid when none of its elements are out of range.

func (*BlockI16) SetToNeutral

func (b *BlockI16) SetToNeutral()

SetToNeutral sets each element to BlockI16NeutralValue.

func (BlockI16) String

func (b BlockI16) String() string

String returns b in human-readable form.

type BlockU8

type BlockU8 [64]uint8

BlockU8 is an 8×8 block of uint8 values, such as a block of red, green, blue or gray pixel values.

It is indexed in XY (not DCT) space. If b is a BlockU8 then b[0] is the top-left corner and b[8] is one pixel below that.

func (*BlockU8) DownsampleFrom

func (dst *BlockU8) DownsampleFrom(src *QuadBlockU8)

DownsampleFrom reduces one 16×16 quad-block to one 8×8 block.

func (*BlockU8) ForwardDCT

func (b *BlockU8) ForwardDCT() (ret BlockI16)

ForwardDCT returns the FDCT (Forward Discrete Cosine Transform) of b.

func (*BlockU8) InverseDCTFrom

func (dst *BlockU8) InverseDCTFrom(src *BlockI16)

InverseDCTFrom sets *dst to src.InverseDCT().

func (*BlockU8) SetToNeutral

func (b *BlockU8) SetToNeutral()

SetToNeutral sets each element to BlockU8NeutralValue.

func (BlockU8) String

func (b BlockU8) String() string

String returns b in human-readable form.

type ColorType

type ColorType byte

ColorType is a JPEG image's color type.

func (ColorType) MCUDimensions

func (c ColorType) MCUDimensions() (width int, height int)

MCUDimensions returns the width and height of a Mininum Coded Unit.

type Encoder

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

Encoder writes JPEG-formatted bytes to an io.Writer.

Call Reset and then AddN multiple times (N depends on the ColorType). Each AddN call encodes a Minimum Coded Unit (an 8×8 or 16×16 group of pixels, depending on the ColorType). Add MCUs in left-to-right top-to-bottom order. The final AddN call also writes the JPEG footer.

AddN takes ArrayNBlockI16 arguments, which are post-FDCT (when encoding) or pre-IDCT (when decoding) coefficients.

To get ArrayNBlockI16 values from pixels, use ExtractYCbCrFrom on an image.Image (to get an array of BlockU8 values) and then FowardDCTFrom (to get an array of BlockI16 values). See Example_basic for an example.

An Encoder makes no allocations, other than the Encoder struct itself and any allocations that the passed io.Writer makes.

An Encoder can be re-used, by calling Reset.

func (*Encoder) Add1

func (e *Encoder) Add1(w io.Writer, b *Array1BlockI16) error

Add1 adds an 8×8 group of pixels to a ColorTypeGray image.

func (*Encoder) Add3

func (e *Encoder) Add3(w io.Writer, b *Array3BlockI16) error

Add3 adds an 8×8 group of pixels to a ColorTypeYCbCr444 image.

func (*Encoder) Add6

func (e *Encoder) Add6(w io.Writer, b *Array6BlockI16) error

Add6 adds a 16×16 group of pixels to a ColorTypeYCbCr420 image.

func (*Encoder) Reset

func (e *Encoder) Reset(w io.Writer, colorType ColorType, width int, height int, options *EncoderOptions) error

Reset makes an Encoder ready to use (ready to make AddN calls), for encoding a JPEG with the given colorType, width and height.

colorType should be ColorTypeGray, ColorTypeYCbCr444 or ColorTypeYCbCr420.

width and height should both be positive but no larger than 0xFFFF, since a JPEG image cannot represent anything larger.

options may be nil, which means to use the default configuration.

type EncoderOptions

type EncoderOptions struct {
	// QuantizationFactors are the BlockI16 quantization factors. A nil pointer
	// is equivalent to using DefaultQuality.
	QuantizationFactors *Array2QuantizationFactors
}

EncoderOptions are optional arguments to Encoder.Reset. The zero value is valid and means to use the default configuration.

type QuadBlockU8

type QuadBlockU8 [256]uint8

QuadBlockU8 is like a BlockU8 but it is 16×16 instead of 8×8.

It is indexed in XY (not DCT) space. If b is a QuadBlockU8 then b[0] is the top-left corner and b[16] is one pixel below that.

func (*QuadBlockU8) SetToNeutral

func (b *QuadBlockU8) SetToNeutral()

SetToNeutral sets each element to BlockU8NeutralValue.

func (QuadBlockU8) String

func (b QuadBlockU8) String() string

String returns b in human-readable form.

func (*QuadBlockU8) UpsampleFrom

func (dst *QuadBlockU8) UpsampleFrom(src *BlockU8)

UpsampleFrom produces one 16×16 quad-block from one 8×8 block.

It uses a triangle filter.

type QuantizationFactors

type QuantizationFactors [64]uint8

QuantizationFactors is an 8×8 block of uint8 values, used to quantize a BlockI16.

It is indexed in DCT (not XY) space, like a Block16.

func (*QuantizationFactors) IsValid

func (b *QuantizationFactors) IsValid() bool

IsValid returns whether b does not contain any zero-valued elements.

func (*QuantizationFactors) SetToStandardValues

func (b *QuantizationFactors) SetToStandardValues(which QuantizationStandardValuesType, quality int)

SetToStandardValues sets b to one of two standard quantization tables (Tables K.1 or K.2 in the JPEG spec, for Luma and Chroma respectively), scaled by a quality parameter with the same meaning as that used by libjpeg's encoder.

The quality parameter ranges from 1 (low quality) to 100 (high quality), inclusive. Values outside of that range will be clamped to be in [1, 100].

Passing quality = MinimumQuality will set every element of b to 0xFF.

Passing quality = MaximumQuality will set every element of b to 0x01.

func (QuantizationFactors) String

func (b QuantizationFactors) String() string

String returns b in human-readable form.

type QuantizationStandardValuesType

type QuantizationStandardValuesType byte

QuantizationStandardValuesType selects which table from the JPEG specification to use for SetToStandardValues.

Jump to

Keyboard shortcuts

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