Return-Path: <awaresystems.be+caf_=filtered=awaresystems.be@gmail.com>
Delivered-To: filtered@awaresystems.be
Received: from mx-h.one.com (mx-h.one.com [91.198.169.55])
	by mail6.local (Postfix) with ESMTP id 1104F300207EC3
	for <filtered@awaresystems.be>; Fri,  6 Jun 2014 11:21:56 +0000 (UTC)
X-Virus-Scanned: by one.com
Received-SPF: pass (mx-h: domain of awaresystems.be+caf_=filtered=awaresystems.be@gmail.com designates 209.85.217.169 as permitted sender)
X-Greylist: whitelisted by SQLgrey-1.8.0-rc2
Received: from mail-lb0-f169.google.com (mail-lb0-f169.google.com [209.85.217.169])
	by mx-h.one.com (Postfix) with ESMTP id B170B839D6
	for <filtered@awaresystems.be>; Fri,  6 Jun 2014 11:21:55 +0000 (UTC)
Received: by mail-lb0-f169.google.com with SMTP id s7so1410610lbd.14
        for <filtered@awaresystems.be>; Fri, 06 Jun 2014 04:21:55 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-original-authentication-results:delivered-to:delivered-to:from:to
         :thread-topic:thread-index:date:message-id:references:in-reply-to
         :accept-language:content-language:content-id:mime-version:subject
         :precedence:list-id:list-unsubscribe:list-archive:list-post
         :list-help:list-subscribe:content-type:content-transfer-encoding
         :sender:errors-to;
        bh=urfP7h6AAd8ncGRKuSHgn4ZxHoedqBXePhxpyEiySGU=;
        b=irjikiyg+wQC2YRfae0nbJ/J6IMbt/29JgQhtZCppIS0P6LXEehrwIuFTXUrZCb7Ph
         CETKGoDbhThkJJYzVcu6sIFQGcasIJETsqEm+RfcAE/7ZiHtRCmcYsQZe4TLDI/ls3sM
         FdLKSUjiR4+beVV+gug9MWIj1fjepZVhIh0nlETM6hxyAYwLXQ+ExhT+h+TB6rqxffrh
         M5cbENQqruSV6CFIL3eAn40Rx+iw8l8F6hw2d0u0HbUVncdqJfcXRCN9BF4ik1TfDogj
         uE9RvTY19YyRqGu1TFEPlUSyOfmtE/hE8bg83iAS5QfHiVBIq/G+1QImK15PYp3AwPN8
         1e1Q==
X-Original-Authentication-Results: mx.google.com;       spf=neutral (google.com: tiff-bounces@lists.maptools.org does not designate permitted sender hosts) smtp.mail=tiff-bounces@lists.maptools.org
X-Received: by 10.152.19.195 with SMTP id h3mr3129428lae.47.1402053715405;
        Fri, 06 Jun 2014 04:21:55 -0700 (PDT)
X-Forwarded-To: filtered@awaresystems.be
X-Forwarded-For: awaresystems.be@gmail.com filtered@awaresystems.be
Delivered-To: awaresystems.be@gmail.com
Received: by 10.114.18.137 with SMTP id w9csp7515ldd;
        Fri, 6 Jun 2014 04:21:54 -0700 (PDT)
X-Received: by 10.152.5.135 with SMTP id s7mr1662705las.55.1402053710455;
        Fri, 06 Jun 2014 04:21:50 -0700 (PDT)
Authentication-Results: mx.google.com;
       spf=neutral (google.com: tiff-bounces@lists.maptools.org does not designate permitted sender hosts) smtp.mail=tiff-bounces@lists.maptools.org
Received-SPF: none (google.com: tiff-bounces@lists.maptools.org does not designate permitted sender hosts) client-ip=195.47.247.73;
Received: by 10.152.47.72 with POP3 id b8mf1257756lan.8;
        Fri, 06 Jun 2014 04:21:50 -0700 (PDT)
X-Gmail-Fetch-Info: info@awaresystems.be 1 pop.awaresystems.be 110 info@awaresystems.be
Delivered-To: info@awaresystems.be
Received: from mx02.one.com (mx02.one.com [195.47.247.73])
	by mail6.local (Postfix) with ESMTP id CDFA5300207EC3
	for <info@awaresystems.be>; Fri,  6 Jun 2014 11:12:49 +0000 (UTC)
X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0-rc2
Received: from lists.maptools.org (ks365428.kimsufi.com [94.23.4.142])
	by mx02.one.com (Postfix) with ESMTP id 929B91431B3D
	for <info@awaresystems.be>; Fri,  6 Jun 2014 11:12:49 +0000 (UTC)
Received: from [10.1.0.241] (localhost.localdomain [127.0.0.1])
	by lists.maptools.org (Postfix) with ESMTP id DC61135C033;
	Fri,  6 Jun 2014 06:12:05 -0500 (EST)
Received: from emea01-db3-obe.outbound.protection.outlook.com
	(mail-db3lp0084.outbound.protection.outlook.com [213.199.154.84])
	by lists.maptools.org (Postfix) with ESMTPS id B2B6F35C033
	for <tiff@lists.maptools.org>; Fri,  6 Jun 2014 06:11:29 -0500 (EST)
Received: from DB3PR06MB092.eurprd06.prod.outlook.com (10.141.1.27) by
	DB3PR06MB092.eurprd06.prod.outlook.com (10.141.1.27) with Microsoft
	SMTP Server (TLS) id 15.0.954.9; Fri, 6 Jun 2014 11:11:29 +0000
Received: from DB3PR06MB092.eurprd06.prod.outlook.com ([169.254.4.25]) by
	DB3PR06MB092.eurprd06.prod.outlook.com ([169.254.4.25]) with mapi id
	15.00.0954.000; Fri, 6 Jun 2014 11:11:29 +0000
From: Stephen Morris <s-morris@n-eos.com>
To: "tiff@lists.maptools.org" <tiff@lists.maptools.org>
Thread-Topic: [Tiff] What's wrong with my code for adding custom tags to a file
Thread-Index: AQHPgLG4n3B3tVLDTkqfNRJXO5POWptiqg4AgAFVbwA=
Date: Fri, 6 Jun 2014 11:11:28 +0000
Message-ID: <CFB75D41.1A522%s-morris@n-eos.com>
References: <CFB6138E.1A4BC%stephen@morris.net>
	<413F4632-74AC-4FB4-AEA7-D1A82DA31FB7@cs.cmu.edu>
In-Reply-To: <413F4632-74AC-4FB4-AEA7-D1A82DA31FB7@cs.cmu.edu>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
x-originating-ip: [81.139.73.159]
x-microsoft-antispam: BL:0; ACTION:Default; RISK:Low; SCL:0; SPMLVL:NotSpam;
	PCL:0; RULEID:
x-forefront-prvs: 023495660C
x-forefront-antispam-report: SFV:NSPM;
	SFS:(6009001)(428001)(243025005)(189002)(199002)(77982001)(31966008)(74662001)(46102001)(15202345003)(81342001)(101416001)(20776003)(99396002)(50986999)(76176999)(54356999)(4396001)(79102001)(92566001)(64706001)(86362001)(92726001)(85852003)(83072002)(21056001)(66066001)(83322001)(19580395003)(19580405001)(81542001)(87936001)(36756003)(2656002)(19273905006)(15975445006)(19300405004)(562404015)(563064011);
	DIR:OUT; SFP:; SCL:1; SRVR:DB3PR06MB092;
	H:DB3PR06MB092.eurprd06.prod.outlook.com; FPR:; MLV:sfv;
	PTR:InfoNoRecords; MX:1; A:1; LANG:en; 
received-spf: None (: n-eos.com does not designate permitted sender hosts)
authentication-results: spf=none (sender IP is )
	smtp.mailfrom=s-morris@n-eos.com; 
Content-ID: <0823205272279F4C803BCA4101D38B57@eurprd06.prod.outlook.com>
MIME-Version: 1.0
X-OriginatorOrg: n-eos.com
Subject: Re: [Tiff] What's wrong with my code for adding custom tags to a
	file
X-BeenThere: tiff@lists.maptools.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: TIFF and libtiff discussion <tiff.lists.maptools.org>
List-Unsubscribe: <http://lists.maptools.org/mailman/listinfo/tiff>,
	<mailto:tiff-request@lists.maptools.org?subject=unsubscribe>
List-Archive: <http://lists.maptools.org/mailman/private/tiff>
List-Post: <mailto:tiff@lists.maptools.org>
List-Help: <mailto:tiff-request@lists.maptools.org?subject=help>
List-Subscribe: <http://lists.maptools.org/mailman/listinfo/tiff>,
	<mailto:tiff-request@lists.maptools.org?subject=subscribe>
Content-Type: text/plain; charset="windows-1252"
Content-Transfer-Encoding: quoted-printable
Sender: tiff-bounces@lists.maptools.org
Errors-To: tiff-bounces@lists.maptools.org

Thank you Paul. I incorporated the TiffSetTagExtender call in the way that
you showed (which helped me a lot to make sense of the documentation) to
produce the code shown below. Sure enough, the access violation has gone
away but I still don=B9t get the custom tags in the file. As the routine
runs, I get error messages in my console to the effect of:

TIFFSetField: TestImage.tif: Unknown tag 65000.
TIFFSetField: TestImage.tif: Unknown tag 65001.
TIFFSetField: TestImage.tif: Unknown tag 65002.
TIFFSetField: TestImage.tif: Unknown tag 65003.
TIFFSetField: TestImage.tif: Unknown tag 65004.
TIFFSetField: TestImage.tif: Unknown tag 65005.

=8Aso there=B9s obviously something that I=B9m still missing. Here=B9s my n=
ew code:

#include "stdafx.h"
#include "PGM.h"
#include "tiffio.h"

// There are a number of TIFF-related definitions we need to make in order
to support the custom tags
// that we want to include in our files. The form of these definitions and
subroutines comes straight
// out of the libtiff documentation, and the values of the custom tags
themselves come from the
// range (65000-75535) defined in the TIFF specification as "reusable" and
suitable for private use
// within organisations. See
http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
#define N(a) (sizeof(a) / sizeof (a[0]))
#define TIFFTAG_INCIDENTPOWER     65000
#define TIFFTAG_REFLECTEDPOWER    65001
#define TIFFTAG_T1                65002
#define TIFFTAG_T2                65003
#define TIFFTAG_HUMIDITY          65004
#define TIFFTAG_EXPOSURE          65005

static const TIFFFieldInfo xtiffFieldInfo[] =3D {
        { TIFFTAG_INCIDENTPOWER,  -1, -1, TIFF_LONG,  FIELD_CUSTOM, 0, 1,
const_cast<char*>("LaserIncidentPower") },
        { TIFFTAG_REFLECTEDPOWER, -1, -1, TIFF_LONG,  FIELD_CUSTOM, 0, 1,
const_cast<char*>("LaserReflectedPower") },
        { TIFFTAG_T1,             -1, -1, TIFF_FLOAT, FIELD_CUSTOM, 0, 1,
const_cast<char*>("Temperature_1") },
        { TIFFTAG_T2,             -1, -1, TIFF_FLOAT, FIELD_CUSTOM, 0, 1,
const_cast<char*>("Temperature_2") },
        { TIFFTAG_HUMIDITY,       -1, -1, TIFF_FLOAT, FIELD_CUSTOM, 0, 1,
const_cast<char*>("Humidity") },
        { TIFFTAG_EXPOSURE,       -1, -1, TIFF_FLOAT, FIELD_CUSTOM, 0, 1,
const_cast<char*>("ExposureTime(ms)") }
};									  // The casts are necessary because the
                   =

// string literals are inherently const,
                   =

// but the definition of TIFFFieldInfo
                   =

// requires a non-const string pointer.
                   =

// The Intel and Microsoft compilers
                   =

// tolerate this, but gcc doesn't.

static TIFFExtendProc parent_extender =3D NULL;  // In case we want a chain
of extensions

static void registerCustomTIFFTags(TIFF *tif)
{
    /* Install the extended Tag field info */
    TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));

    if (parent_extender)
        (*parent_extender)(tif);
}

static void augment_libtiff_with_custom_tags() {
    static bool first_time =3D true;
    if (!first_time) return;
    first_time =3D false;
    parent_extender =3D TIFFSetTagExtender(registerCustomTIFFTags);
}

void saveAsTiff(int nx, int ny, unsigned short *image, const char*
filename,
                int Power1, int Power2, float T1, float T2, float
Humidity, float Exposure)
{
    // Create the TIFF directory object:
    TIFF* tif =3D TIFFOpen(filename, "w");

    // Prepare for writing the custom tags:
    augment_libtiff_with_custom_tags();

    // Set the tags: first the standard ones...
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, nx);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, ny);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
    TIFFSetField(tif, TIFFTAG_ZIPQUALITY, 6); // Takes maximum advantage
of Intel ZLIB enhancements
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
    TIFFSetField(tif, TIFFTAG_ORIENTATION,
static_cast<int>(ORIENTATION_TOPLEFT));
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, ny);
    // Saving the whole image in a single block makes heavy
    // demands on memory but should enable optimum compression
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);

    // ... and now our own custom ones:
    TIFFSetField(tif, TIFFTAG_INCIDENTPOWER, Power1);
    TIFFSetField(tif, TIFFTAG_REFLECTEDPOWER, Power2);
    TIFFSetField(tif, TIFFTAG_T1, T1);
    TIFFSetField(tif, TIFFTAG_T2, T2);
    TIFFSetField(tif, TIFFTAG_HUMIDITY, Humidity);
    TIFFSetField(tif, TIFFTAG_EXPOSURE, Exposure);

    TIFFWriteEncodedStrip(tif, 0, static_cast<void *>(image), nx * ny *
2); =

                                                              // The '* 2'
is present because each pixel
                                                              // has 16
bits, hence two bytes
    // Write the directory to a file, and close it:
    TIFFWriteDirectory(tif);
    TIFFClose(tif);
}

int _tmain(int argc, _TCHAR* argv[])
{
    // Variables to hold the image
    int nx, ny;
    unsigned short *image =3D nullptr;

    // Information we'd like to put into our custom tags:
    int Power1 =3D 1000000;
    int Power2 =3D 8;
    float T1 =3D 23.5f;
    float T2 =3D -18.7f;
    float Humidity =3D 0.98f;
    float Exposure =3D 0.001f;

    // Read the test image in from a PGM file:
    readFromPGM(&nx, &ny, &image, "TestImage.pgm");

    // Save the image as a TIF file:
    saveAsTiff(nx, ny, image, "TestImage.tif", Power1, Power2, T1, T2,
Humidity, Exposure);

    return 0;
}



From:  Paul Heckbert <ph@cs.cmu.edu>
Date:  Thursday, 5 June 2014 16:49
To:  Stephen Morris <s-morris@n-eos.com>
Cc:  Paul Heckbert <ph@cs.cmu.edu>, "tiff@lists.maptools.org"
<tiff@lists.maptools.org>
Subject:  Re: [Tiff] What's wrong with my code for adding custom tags to a
file


I think you need to call TIFFSetTagExtender(). I agree that the libtiff
documentation leaves a lot to be desired.

I slogged through a similar debugging challenge a few months ago, when I
needed to read TIFFs in the =B3DNG=B2 dialect that used exotic tags unknown=
 to
libtiff. Here=B9s an excerpt of the code I came up with. This works
(compiling with g++ on mac or linux).
 Note the call to TIFFSetTagExtender(). I=B9m not including my DNG.h because
I don=B9t think that=B9s relevant to you. Don=B9t worry too much about the
SUBIFD0 stuff; that=B9s a DNG convention.

#include <tiffio.h>

#include "DNG.h"

/////////////////////////////////////////////////////////////////// DNG
tag grunge

/*
to get rid of warning messages from libtiff on stdout that look like the
following,
coming when we read files containing DNG tags:
  TIFFReadDirectory: Warning, Unknown field with tag 33421 (0x828d)
encountered.
  TIFFReadDirectory: Warning, Unknown field with tag 33422 (0x828e)
encountered.

we follow these instructions
  http://www.remotesensing.org/libtiff/addingtags.html
*/

#define DNG_TAG_CFARepeatPatternDim 0x828d
#define DNG_TAG_CFAPattern2 0x828e
staticchar CFARepeatPatternDimName[] =3D
"CFARepeatPatternDim";
staticchar CFAPattern2Name[] =3D
"CFAPattern2";

staticconst TIFFFieldInfo dng_field_info[] =3D {
  // tag, readcount, writecount, field_type, field_bit, ok_to_change,
passcount, field_name
  // note: if pass_count=3D1 then TIFFGetField should be passed a ptr to a
uint16 count
  { DNG_TAG_CFARepeatPatternDim,
2,             2,             TIFF_SHORT, FIELD_CUSTOM,
    =

1, 0, CFARepeatPatternDimName },
  { DNG_TAG_CFAPattern2,         TIFF_VARIABLE, TIFF_VARIABLE, TIFF_BYTE,
FIELD_CUSTOM,
    =

1, 1, CFAPattern2Name }
};

static TIFFExtendProc parent_extender =3D
NULL;  =

// in case we want a chain of extensions

// Extender callback.
// It merges in our new fields and then calls the next extender if there
is one in effect.

staticvoid dng_extender_callback(TIFF *tif) {
  // install tag field extensions for DNG
  TIFFMergeFieldInfo(tif, dng_field_info,
sizeof dng_field_info /
sizeof dng_field_info[0]);

  // call default directory method, if any
  =

if (parent_extender)
    (*parent_extender)(tif);
}

staticvoid augment_libtiff_with_dng_tags() {
  =

static bool first_time =3D
true;
  =

if (!first_time) return;
  first_time =3D =

false;
  parent_extender =3D TIFFSetTagExtender(dng_extender_callback);
}

///////////////////////////////////////////////////////////////////

static =

void print_dir(TIFF *tif) {
  TIFFPrintDirectory(tif, stdout, TIFFPRINT_NONE);  // PRINT_NONE means
print no extra info
  =

int filetype, nx, ny;
  uint16 samples_per_pixel, bits_per_sample;
  assert(TIFFGetField(tif, TIFFTAG_SUBFILETYPE, &filetype));
  assert(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &nx));
  assert(TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &ny));
  assert(TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel));
  assert(TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits_per_sample));
  printf("DNG::DNG IFD with filetype=3D%d%dx%d samples_per_pixel=3D%d
bits_per_sample=3D%d\n",
      filetype, nx, ny, samples_per_pixel, bits_per_sample);
}

DNG::DNG(const std::string &filename,
bool verbose)
  : PicFile<PixelI8>(filename),
    m_tif(TIFFOpen(filename.c_str(),
"r")) {
  =

if (m_tif =3D=3D NULL) =

return;  // can't open file
  // to suppress warnings about unknown tags, inform libtiff about several
DNG tags
  augment_libtiff_with_dng_tags();

  // read SUBIFD0, which contains the full resolution image
  int16 sub_ifd_count;
  uint64 *offset =3D
0;
  assert(TIFFGetField(m_tif, TIFFTAG_SUBIFD, &sub_ifd_count, &offset));
  // printf("GetField SUBIFD count=3D%d offset=3D0x%px offset[0]=3D0x%llx
offset[1]=3D0x%llx\n",
      // sub_ifd_count, offset, (long long)offset[0], (long
long)offset[1]);
  assert(sub_ifd_count>=3D1 && sub_ifd_count<=3D2);
// expect at least 1 and not more than 2 sub-IFDs
  assert(TIFFSetSubDirectory(m_tif, offset[0]));
  print_dir(m_tif);

  =

int filetype;
  assert(TIFFGetField(m_tif, TIFFTAG_SUBFILETYPE, &filetype));
  assert(TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &m_nx));
  assert(TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &m_ny));
  =

if (verbose)
    printf("DNG::DNG
%s %dx%d\n", filename.c_str(), m_nx, m_ny);
  // expect this subIFD to contain the full size image, 1 channel (bayer
pattern), 8 bits per pixel
  assert(filetype=3D=3DFILETYPE_FULLSIZEIMAGE);
  uint16 samples_per_pixel, bits_per_sample;
  assert(TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel));
  assert(TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bits_per_sample));
  assert(samples_per_pixel=3D=3D1);
  assert(bits_per_sample=3D=3D8);

  // check assumptions that the code makes about the Bayer pattern
  uint16 *dim;
  assert(TIFFGetField(m_tif, DNG_TAG_CFARepeatPatternDim, &dim));
  assert(dim[0]=3D=3D2 && dim[1]=3D=3D2);
// Bayer pattern is 2x2 pixels
  uint16 count;
  uint8 *pattern;
  assert(TIFFGetField(m_tif, DNG_TAG_CFAPattern2, &count, &pattern));
  // printf("CFAPattern2: count=3D%d pattern=3D%d,%d,%d,%d\n",
      // count, pattern[0], pattern[1], pattern[2], pattern[3]);
  assert(count=3D=3Ddim[0]*dim[1]);
  assert(pattern[0]=3D=3D1 && pattern[1]=3D=3D0 && pattern[2]=3D=3D2
 && pattern[3]=3D=3D1);
// GR,BG

    ...


_______________________________________________
Tiff mailing list: Tiff@lists.maptools.org
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/
