src/pkg/image/format.go - The Go Programming Language

Golang

Source file src/pkg/image/format.go

     1	// Copyright 2010 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package image
     6	
     7	import (
     8		"bufio"
     9		"errors"
    10		"io"
    11	)
    12	
    13	// ErrFormat indicates that decoding encountered an unknown format.
    14	var ErrFormat = errors.New("image: unknown format")
    15	
    16	// A format holds an image format's name, magic header and how to decode it.
    17	type format struct {
    18		name, magic  string
    19		decode       func(io.Reader) (Image, error)
    20		decodeConfig func(io.Reader) (Config, error)
    21	}
    22	
    23	// Formats is the list of registered formats.
    24	var formats []format
    25	
    26	// RegisterFormat registers an image format for use by Decode.
    27	// Name is the name of the format, like "jpeg" or "png".
    28	// Magic is the magic prefix that identifies the format's encoding. The magic
    29	// string can contain "?" wildcards that each match any one byte.
    30	// Decode is the function that decodes the encoded image.
    31	// DecodeConfig is the function that decodes just its configuration.
    32	func RegisterFormat(name, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error)) {
    33		formats = append(formats, format{name, magic, decode, decodeConfig})
    34	}
    35	
    36	// A reader is an io.Reader that can also peek ahead.
    37	type reader interface {
    38		io.Reader
    39		Peek(int) ([]byte, error)
    40	}
    41	
    42	// AsReader converts an io.Reader to a reader.
    43	func asReader(r io.Reader) reader {
    44		if rr, ok := r.(reader); ok {
    45			return rr
    46		}
    47		return bufio.NewReader(r)
    48	}
    49	
    50	// Match returns whether magic matches b. Magic may contain "?" wildcards.
    51	func match(magic string, b []byte) bool {
    52		if len(magic) != len(b) {
    53			return false
    54		}
    55		for i, c := range b {
    56			if magic[i] != c && magic[i] != '?' {
    57				return false
    58			}
    59		}
    60		return true
    61	}
    62	
    63	// Sniff determines the format of r's data.
    64	func sniff(r reader) format {
    65		for _, f := range formats {
    66			b, err := r.Peek(len(f.magic))
    67			if err == nil && match(f.magic, b) {
    68				return f
    69			}
    70		}
    71		return format{}
    72	}
    73	
    74	// Decode decodes an image that has been encoded in a registered format.
    75	// The string returned is the format name used during format registration.
    76	// Format registration is typically done by the init method of the codec-
    77	// specific package.
    78	func Decode(r io.Reader) (Image, string, error) {
    79		rr := asReader(r)
    80		f := sniff(rr)
    81		if f.decode == nil {
    82			return nil, "", ErrFormat
    83		}
    84		m, err := f.decode(rr)
    85		return m, f.name, err
    86	}
    87	
    88	// DecodeConfig decodes the color model and dimensions of an image that has
    89	// been encoded in a registered format. The string returned is the format name
    90	// used during format registration. Format registration is typically done by
    91	// the init method of the codec-specific package.
    92	func DecodeConfig(r io.Reader) (Config, string, error) {
    93		rr := asReader(r)
    94		f := sniff(rr)
    95		if f.decodeConfig == nil {
    96			return Config{}, "", ErrFormat
    97		}
    98		c, err := f.decodeConfig(rr)
    99		return c, f.name, err
   100	}