format.go 2.8 KB

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