| // Copyright 2010 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package image | |
| import ( | |
| "bufio" | |
| "io" | |
| "os" | |
| ) | |
| // An UnknownFormatErr indicates that decoding encountered an unknown format. | |
| var UnknownFormatErr = os.NewError("image: unknown format") | |
| // A format holds an image format's name, magic header and how to decode it. | |
| type format struct { | |
| name, magic string | |
| decode func(io.Reader) (Image, os.Error) | |
| decodeConfig func(io.Reader) (Config, os.Error) | |
| } | |
| // Formats is the list of registered formats. | |
| var formats []format | |
| // RegisterFormat registers an image format for use by Decode. | |
| // Name is the name of the format, like "jpeg" or "png". | |
| // Magic is the magic prefix that identifies the format's encoding. | |
| // Decode is the function that decodes the encoded image. | |
| // DecodeConfig is the function that decodes just its configuration. | |
| func RegisterFormat(name, magic string, decode func(io.Reader) (Image, os.Error), decodeConfig func(io.Reader) (Config, os.Error)) { | |
| n := len(formats) | |
| if n == cap(formats) { | |
| x := make([]format, n+1, 2*n+4) | |
| copy(x, formats) | |
| formats = x | |
| } else { | |
| formats = formats[0 : n+1] | |
| } | |
| formats[n] = format{name, magic, decode, decodeConfig} | |
| } | |
| // A reader is an io.Reader that can also peek ahead. | |
| type reader interface { | |
| io.Reader | |
| Peek(int) ([]byte, os.Error) | |
| } | |
| // AsReader converts an io.Reader to a reader. | |
| func asReader(r io.Reader) reader { | |
| if rr, ok := r.(reader); ok { | |
| return rr | |
| } | |
| return bufio.NewReader(r) | |
| } | |
| // sniff determines the format of r's data. | |
| func sniff(r reader) format { | |
| for _, f := range formats { | |
| s, err := r.Peek(len(f.magic)) | |
| if err == nil && string(s) == f.magic { | |
| return f | |
| } | |
| } | |
| return format{} | |
| } | |
| // Decode decodes an image that has been encoded in a registered format. | |
| // The string returned is the format name used during format registration. | |
| // Format registration is typically done by the init method of the codec- | |
| // specific package. | |
| func Decode(r io.Reader) (Image, string, os.Error) { | |
| rr := asReader(r) | |
| f := sniff(rr) | |
| if f.decode == nil { | |
| return nil, "", UnknownFormatErr | |
| } | |
| m, err := f.decode(rr) | |
| return m, f.name, err | |
| } | |
| // DecodeConfig decodes the color model and dimensions of an image that has | |
| // been encoded in a registered format. The string returned is the format name | |
| // used during format registration. Format registration is typically done by | |
| // the init method of the codec-specific package. | |
| func DecodeConfig(r io.Reader) (Config, string, os.Error) { | |
| rr := asReader(r) | |
| f := sniff(rr) | |
| if f.decodeConfig == nil { | |
| return Config{}, "", UnknownFormatErr | |
| } | |
| c, err := f.decodeConfig(rr) | |
| return c, f.name, err | |
| } |