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 5package image 6 7import ( 8 "bufio" 9 "errors" 10 "io" 11) 12 13// ErrFormat indicates that decoding encountered an unknown format. 14var ErrFormat = errors.New("image: unknown format") 15 16// A format holds an image format's name, magic header and how to decode it. 17type 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. 24var 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. 32func 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. 37type reader interface { 38 io.Reader 39 Peek(int) ([]byte, error) 40} 41 42// asReader converts an io.Reader to a reader. 43func 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 reports whether magic matches b. Magic may contain "?" wildcards. 51func 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. 64func 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 an init function in the codec- 77// specific package. 78func 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// an init function in the codec-specific package. 92func 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} 101