b71a28d3c0
support new types for import * tests pass * missing file * bug fixes
127 lines
2.5 KiB
Go
127 lines
2.5 KiB
Go
// Copyright 2011 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package tiff
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"io"
|
|
)
|
|
|
|
type Reader struct {
|
|
Reader io.ReadSeeker
|
|
Header *Header
|
|
Ifd [][]*IFD
|
|
|
|
rs *seekioReader
|
|
}
|
|
|
|
func OpenReader(r io.Reader) (p *Reader, err error) {
|
|
rs := openSeekioReader(r, -1)
|
|
defer func() {
|
|
if err != nil && rs != nil {
|
|
rs.Close()
|
|
}
|
|
}()
|
|
|
|
p = &Reader{}
|
|
if p.Header, err = ReadHeader(rs); err != nil {
|
|
return
|
|
}
|
|
if !p.Header.Valid() {
|
|
err = fmt.Errorf("tiff: OpenReader, invalid header: %v", p.Header)
|
|
return
|
|
}
|
|
|
|
for offset := p.Header.FirstIFD; offset != 0; {
|
|
var ifd *IFD
|
|
var ifdList []*IFD
|
|
|
|
if ifd, err = ReadIFD(rs, p.Header, offset); err != nil {
|
|
return
|
|
}
|
|
ifdList = append(ifdList, ifd)
|
|
offset = ifd.NextIFD
|
|
|
|
subIfdOffsets, _ := ifd.TagGetter().GetSubIFD()
|
|
for _, subOffset := range subIfdOffsets {
|
|
ifd, _ = ReadIFD(rs, p.Header, subOffset)
|
|
ifdList = append(ifdList, ifd)
|
|
}
|
|
p.Ifd = append(p.Ifd, ifdList)
|
|
}
|
|
|
|
p.Reader = rs
|
|
p.rs = rs
|
|
return
|
|
}
|
|
|
|
func (p *Reader) ImageNum() int {
|
|
return len(p.Ifd)
|
|
}
|
|
func (p *Reader) SubImageNum(i int) int {
|
|
return len(p.Ifd[i])
|
|
}
|
|
|
|
func (p *Reader) ImageConfig(i, j int) (image.Config, error) {
|
|
return p.Ifd[i][j].ImageConfig()
|
|
}
|
|
|
|
func (p *Reader) ImageBlocksAcross(i, j int) int {
|
|
return p.Ifd[i][j].BlocksAcross()
|
|
}
|
|
|
|
func (p *Reader) ImageBlocksDown(i, j int) int {
|
|
return p.Ifd[i][j].BlocksDown()
|
|
}
|
|
|
|
func (p *Reader) ImageBlockBounds(i, j, col, row int) image.Rectangle {
|
|
return p.Ifd[i][j].BlockBounds(col, row)
|
|
}
|
|
|
|
func (p *Reader) DecodeImage(i, j int) (m image.Image, err error) {
|
|
cfg, err := p.ImageConfig(i, j)
|
|
if err != nil {
|
|
return
|
|
}
|
|
imgRect := image.Rect(0, 0, cfg.Width, cfg.Height)
|
|
if m, err = newImageWithIFD(imgRect, p.Ifd[i][j]); err != nil {
|
|
return
|
|
}
|
|
|
|
blocksAcross := p.ImageBlocksAcross(i, j)
|
|
blocksDown := p.ImageBlocksDown(i, j)
|
|
|
|
for col := 0; col < blocksAcross; col++ {
|
|
for row := 0; row < blocksDown; row++ {
|
|
if err = p.Ifd[i][j].DecodeBlock(p.rs, col, row, m); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (p *Reader) DecodeImageBlock(i, j, col, row int) (m image.Image, err error) {
|
|
r := p.ImageBlockBounds(i, j, col, row)
|
|
if m, err = newImageWithIFD(r, p.Ifd[i][j]); err != nil {
|
|
return
|
|
}
|
|
if err = p.Ifd[i][j].DecodeBlock(p.rs, col, row, m); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (p *Reader) Close() (err error) {
|
|
if p != nil {
|
|
if p.rs != nil {
|
|
err = p.rs.Close()
|
|
}
|
|
*p = Reader{}
|
|
}
|
|
return
|
|
}
|