-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdecode.go
More file actions
97 lines (87 loc) · 2.33 KB
/
decode.go
File metadata and controls
97 lines (87 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package xtx
import (
"fmt"
"image"
"io"
)
func init() {
// Register XTG format: magic bytes "XTG\0" at offset 0.
image.RegisterFormat("xtg",
"XTG\x00", // magic string (XTG\0 in little-endian starts with 'X','T','G',0)
func(r io.Reader) (image.Image, error) { return Decode(r) },
func(r io.Reader) (image.Config, error) { return DecodeConfig(r) },
)
// Register XTH format: magic bytes "XTH\0" at offset 0.
image.RegisterFormat("xth",
"XTH\x00",
func(r io.Reader) (image.Image, error) { return Decode(r) },
func(r io.Reader) (image.Config, error) { return DecodeConfig(r) },
)
}
// Decode reads an XTG or XTH image from r, auto-detecting the format from
// the magic bytes in the header.
func Decode(r io.Reader) (image.Image, error) {
var h Header
if _, err := h.ReadFrom(r); err != nil {
return nil, err
}
if err := h.Validate(); err != nil {
return nil, err
}
data := make([]byte, h.DataSize)
if _, err := io.ReadFull(r, data); err != nil {
return nil, fmt.Errorf("xtx: reading image data: %w", err)
}
switch h.Mark {
case MagicXTG:
return decodeMono(&h, data), nil
case MagicXTH:
return decodeGray(&h, data), nil
default:
return nil, ErrInvalidMagic
}
}
// DecodeConfig returns the image dimensions and color model without reading
// the pixel data.
func DecodeConfig(r io.Reader) (image.Config, error) {
var h Header
if _, err := h.ReadFrom(r); err != nil {
return image.Config{}, err
}
var model image.Config
model.Width = int(h.Width)
model.Height = int(h.Height)
switch h.Mark {
case MagicXTG:
model.ColorModel = MonoModel
case MagicXTH:
model.ColorModel = Gray4Model
default:
return image.Config{}, ErrInvalidMagic
}
return model, nil
}
// decodeMono constructs a Monochrome image from the header and raw pixel data.
func decodeMono(h *Header, data []byte) *Monochrome {
w, ht := int(h.Width), int(h.Height)
stride := (w + 7) / 8
img := &Monochrome{
Pix: data,
Stride: stride,
Rect: image.Rect(0, 0, w, ht),
}
return img
}
// decodeGray constructs a Grayscale image from the header and raw pixel data.
func decodeGray(h *Header, data []byte) *Grayscale {
w, ht := int(h.Width), int(h.Height)
colBytes := (ht + 7) / 8
planeSize := w * colBytes
img := &Grayscale{
Pix: data,
Rect: image.Rect(0, 0, w, ht),
PlaneSize: planeSize,
ColBytes: colBytes,
}
return img
}