How to read multi-page TIFF image?

1,163 views
Skip to first unread message

Tad Vizbaras

unread,
Sep 22, 2017, 1:49:47 PM9/22/17
to golang-nuts
No problem reading single page TIFF images using: "golang.org/x/image/tiff".
It works great.

Question: how to read multi-page scanned TIFFs? How to access pages 2, 3, etc.?

Guy Allard

unread,
Sep 24, 2017, 9:20:31 AM9/24/17
to golang-nuts
This package does not appear to support multi-page TIFs.  Decoder initialization only reads the 1st IFD.

Tad Vizbaras

unread,
Sep 24, 2017, 2:21:39 PM9/24/17
to golang-nuts
Sad.

Any chance to add multi page support to this? I am in desperate need for multi-page TIFF support.

Andrew O'Neill

unread,
Sep 24, 2017, 2:48:50 PM9/24/17
to Tad Vizbaras, golang-nuts
A while ago I reading Adobe's doc's on SubIFD's since that is needed for decoding Nikon's RAW files. Is this a similar thing or is it just reading all the IFD's? I plan to implement a SubIFD decoder for tiff, unless someone else has done it.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tad Vizbaras

unread,
Sep 25, 2017, 7:10:40 AM9/25/17
to golang-nuts
If you implement decoder I can provide sample multi-page TIFF files to see if it is working.

Jonathan Pittman

unread,
Sep 25, 2017, 9:40:25 AM9/25/17
to golang-nuts
Wether a multi-page TIFF uses multiple IFDs or uses one IFD with multiple SubIFDs is implementation dependent.  Though, I think most probably just use multiple IFDs.  The basic structure of an IFD and a SubIFD is essentially the same.  The main difference is where you find their offsets and the offset for the next IFD.  If you want to just grab all of the regular IFDs, that is pretty easy to do.  The "next offset" to the next IFD is at the end of the IFD's structure.  You just go to that next offset and then process the IFD just like you did the first one.  Grabbing SubIFDs requires you to look for the SubIFD tag (330 or 0x014a) inside an IFD and process the value field into a list of offsets values as a []uint32.  There could be one or more offsets.  Keep in mind that with SubIFDs, while the tag ID, its purpose, and format are documented and not intended to be changed, some manufacturers will ignore this and reuse the field for something else.  Sony did this on at least one camera model that I know of.  Most uses I have seen adhere to the original purpose though.

If you want to see some (unfortunately) undocumented and very incomplete code for processing the basic data structures of a tiff (i.e. getting IFDs and SubIFDs, but not going as far as processing the actual image data), I posted some code here github.com/google/tiff.  The godoc page is more useful I think.  I started on this code a while back, but have not had time to revisit it in depth in a while.

Andrew, which camera makes and models do you shoot with?  I have a Nikon D200 and a D800.  I started working on model specific data structures for multiple camera models at https://godoc.org/github.com/google/cameraraw.  I actually have code to generate those go files based on a TIFF/DNG/RAW file.  It is just not checked in anywhere.

Andrew O'Neill

unread,
Sep 25, 2017, 11:37:01 AM9/25/17
to golang-nuts
I'm currently travelling with a Nikon D750. From what I can tell the raw images use a single IFD with 2 SubIFDs the main one being the embedded jpeg for the thumbnail and the second being the raw image data. If you have something to parse the raw image data that would be awesome. I've been testing some different storage solutions (upspin, camlistore) and wanted to build something that would watch for newly added RAW images and create jpeg thumbnails, and various sizes for sharing via blog, twitter, whatever.

Guy Allard

unread,
Sep 25, 2017, 11:55:50 AM9/25/17
to golang-nuts
The multi-page TIFs I have seen have multiple IFDs (a linked list).  I do not know anything about SubIFds, have never seen such.

Adding support for multiple IFDs to the go package being discussed seems not too difficult (reading the existing code).

Suggest trying to contact the package authors.

Jonathan Pittman

unread,
Sep 25, 2017, 12:14:05 PM9/25/17
to Andrew O'Neill, golang-nuts
We have some ideas in common for sure (i.e. storing with upsin/camlistore and grabbing the embedded previews for display).  Though, my needs go much further (i.e. being able to process my raw images with Go).  I stick every RAW image from my D800 in Google Cloud Storage with the plan to eventually do something like that.  We should discuss this separately at some point.

The biggest issue with the multipage TIFF support being added to the current tiff package is that the intent was to only support the base requirements (the first IFD and only the base and some extended tags).  It might not be a lot of code or trouble to support processing additional IFDs, but I want to caution against supporting much more than that without rethinking the API and scope of the package.  The TIFF data structures are pretty simple, but what you do with the data and how you process the data in them can get complicated when you start adding support for more tags and devices.  It is something I really want to see though.

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/-FH2y0iGHLI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts+unsubscribe@googlegroups.com.

Nigel Tao

unread,
Sep 27, 2017, 8:04:32 PM9/27/17
to Guy Allard, golang-nuts
On Tue, Sep 26, 2017 at 1:55 AM, Guy Allard <allard...@gmail.com> wrote:
> Adding support for multiple IFDs to the go package being discussed seems not
> too difficult (reading the existing code).
>
> Suggest trying to contact the package authors.

Hi, I'm one of the authors of the golang.org/x/image/tiff package.

Lack of multi-page TIFF support is indeed a bug.

As Jonathan Pittman already said, though, doing it well might first
require some thinking about the API.
https://github.com/golang/go/issues/8055 is a related issue. It would
be nice if the GIF and TIFF packages had some sort of common API for
multi-frame images, with one eye on possible video APIs, but that's a
lot of thinking.

Speaking only for myself, I don't have much free time in the short
term to do that thinking, or otherwise work on multi-page TIFF.

Michael Jones

unread,
Sep 27, 2017, 8:29:20 PM9/27/17
to Nigel Tao, Guy Allard, golang-nuts
Not quite related, but if changes are going to happen, I want to add (or see someone add) colorspace tags to the PNG code and the TIFF code. I need it and have a work-around, but I don't know how Nigel et-al think it should be presented through the api. I'm happy to supply the work / tags / etc. (the standard tags -- the normal case -- allow specification of the rgb space and the gamma value used for encoding.)

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Michael T. Jones
michae...@gmail.com

Nigel Tao

unread,
Sep 28, 2017, 2:02:02 AM9/28/17
to Michael Jones, Guy Allard, golang-nuts
On Thu, Sep 28, 2017 at 10:28 AM, Michael Jones <michae...@gmail.com> wrote:
> Not quite related, but if changes are going to happen, I want to add (or see
> someone add) colorspace tags to the PNG code and the TIFF code.

It's not exactly what you're asking for, but there are already issues
https://github.com/golang/go/issues/11420 "x/image/draw: color
space-correct interpolation" and
https://github.com/golang/go/issues/20613 "image/png: don't ignore PNG
gAMA chunk". There might be other issues filed, I didn't do an
exhaustive search.

Michael Jones

unread,
Sep 28, 2017, 10:39:19 AM9/28/17
to Nigel Tao, Guy Allard, golang-nuts
thanks, i'll make notes there

Michael Jones

unread,
Oct 3, 2017, 7:10:13 PM10/3/17
to Nigel Tao, Guy Allard, golang-nuts
Nigel, I added the sRGB, cHRM, and gAMA chunks, extended the Encoder structure, and use it like this in my own code:

case ".jpg":
err = jpeg.Encode(file, p, &jpeg.Options{
Quality: 95,
})
if err != nil {
log.Fatal(err)
}
case ".png":
// err = png.Encode(file, p) // colorspace and gamma unspecified
err = (&png.Encoder{IsSRGB: true, RenderingIntent: png.Perceptual}).Encode(file, p)
if err != nil {
log.Fatal(err)
}
case ".tiff":
// err = tiff.Encode(file, p, nil) // uncompressed
err = tiff.Encode(file, p, &tiff.Options{
Compression: tiff.Deflate,
Predictor:   true,
})
if err != nil {
log.Fatal(err)
}

I updated https://github.com/golang/go/issues/20613 about the details.
Reply all
Reply to author
Forward
0 new messages