// 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 }