OSDN Git Service

libgo: Update to weekly.2011-11-02.
[pf3gnuchains/gcc-fork.git] / libgo / go / 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 // An UnknownFormatErr indicates that decoding encountered an unknown format.
14 var UnknownFormatErr = 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, "", UnknownFormatErr
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{}, "", UnknownFormatErr
97         }
98         c, err := f.decodeConfig(rr)
99         return c, f.name, err
100 }