Home | History | Annotate | Download | only in image
      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 reports 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 an init function in 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 // an init function in 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 }
    101