-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreader.go
More file actions
93 lines (84 loc) · 2.81 KB
/
Copy pathreader.go
File metadata and controls
93 lines (84 loc) · 2.81 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
// Package tiff provides a memory-efficient, standards-compatible TIFF decoder for Go,
// with support for on-demand access to striped and tiled TIFF images.
//
// When working with supported TIFF formats, this decoder avoids loading the entire image
// into memory. Instead, it reads only the required pixel data on demand using io.ReaderAt.
//
// ⚠️ When a supported format is detected, the caller must keep the underlying reader
// (typically a file) open for as long as the image.Image is in use.
//
// If the format is unsupported, the decoder gracefully falls back to golang.org/x/image/tiff,
// in which case the full image is decoded eagerly and no special reader lifetime is required.
//
// Supported features in random access mode:
//
// - Striped and Tiled TIFF decoding
// - Compression: None, Deflate (zlib)
// - Photometric: RGB, BlackIsZero (grayscale)
// - PlanarConfig: Contig (interleaved samples only)
//
// Example usage:
//
// import (
// "image"
// _ "github.com/echoflaresat/tiff"
// )
//
// func main() {
// f, _ := os.Open("image.tif") // Must remain open when using the image
// defer f.Close()
//
// img, _, err := image.Decode(f)
// if err != nil {
// log.Fatal(err)
// }
//
// // Use img.At(x, y), img.Bounds(), etc.
// }
//
// For full details and source, visit: https://pkg.go.dev/github.com/echoflaresat/tiff
package tiff
import (
"image"
"io"
"github.com/echoflaresat/tiff/impl"
stdtiff "golang.org/x/image/tiff"
)
// DecodeConfig returns the color model and dimensions of a TIFF image without decoding the entire image.
// It uses the standard library's TIFF decoder for configuration extraction.
func DecodeConfig(r io.Reader) (image.Config, error) {
return stdtiff.DecodeConfig(r)
}
// Decode reads a TIFF image from r and returns it as an image.Image.
// It first attempts to decode using custom striped and tiled TIFF loaders,
// falling back to the standard library's TIFF decoder if those fail.
func Decode(r io.Reader) (image.Image, error) {
var readerAt io.ReaderAt
if ra, ok := r.(io.ReaderAt); ok {
readerAt = ra
} else if rs, ok := r.(io.ReadSeeker); ok {
readerAt = &readerAtFromSeeker{rs: rs}
}
if readerAt != nil {
if img, err := impl.LoadStripedTiff(readerAt); err == nil {
return img, nil
}
if img, err := impl.LoadTiledTiff(readerAt); err == nil {
return img, nil
}
}
// Fallback to standard decoder
return stdtiff.Decode(r)
}
// readerAtFromSeeker adapts an io.ReadSeeker to io.ReaderAt.
type readerAtFromSeeker struct {
rs io.ReadSeeker
}
// ReadAt implements the io.ReaderAt interface for readerAtFromSeeker.
// It seeks to the specified offset and reads into p.
func (r *readerAtFromSeeker) ReadAt(p []byte, off int64) (int, error) {
if _, err := r.rs.Seek(off, io.SeekStart); err != nil {
return 0, err
}
return r.rs.Read(p)
}