/*
 * Copyright (c) 2012, Frank Warmerdam <warmerdam@pobox.com>
 *
 * Permission to use, copy, modify, distribute, and sell this software and
 * its documentation for any purpose is hereby granted without fee, provided
 * that (i) the above copyright notices and this permission notice appear in
 * all copies of the software and related documentation, and (ii) the names of
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
 * publicity relating to the software without the specific, prior written
 * permission of Sam Leffler and Silicon Graphics.
 *
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THIS SOFTWARE.
 */

/*
 * TIFF Library
 *
 * -- Module copied from custom_dir.c --
 *===========  Purpose
 *===================================================================================
 * Extended and amended version for testing of EXIF 2.32, GPS and handling of
 *custom fields. EXIF 2.32 and GPS are defined in amended files tif_dirinfo.c,
 *tif_dirread.c, tiff.h, tiffio.h, tif_dir.h, tif_dir.c
 *
 *-- ATTENTION: After the upgrade with Rational2Double, the GPSTAG values are
 *defined as double precision and need to be written and also read in double
 *precision! In order to maintain this code for both cases, it is checked above
 *if the TiffLibrary is compiled with the new interface with Rational2Double or
 *still uses the old definitions, by setting blnIsRational2Double above.
 *
 */

/*------------
 * This version writes the GPS and EXIF tags correctly, without additional
 main-IFD and parameters!
 * In contrary, custom_dir.c does write additional main-IFD and parameters to
 file.
 -------------*/

#define FOR_AUTO_TESTING
#ifdef FOR_AUTO_TESTING
/*  Only for automake and CMake infrastructure the test should:
        a.) delete any written testfiles when test passed (otherwise autotest
   will fail) b.) goto failure, if any failure is detected, which is not
   necessary when test is initiated manually for debugging
*/
#define GOTOFAILURE goto failure;
#define GOTOFAILURE_GPS goto failure;
#define GOTOFAILURE_ALL_EXIF goto failure;
#else
#define GOTOFAILURE
#define GOTOFAILURE_GPS
#define GOTOFAILURE_ALL_EXIF
#endif

#ifdef _MSC_VER
#pragma warning(disable : 4101)
#endif

#include "tif_config.h" //necessary for linux compiler

#include <errno.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include "tiffio.h"
#include "tiffiop.h"

int write_test_tiff(TIFF *tif, const char *filenameRead);

static const char filename[] = "custom_dir_EXIF_231.tif";
static const char filenameBigTiff[] = "custom_dir_EXIF_231_Big.tif";

#define SPP 3 /* Samples per pixel */
const uint16_t width = 1;
const uint16_t length = 1;
const uint16_t bps = 8;
const uint16_t photometric = PHOTOMETRIC_RGB;
const uint16_t rows_per_strip = 1;
const uint16_t planarconfig = PLANARCONFIG_CONTIG;

int main()
{
    TIFF *tif;
    int ret, ret1, ret2;

    fprintf(stderr, "==== Test automatically if all EXIF and GPS tags are "
                    "written/read correctly. ====\n");
    /* --- Test with Classic-TIFF ---*/
    /* delete file, if exists */
    ret = unlink(filename);
    if (ret != 0 && errno != ENOENT)
    {
        fprintf(stderr, "Can't delete test TIFF file %s.\n", filename);
    }

    /* We write the main directory as a simple image. */
    tif = TIFFOpen(filename, "w+");
    if (!tif)
    {
        fprintf(stderr, "Can't create test TIFF file %s.\n", filename);
        return 1;
    }
    fprintf(stderr, "-------- Test with ClassicTIFF started  ----------\n");
    ret1 = write_test_tiff(tif, filename);

    if (ret1 > 0)
        return (ret1);

    /*--- Test with BIG-TIFF ---*/
    /* delete file, if exists */
    ret = unlink(filenameBigTiff);
    if (ret != 0 && errno != ENOENT)
    {
        fprintf(stderr, "Can't delete test TIFF file %s.\n", filenameBigTiff);
    }

    tif = TIFFOpen(filenameBigTiff, "w8");
    if (!tif)
    {
        fprintf(stderr, "Can't create test TIFF file %s.\n", filenameBigTiff);
        return 1;
    }
    fprintf(stderr, "\n\n-------- Test with BigTIFF started  ----------\n");
    ret2 = write_test_tiff(tif, filenameBigTiff);

    if (ret2 > 0)
        return (ret2 + 10);
    else
        return (ret2);

} /* main() */

int write_test_tiff(TIFF *tif, const char *filenameRead)
{
    unsigned char buf[SPP] = {0, 127, 255};
    uint64_t dir_offset = 0;
    uint64_t dir_offset_GPS = 0, dir_offset_EXIF = 0;
    uint64_t read_dir_offset = 0;
    /*-- Additional variables --*/
    int retCode, retCode2;
    unsigned char exifVersion[4] = {
        '0', '2', '3',
        '1'}; /* EXIF 2.31 version is 4 characters of a string! */
    unsigned char gpsVersion[4] = {2, 2, 0, 1}; /* GPS Version is 4 numbers! */
    unsigned char *pGpsVersion;
    float auxFloat = 0.0f;
    double auxDouble = 0.0;
    char auxChar = 0;
    uint32_t auxUint32 = 0;
    short auxShort = 0;
    int32_t auxInt32 = 0;
    void *pVoid;
    int blnIsRational2Double;

    int i, j;
    int32_t nTags;

    const TIFFFieldArray *tFieldArray;
    uint32_t tTag;
    TIFFDataType tType;
    short tWriteCount;
    TIFFSetGetFieldType tSetFieldType;
    char *tFieldName;
    const TIFFField *fip;

    char blnFillGPSManually = 1;

#define STRSIZE 1000
#define N_SIZE 120
#define VARIABLE_ARRAY_SIZE 6

    /* -- Test data for writing -- */
    char auxCharArrayW[N_SIZE];
    short auxShortArrayW[N_SIZE];
    int32_t auxInt32ArrayW[N_SIZE];
    float auxFloatArrayW[N_SIZE];
    double auxDoubleArrayW[N_SIZE];
    char auxTextArrayW[N_SIZE][STRSIZE];
    double auxDoubleArrayGPS1[3] = {1.0 / 7.0, 61.23456789012345, 62.0};
    double auxDoubleArrayGPS2[3] = {1.0 / 19.0, 88.34434,
                                    15.12345678901234567890};
    double auxDoubleArrayGPSTime[3] = {22.0, 17.0, 15.3456789};
    double auxDoubleGPSAltitude = 3456.0;
    double auxDoubleGPSDirection = 63.7;
    float auxFloatArrayN1[3] = {1.0f / 7.0f, 61.23456789012345f, 62.3f};
    float auxFloatArrayN2[3] = {-1.0f / 7.0f, -61.23456789012345f, -62.3f};
    float auxFloatArrayResolutions[4] = {5.456789f, 6.666666f, 0.0033f,
                                         5.0f / 213.0f};

    /* -- Variables for reading -- */
    uint16_t count16 = 0;
    union
    {
        int32_t Int32;
        short Short1;
        short Short2[2];
        char Char[4];
    } unionInt32;
    union
    {
        double dbl;
        float flt1;
        float flt2;
    } auxDblUnion;
    void *pVoidArray;
    char *pAscii;
    char auxCharArray[2 * STRSIZE];
    short auxShortArray[2 * N_SIZE];
    int32_t auxInt32Array[2 * N_SIZE];
    float auxFloatArray[2 * N_SIZE];
    double auxDoubleArray[2 * N_SIZE];
    double dblDiff, dblDiffLimit;
#define RATIONAL_EPS                                                           \
    (1.0 / 30000.0) /* reduced difference of rational values, approx 3.3e-5 */

    /*-- Fill test data arrays for writing ----------- */
    for (i = 0; i < N_SIZE; i++)
    {
        sprintf(auxTextArrayW[i],
                "N%d-String-%d_tttttttttttttttttttttttttttttx", i, i);
    }
    for (i = 0; i < N_SIZE; i++)
    {
        auxCharArrayW[i] = (char)(i + 1);
    }
    for (i = 0; i < N_SIZE; i++)
    {
        auxShortArrayW[i] = (short)(i + 1) * 7;
    }
    for (i = 0; i < N_SIZE; i++)
    {
        auxInt32ArrayW[i] = (i + 1) * 133;
    }
    for (i = 0; i < N_SIZE; i++)
    {
        auxFloatArrayW[i] = (float)((i + 1) * 133) / 3.3f;
    }
    for (i = 0; i < N_SIZE; i++)
    {
        auxDoubleArrayW[i] = (double)((i + 1) * 3689) / 4.5697;
    }

    /*-- Setup standard tags of a simple tiff file --*/
    if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width))
    {
        fprintf(stderr, "Can't set ImageWidth tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, length))
    {
        fprintf(stderr, "Can't set ImageLength tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps))
    {
        fprintf(stderr, "Can't set BitsPerSample tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, SPP))
    {
        fprintf(stderr, "Can't set SamplesPerPixel tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rows_per_strip))
    {
        fprintf(stderr, "Can't set SamplesPerPixel tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, planarconfig))
    {
        fprintf(stderr, "Can't set PlanarConfiguration tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric))
    {
        fprintf(stderr, "Can't set PhotometricInterpretation tag.\n");
        goto failure;
    }

    if (!TIFFSetField(tif, TIFFTAG_XRESOLUTION, auxFloatArrayResolutions[0]))
    {
        fprintf(stderr, "Can't set TIFFTAG_XRESOLUTION tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_YRESOLUTION, auxFloatArrayResolutions[1]))
    {
        fprintf(stderr, "Can't set TIFFTAG_YRESOLUTION tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_XPOSITION, auxFloatArrayResolutions[2]))
    {
        fprintf(stderr, "Can't set TIFFTAG_XPOSITION tag.\n");
        goto failure;
    }
    if (!TIFFSetField(tif, TIFFTAG_YPOSITION, auxFloatArrayResolutions[3]))
    {
        fprintf(stderr, "Can't set TIFFTAG_YPOSITION tag.\n");
        goto failure;
    }

#define ADDITIONAL_TAGS
#ifdef ADDITIONAL_TAGS
    /*-- Additional tags to check Rational standard tags, which are also defined
     * as FIELD_CUSTOM */

    /*- TIFFTAG_INKSET is a SHORT parameter (TIFF_SHORT, TIFF_SETGET_UINT16)
     * with field_bit=FIELD_CUSTOM !! -*/
    if (!TIFFSetField(tif, TIFFTAG_INKSET, 34))
    {
        fprintf(stderr, "Can't set TIFFTAG_INKSET tag.\n");
        goto failure;
    }

    /*- TIFFTAG_PIXAR_FOVCOT is a FLOAT parameter ( TIFF_FLOAT,
     * TIFF_SETGET_FLOAT) with field_bit=FIELD_CUSTOM !! -*/
    /*  - can be written with Double but has to be read with float parameter */
#define PIXAR_FOVCOT_VAL 5.123456789123456789
    auxFloat = (float)PIXAR_FOVCOT_VAL;
    auxDouble = (double)PIXAR_FOVCOT_VAL;
    if (!TIFFSetField(tif, TIFFTAG_PIXAR_FOVCOT, auxDouble))
    {
        fprintf(stderr, "Can't set TIFFTAG_PIXAR_FOVCOT tag.\n");
        goto failure;
    }
    /*- TIFFTAG_STONITS is a DOUBLE parameter (TIFF_DOUBLE, TIFF_SETGET_DOUBLE)
     * with field_bit=FIELD_CUSTOM! Only TIFFTAG_STONITS is a TIFF_DOUBLE, which
     * has to be read as DOUBLE!!
     */
#define STONITS_VAL 6.123456789123456789
    auxDouble = STONITS_VAL;
    auxFloat = (float)auxDouble;
    if (!TIFFSetField(tif, TIFFTAG_STONITS, auxDouble))
    {
        fprintf(stderr, "Can't set TIFFTAG_STONITS tag.\n");
        goto failure;
    }

    /*- TIFFTAG_YCBCRPOSITIONING is a SHORT parameter */
    auxInt32 = auxShort = 5;
    if (!TIFFSetField(tif, TIFFTAG_YCBCRPOSITIONING, auxInt32))
    {
        fprintf(stderr, "Can't set TIFFTAG_YCBCRPOSITIONING tag.\n");
        goto failure;
    }

    /* - TIFFTAG_BESTQUALITYSCALE is a Rational parameter, FIELD_CUSTOM and
     * TIFF_SETGET_DOUBLE */
    /* With Rational2Double upgrade tag is redefined to TIFF_SETGET_FLOAT, but
     * can be still written with double. */
#define BESTQUALITYSCALE_VAL 15.3
    auxDouble = BESTQUALITYSCALE_VAL;
    if (!TIFFSetField(tif, TIFFTAG_BESTQUALITYSCALE, auxDouble))
    {
        fprintf(stderr, "Can't set TIFFTAG_BESTQUALITYSCALE tag.\n");
        goto failure;
    }

    /* - TIFFTAG_BASELINENOISE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT */
    if (!TIFFSetField(tif, TIFFTAG_BASELINENOISE, auxDouble))
    {
        fprintf(stderr, "Can't set TIFFTAG_BASELINENOISE tag.\n");
        goto failure;
    }

    /*--- For static or variable ARRAYs the case is different ---*/
    /*- Variable Array: TIFFTAG_DECODE is a SRATIONAL parameter
     * TIFF_SETGET_C16_FLOAT type FIELD_CUSTOM with passcount=1 and variable
     * length of array. */
    if (!TIFFSetField(tif, TIFFTAG_DECODE, 3, auxFloatArrayN2))
    {
        fprintf(stderr, "Can't set TIFFTAG_DECODE tag.\n");
        goto failure;
    }

    /*- Variable Array:  TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT */
    if (!TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 3, auxFloatArrayN1))
    {
        fprintf(stderr, "Can't set TIFFTAG_BLACKLEVEL tag.\n");
        goto failure;
    }

    /*- Fixed Array: TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, 0,
     * TIFF_SETGET_C0_FLOAT */
    if (!TIFFSetField(tif, TIFFTAG_DEFAULTCROPSIZE, &auxFloatArrayW[0]))
    {
        fprintf(stderr, "Can't set TIFFTAG_DEFAULTCROPSIZE tag.\n");
        goto failure;
    }
#endif /* -- ADDITIONAL_TAGS -- */

    /*================== Rational2Double Interface Check =====================*/
    /*-- Check, if the TiffLibrary is compiled with the new interface with
       Rational2Double or still uses the old definitions. For that,
       TIFF_RATIONAL tags with FIELD_CUSTOM are changed from TIFF_SETGET_DOUBLE
       to TIFF_SETGET_FLOAT for the new interface in order to prevent the old
       reading behavior. Tags to check: TIFFTAG_BESTQUALITYSCALE,
       TIFFTAG_BASELINENOISE, TIFFTAG_BASELINESHARPNESS
     */
    fip = TIFFFindField(tif, TIFFTAG_BESTQUALITYSCALE, TIFF_ANY);
    tSetFieldType = fip->set_field_type;
    if (tSetFieldType == TIFF_SETGET_DOUBLE)
    {
        blnIsRational2Double = FALSE;
    }
    else
    {
        blnIsRational2Double = TRUE;
        fprintf(stderr, "-- Rational2Double from TIFF tag detected --\n");
    }

    /*================== Write GPS and EXIF tags =====================*/

    /*-- Set dummy EXIF/GPS tag in original tiff-structure in order to reserve
     * space for final dir_offset value, */
    /*   which is properly written at the end.  */
    dir_offset = 0; /* Zero, in case no Custom-IFD is written */

#define WRITE_GPS_TAGS
#ifdef WRITE_GPS_TAGS
    if (!TIFFSetField(tif, TIFFTAG_GPSIFD, dir_offset))
    {
        fprintf(stderr, "Can't write TIFFTAG_GPSIFD\n");
    }
#endif

    /*------- And also do the same for the EXIF IFD tag here, because we have to
     * save the main directory next ------*/
    /*-- Set dummy EXIF/GPS tag in original tiff-structure in order to reserve
     * space for final dir_offset value, which is properly written at the end.
     */
#define WRITE_EXIF_TAGS
#ifdef WRITE_EXIF_TAGS
    if (!TIFFSetField(tif, TIFFTAG_EXIFIFD, dir_offset))
    {
        fprintf(stderr, "Can't write TIFFTAG_EXIFIFD\n");
    }
#endif

#ifndef WRITEPIXELLAST
    /*-- Write dummy pixel data. --*/
    if (TIFFWriteScanline(tif, buf, 0, 0) < 0)
    {
        fprintf(stderr, "Can't write image data.\n");
        goto failure;
    }
#endif

#ifdef WRITE_GPS_TAGS
#define READ_GPS_TAGS
    /*================== Write GPS tags =====================*/

    /*-- Save current tiff-directory to file before directory is changed.
     * Otherwise it will be lost!  */
    /*   The tif-structure is overwritten/ freshly initialized by any
     * "CreateDirectory" */
    /*retCode = TIFFCheckpointDirectory(tif);*/ /* does not cleanup
                                                   Tiff-Structure */
    retCode = TIFFWriteDirectory(tif);          /* cleanup Tiff-structure */

    /*-- Now create a GPS directory. */
    if (TIFFCreateGPSDirectory(tif) != 0)
    {
        fprintf(stderr, "TIFFCreateGPSDirectory() failed.\n");
        goto failure;
    }

    if (!TIFFSetField(tif, GPSTAG_VERSIONID, gpsVersion))
    {
        fprintf(stderr, "Can't write GPSTAG_VERSIONID\n");
        goto failure;
    }

    if (blnFillGPSManually)
    {
        /*================= Write manually valid data to the GPS fields
         * ==============*/
        if (!TIFFSetField(tif, GPSTAG_LATITUDEREF, "N\0"))
        {
            fprintf(stderr, "Can't write GPSTAG_LATITUDEREF\n");
            goto failure;
        }
        /*-- Unfortunately, Rational values are defined as SETGET_DOUBLE but are
         * internally always stored as float. Single Rational values do not
         * matter for writing, because TIFFSetField() uses va_arg() which
         * performs "variables promotion" from type float to type double!
         *   However, for reading of Rational values ONLY float-variables are
         * allowed - in contrary to the SETGET_DOUBLE specification at
         * tiffFields[] in tif_dirinfo.c.
         */
        /*-- ATTENTION: After the upgrade with Rational2Double, the GPSTAG
         * values are defined as double precision and need to be written and
         * also read in double precision! In order to maintain this code for
         * both cases, it is checked above if the TiffLibrary is compiled with
         * the new interface with Rational2Double or still uses the old
         * definitions, by setting blnIsRational2Double above.
         */
        if (blnIsRational2Double)
        {
            fprintf(stderr,
                    "-- GPS tags are written using Rational2Double --\n");
        }
        else
        {
            fprintf(stderr, "-- GPS tags are written using standard --\n");
        }
        if (!blnIsRational2Double)
        {
            for (j = 0; j < 3; j++)
                auxFloatArray[j] = (float)auxDoubleArrayGPS1[j];
            if (!TIFFSetField(tif, GPSTAG_LATITUDE, auxFloatArray))
            {
                fprintf(stderr, "Can't write GPSTAG_LATITUDE\n");
                goto failure;
            }
        }
        else
        {
            /* Rational2Double interface for GPSTAG */
            if (!TIFFSetField(tif, GPSTAG_LATITUDE, auxDoubleArrayGPS1))
            {
                fprintf(stderr, "Can't write GPSTAG_LATITUDE\n");
                goto failure;
            }
        }
        if (!TIFFSetField(tif, GPSTAG_LONGITUDEREF, "W\0"))
        {
            fprintf(stderr, "Can't write GPSTAG_LONGITUDEREF\n");
            goto failure;
        }
        if (!blnIsRational2Double)
        {
            for (j = 0; j < 3; j++)
                auxFloatArray[j] = (float)auxDoubleArrayGPS2[j];
            if (!TIFFSetField(tif, GPSTAG_LONGITUDE, auxFloatArray))
            {
                fprintf(stderr, "Can't write GPSTAG_LONGITUDE\n");
                goto failure;
            }
        }
        else
        {
            /* Rational2Double interface for GPSTAG */
            if (!TIFFSetField(tif, GPSTAG_LONGITUDE, auxDoubleArrayGPS2))
            {
                fprintf(stderr, "Can't write GPSTAG_LONGITUDE\n");
                goto failure;
            }
        }
        /*-- AltitudeRef: default is above sea level!! */
        if (!TIFFSetField(tif, GPSTAG_ALTITUDEREF, 0))
        {
            fprintf(stderr, "Can't write GPSTAG_ALTITUDEREF\n");
            goto failure;
        }
        if (!TIFFSetField(tif, GPSTAG_ALTITUDE, auxDoubleGPSAltitude))
        {
            fprintf(stderr, "Can't write GPSTAG_ALTITUDE\n");
            goto failure;
        }
        /*-- TimeStamp is only hh:mm:ss. See also DateTime string */
        if (!TIFFSetField(tif, GPSTAG_TIMESTAMP, auxDoubleArrayGPSTime))
        {
            fprintf(stderr, "Can't write GPSTAG_TIMESTAMP\n");
            goto failure;
        }
        if (!TIFFSetField(tif, GPSTAG_DATESTAMP, "2012:11:04"))
        {
            fprintf(stderr, "Can't write GPSTAG_DATESTAMP\n");
            goto failure;
        }

        if (!TIFFSetField(tif, GPSTAG_IMGDIRECTIONREF, "T\0"))
        {
            fprintf(stderr, "Can't write GPSTAG_IMGDIRECTIONREF\n");
            goto failure;
        }
        if (!TIFFSetField(tif, GPSTAG_IMGDIRECTION, auxDoubleGPSDirection))
        {
            fprintf(stderr, "Can't write GPSTAG_IMGDIRECTION\n");
            goto failure;
        }

        /*-- Type TIFF_UNDEFINED */
        if (!TIFFSetField(tif, GPSTAG_PROCESSINGMETHOD, 3, &auxCharArrayW[10]))
        {
            fprintf(stderr, "Can't write GPSTAG_PROCESSINGMETHOD\n");
            goto failure;
        }
        if (!TIFFSetField(tif, GPSTAG_AREAINFORMATION, 4, &auxCharArrayW[20]))
        {
            fprintf(stderr, "Can't write GPSTAG_AREAINFORMATION\n");
            goto failure;
        }

        /*-- PSTAG_DIFFERENTIAL	, 1, 1,	TIFF_SHORT	, 0,
         * TIFF_SETGET_UINT16 */
        if (!TIFFSetField(tif, GPSTAG_DIFFERENTIAL, auxShortArrayW[5]))
        {
            fprintf(stderr, "Can't write GPSTAG_DIFFERENTIAL\n");
            goto failure;
        }

        /* GPSTAG_GPSHPOSITIONINGERROR	, 1, 1,	TIFF_RATIONAL	, 0,
         * TIFF_SETGET_DOUBLE  but here written in float-precision */
#define GPSHPOSITIONINGERROR_VAL 0.369
        auxFloat = (float)GPSHPOSITIONINGERROR_VAL;
        if (!TIFFSetField(tif, GPSTAG_GPSHPOSITIONINGERROR, auxFloat))
        {
            fprintf(stderr, "Can't write GPSTAG_GPSHPOSITIONINGERROR\n");
            goto failure;
        }
    }
    else
    {
        /*================= Write arbitrary data to the GPS fields
         * ==============*/

        /*-- Get array, where GPS tag fields are defined --*/
        tFieldArray = _TIFFGetGpsFields();
        nTags = tFieldArray->count;

        /*-- TODO: fill in the for / switch part of EXIF writing, when finished
         * and tested!! */

    } /*-- if (blnFillGPSManually) --*/

    /*-- GPS - write custom directory GPS into file...---*/
    /*   (Get back the offset of GPS directory)          */
    if (!TIFFWriteCustomDirectory(tif, &dir_offset_GPS))
    {
        fprintf(stderr, "TIFFWriteCustomDirectory() with GPS failed.\n");
        goto failure;
    }

    /*--- CheckpointDirectory at this place generates a second Main-IFD!!! */
    /* retCode = TIFFCheckpointDirectory(tif); */

    /*-- Set / reload previously saved main directory from file ---*/
    if (!TIFFSetDirectory(tif, 0))
    {
        fprintf(stderr, "TIFFSetDirectory() within GPS failed.\n");
        goto failure;
    }

    /*-- Write GPS tag reference / offset into GPSIFD tag in main directory --*/
    if (!TIFFSetField(tif, TIFFTAG_GPSIFD, dir_offset_GPS))
    {
        fprintf(stderr, "Can't write TIFFTAG_GPSIFD\n");
        goto failure;
    }

    /*===============  END writing GPS tags ==========================*/
#endif /*-- WRITE_GPS_TAGS --*/

    /*================== Write EXIF 2.31 tags =====================*/

    /*-- Set dummy EXIF/GPS tag in original tiff-structure in order to reserve
     * space for final dir_offset value, */
    /*   which is properly written at the end.*/
    /*- We did this already above together with the GPS IFD-tag. Otherwise we
     * would do this here !! --------*/
    /* if (!TIFFSetField(tif, TIFFTAG_EXIFIFD, dir_offset )) {
            fprintf (stderr, "Can't write TIFFTAG_EXIFIFD\n" );
    }
    */

#ifdef WRITE_EXIF_TAGS
#define READ_EXIF_TAGS
    /*-- Save current tiff-directory to file before directory is changed.
     * Otherwise it will be lost! The tif-structure is overwritten/ freshly
     * initialized by any "CreateDirectory"
     */

    /*-----  What is needed here ??? ----
     * In custom_dir.c only 	TIFFFreeDirectory( tif );   is used to set
     *fields of another Sub-Directory TIFFFreeDirectory(tif);  *-- Release
     *storage associated with a directory, especially custom-fields.
     *-- Using only  TIFFFreeDirectory() here leads to an error!!
     *-- Using here TIFFCheckpointDirectory() leads to an additional Main-IFD ??
     */
    /*retCode = TIFFCheckpointDirectory(tif);*/ /* does not cleanup
                                                   Tiff-Structure */
    retCode = TIFFWriteDirectory(tif);          /* cleanup Tiff-structure */

    /*-- Now create an EXIF directory. */
    if (TIFFCreateEXIFDirectory(tif) != 0)
    {
        fprintf(stderr, "TIFFCreateEXIFDirectory() failed.\n");
        goto failure;
    }

#define WRITE_ALL_EXIF_TAGS
#ifdef WRITE_ALL_EXIF_TAGS
#define READ_ALL_EXIF_TAGS
    /*================= EXIF: Write arbitrary data to the EXIF fields
     * ==============*/
    /*-- Get array, where EXIF tag fields are defined
     *    EXIF tags are written automatically with the defined precision
     * according to its tSetFieldType using the code below  --*/
    tFieldArray = _TIFFGetExifFields();
    nTags = tFieldArray->count;

    for (i = 0; i < nTags; i++)
    {
        bool deferredSetField = false;
        tTag = tFieldArray->fields[i].field_tag;
        tType = tFieldArray->fields[i].field_type; /* e.g. TIFF_RATIONAL */
        tWriteCount = tFieldArray->fields[i].field_writecount;
        tSetFieldType = tFieldArray->fields[i]
                            .set_field_type; /* e.g. TIFF_SETGET_C0_FLOAT */
        tFieldName = tFieldArray->fields[i].field_name;
        pVoid = NULL;

        /*-- dependent on set_field_type write value --*/
        switch (tSetFieldType)
        {
            case TIFF_SETGET_ASCII:
                /* Either the stringlength is defined as a fixed length in
                 * .field_writecount or a NULL-terminated string is used. */
                /* Shorter strings than in auxTextArraxW need a
                 * NULL-termination. Therefore copy the string. */
                if (tWriteCount > 0)
                    auxInt32 = tWriteCount - 1;
                else
                    auxInt32 = (int32_t)strlen(auxTextArrayW[i]) - 1;
                strncpy(auxCharArray, auxTextArrayW[i], auxInt32);
                auxCharArray[auxInt32] = 0;
                if (!TIFFSetField(tif, tTag, auxCharArray))
                {
                    fprintf(stderr, "Can't write %s\n",
                            tFieldArray->fields[i].field_name);
                    goto failure;
                }
                break;
            case TIFF_SETGET_UINT8:
            case TIFF_SETGET_UINT16:
            case TIFF_SETGET_UINT32:
            case TIFF_SETGET_IFD8:
            case TIFF_SETGET_INT:
                /*-- All those can be written with char, short or long
                 * parameter. Only value range should be in line. */
                if (!TIFFSetField(tif, tTag, auxInt32ArrayW[i]))
                {
                    fprintf(stderr, "Can't write %s\n",
                            tFieldArray->fields[i].field_name);
                    goto failure;
                }
                break;
            case TIFF_SETGET_SINT8:
            case TIFF_SETGET_SINT16:
            case TIFF_SETGET_SINT32:
                /*-- All those can be written with char, short or long
                 * parameter. Only value range should be in line. */
                if (!TIFFSetField(tif, tTag, -1.0 * auxInt32ArrayW[i]))
                {
                    fprintf(stderr, "Can't write %s\n",
                            tFieldArray->fields[i].field_name);
                    goto failure;
                }
                break;
            case TIFF_SETGET_FLOAT:
            case TIFF_SETGET_DOUBLE:
                if (tWriteCount == 1)
                {
                    /*-- All single values can be written with float or double
                     * parameter. Only value range should be in line. */
                    if (!TIFFSetField(tif, tTag, auxDoubleArrayW[i]))
                    {
                        fprintf(stderr, "Can't write %s\n",
                                tFieldArray->fields[i].field_name);
                        goto failure;
                    }
                }
                else
                {
                    fprintf(
                        stderr,
                        "WriteCount for .set_field_type %d should be 1!  %s\n",
                        tSetFieldType, tFieldArray->fields[i].field_name);
                }
                break;
            case TIFF_SETGET_C0_FLOAT:
            case TIFF_SETGET_C0_DOUBLE:
            case TIFF_SETGET_C16_FLOAT:
            case TIFF_SETGET_C16_DOUBLE:
            case TIFF_SETGET_C32_FLOAT:
            case TIFF_SETGET_C32_DOUBLE:
                /* _Cxx_ just defines the size of the count parameter for the
                 * array as C0=char, C16=short or C32=long */
                /*-- Check, if it is a single parameter, a fixed array or a
                 * variable array */
                if (tWriteCount == 1)
                {
                    fprintf(stderr,
                            "WriteCount for .set_field_type %d should be -1 or "
                            "greater than 1!  %s\n",
                            tSetFieldType, tFieldArray->fields[i].field_name);
                }
                else
                {
                    /*-- Either fix or variable array --*/
                    /* For arrays, distinguishing between float or double is
                     * essential, even for writing */
                    if (tSetFieldType == TIFF_SETGET_C0_FLOAT ||
                        tSetFieldType == TIFF_SETGET_C16_FLOAT ||
                        tSetFieldType == TIFF_SETGET_C32_FLOAT)
                        pVoid = &auxFloatArrayW[i];
                    else
                        pVoid = &auxDoubleArrayW[i];
                    /* Now decide between fixed or variable array */
                    if (tWriteCount > 1)
                    {
                        /* fixed array with needed arraysize defined in
                         * .field_writecount */
                        if (!TIFFSetField(tif, tTag, pVoid))
                        {
                            fprintf(stderr, "Can't write %s\n",
                                    tFieldArray->fields[i].field_name);
                            goto failure;
                        }
                    }
                    else
                    {
                        /* special treatment of variable array */
                        /* for test, use always arraysize of VARIABLE_ARRAY_SIZE
                         */
                        if (!TIFFSetField(tif, tTag, VARIABLE_ARRAY_SIZE,
                                          pVoid))
                        {
                            fprintf(stderr, "Can't write %s\n",
                                    tFieldArray->fields[i].field_name);
                            goto failure;
                        }
                    }
                }
                break;
            case TIFF_SETGET_C0_UINT8:
            case TIFF_SETGET_C0_SINT8:
            case TIFF_SETGET_C16_UINT8:
            case TIFF_SETGET_C16_SINT8:
            case TIFF_SETGET_C32_UINT8:
            case TIFF_SETGET_C32_SINT8:
                /* For arrays, distinguishing between float or double is
                 * essential, even for writing */
                pVoid = &auxCharArrayW[i];
                deferredSetField = true;
                break;
            case TIFF_SETGET_C0_UINT16:
            case TIFF_SETGET_C0_SINT16:
            case TIFF_SETGET_C16_UINT16:
            case TIFF_SETGET_C16_SINT16:
            case TIFF_SETGET_C32_UINT16:
            case TIFF_SETGET_C32_SINT16:
                pVoid = &auxShortArrayW[i];
                deferredSetField = true;
                break;
            case TIFF_SETGET_C0_UINT32:
            case TIFF_SETGET_C0_SINT32:
            case TIFF_SETGET_C16_UINT32:
            case TIFF_SETGET_C16_SINT32:
            case TIFF_SETGET_C32_UINT32:
            case TIFF_SETGET_C32_SINT32:
                pVoid = &auxInt32ArrayW[i];
                deferredSetField = true;
                break;
            default:
                fprintf(stderr,
                        "SetFieldType %d not defined within writing switch for "
                        "%s.\n",
                        tSetFieldType, tFieldName);
        }; /*-- switch() --*/

        if (deferredSetField)
        {
            /* _Cxx_ just defines the size of the count parameter for the array
             * as C0=char, C16=short or C32=long */
            /*-- Check, if it is a single parameter, a fixed array or a variable
             * array */
            if (tWriteCount == 1)
            {
                fprintf(stderr,
                        "WriteCount for .set_field_type %d should be -1 or "
                        "greater than 1!  %s\n",
                        tSetFieldType, tFieldArray->fields[i].field_name);
            }
            else
            {
                /*-- Either fix or variable array --*/
                /* Now decide between fixed or variable array */
                if (tWriteCount > 1)
                {
                    /* fixed array with needed arraysize defined in
                     * .field_writecount */
                    if (!TIFFSetField(tif, tTag, pVoid))
                    {
                        fprintf(stderr, "Can't write %s\n",
                                tFieldArray->fields[i].field_name);
                        goto failure;
                    }
                }
                else
                {
                    /* special treatment of variable array */
                    /* for test, use always arraysize of VARIABLE_ARRAY_SIZE */
                    if (!TIFFSetField(tif, tTag, VARIABLE_ARRAY_SIZE, pVoid))
                    {
                        fprintf(stderr, "Can't write %s\n",
                                tFieldArray->fields[i].field_name);
                        goto failure;
                    }
                }
            }
        }
    } /*-- for() --*/
    /*================= EXIF: END Writing arbitrary data to the EXIF fields END
     * END END ==============*/
#endif /*-- WRITE_ALL_EXIF_TAGS --*/

    /*--- Set valid EXIF version, which is a 4 byte string --*/
    if (!TIFFSetField(tif, EXIFTAG_EXIFVERSION, exifVersion))
    {
        fprintf(stderr, "Can't write EXIFTAG_EXIFVERSION\n");
        goto failure;
    }

    /*-- EXIF - write custom directory EXIF into file...---*/
    /*   (Get back the offset of EXIF directory) */
    if (!TIFFWriteCustomDirectory(tif, &dir_offset_EXIF))
    {
        fprintf(stderr, "TIFFWriteCustomDirectory() with EXIF failed.\n");
        goto failure;
    }

    /*-- Go back to the first (main) directory, and set correct value of the
     * EXIFIFD pointer.  */
    /*   (directory is reloaded from file!) */
    TIFFSetDirectory(tif, 0);
    TIFFSetField(tif, TIFFTAG_EXIFIFD, dir_offset_EXIF);
#endif /*-- WRITE_EXIF_TAGS --*/

#ifdef WRITEPIXELLAST
    /*-- Write dummy pixel data. --*/
    if (TIFFWriteScanline(tif, buf, 0, 0) < 0)
    {
        fprintf(stderr, "Can't write image data.\n");
        goto failure;
    }
#endif
    /*-- Write directory to file --*/
    /* Always WriteDirectory before using/creating another directory. */
    /* Not necessary before TIFFClose(), however, TIFFClose() uses
     * TIFFReWriteDirectory(), which forces directory to be written at another
     * location. */
    retCode = TIFFWriteDirectory(tif);

    /*-- Write File to disk and close file --*/
    /* TIFFClose() uses TIFFReWriteDirectory(), which forces directory to be
     * written at another location. */
    /* Therefore, better use TIFFWriteDirectory() before. */
    TIFFClose(tif);

    fprintf(stderr, "-------- Continue Test  ---------- reading ...\n");

    /*=========================  READING  =============  READING
     * ========================================*/
    /* Ok, now test whether we can read written values correctly. */
    tif = TIFFOpen(filenameRead, "r");

    /*-- Read some parameters out of the main directory --*/

    /*-- IMAGEWIDTH and -LENGTH are defined as TIFF_SETGET_UINT32 */
    retCode = TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &auxUint32);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_IMAGEWIDTH");
    }
    if (auxUint32 != width)
    {
        fprintf(stderr,
                "Read value of IMAGEWIDTH %" PRIu32
                " differs from set value %" PRIu16 "\n",
                auxUint32, width);
    }
    retCode = TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &auxUint32);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_IMAGELENGTH");
    }
    if (auxUint32 != length)
    {
        fprintf(stderr,
                "Read value of TIFFTAG_IMAGELENGTH %" PRIu32
                " differs from set value %" PRIu16 "\n",
                auxUint32, length);
    }

#ifdef ADDITIONAL_TAGS
    /*- TIFFTAG_PIXAR_FOVCOT is a FLOAT parameter of type  FIELD_CUSTOM !! */
    retCode = TIFFGetField(tif, TIFFTAG_PIXAR_FOVCOT, &auxFloat);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_PIXAR_FOVCOT");
    }
    if (auxFloat != (float)PIXAR_FOVCOT_VAL)
    {
        fprintf(
            stderr,
            "Read value of TIFFTAG_PIXAR_FOVCOT %f differs from set value %f\n",
            auxFloat, PIXAR_FOVCOT_VAL);
    }

    /* - TIFFTAG_BESTQUALITYSCALE is a Rational parameter, FIELD_CUSTOM and
     * TIFF_SETGET_FLOAT  */
    retCode = TIFFGetField(tif, TIFFTAG_BESTQUALITYSCALE, &auxFloat);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_BESTQUALITYSCALE");
    }
    if (auxFloat != (float)BESTQUALITYSCALE_VAL)
    {
        fprintf(stderr,
                "Read value of TIFFTAG_BESTQUALITYSCALE %f differs from set "
                "value %f\n",
                auxFloat, BESTQUALITYSCALE_VAL);
    }

    /* - TIFFTAG_BASELINENOISE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT */
    retCode = TIFFGetField(tif, TIFFTAG_BASELINENOISE, &auxDblUnion.dbl);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_BASELINENOISE");
    }
    if (auxDblUnion.flt1 != (float)BESTQUALITYSCALE_VAL)
    {
        fprintf(stderr,
                "Read float value of TIFFTAG_BASELINENOISE %f differs from set "
                "value %f\n",
                auxDblUnion.flt1, BESTQUALITYSCALE_VAL);
    }

    /*- Variable Array: TIFFTAG_DECODE is a SRATIONAL parameter
     * TIFF_SETGET_C16_FLOAT type FIELD_CUSTOM with passcount=1 and variable
     * length of array. */
    retCode = TIFFGetField(tif, TIFFTAG_DECODE, &count16, &pVoidArray);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_DECODE");
    }
    /*- pVoidArray points to a Tiff-internal temporary memorypart. Thus,
     * contents needs to be saved. */
    memcpy(&auxFloatArray, pVoidArray, (count16 * sizeof(auxFloatArray[0])));
    for (i = 0; i < count16; i++)
    {
        dblDiffLimit = RATIONAL_EPS * auxFloatArrayN2[i];
        dblDiff = auxFloatArray[i] - auxFloatArrayN2[i];
        if (fabs(dblDiff) > fabs(dblDiffLimit))
        {
            fprintf(stderr,
                    "Read value %d of TIFFTAG_DECODE Array %f differs from set "
                    "value %f\n",
                    i, auxFloatArray[i], auxFloatArrayN2[i]);
        }
    }

    retCode = TIFFGetField(tif, TIFFTAG_BLACKLEVEL, &count16, &pVoidArray);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_BLACKLEVEL");
    }
    /*- pVoidArray points to a Tiff-internal temporary memorypart. Thus,
     * contents needs to be saved. */
    memcpy(&auxFloatArray, pVoidArray, (count16 * sizeof(auxFloatArray[0])));
    for (i = 0; i < count16; i++)
    {
        dblDiffLimit = RATIONAL_EPS * auxFloatArrayN1[i];
        dblDiff = auxFloatArray[i] - auxFloatArrayN1[i];
        if (fabs(dblDiff) > fabs(dblDiffLimit))
        {
            fprintf(stderr,
                    "Read value %d of TIFFTAG_BLACKLEVEL Array %f differs from "
                    "set value %f\n",
                    i, auxFloatArray[i], auxFloatArrayN1[i]);
        }
    }

    /*- Fixed Array: TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, 0,
     * TIFF_SETGET_C0_FLOAT */
    retCode = TIFFGetField(tif, TIFFTAG_DEFAULTCROPSIZE, &pVoidArray);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_DEFAULTCROPSIZE");
    }
    /*- pVoidArray points to a Tiff-internal temporary memorypart. Thus,
     * contents needs to be saved. */
    memcpy(&auxFloatArray, pVoidArray, (2 * sizeof(auxFloatArray[0])));
    for (i = 0; i < 2; i++)
    {
        dblDiffLimit = RATIONAL_EPS * auxFloatArrayW[i];
        dblDiff = auxFloatArray[i] - auxFloatArrayW[i];
        if (fabs(dblDiff) > fabs(dblDiffLimit))
        {
            fprintf(stderr,
                    "Read value %d of TIFFTAG_DEFAULTCROPSIZE Array %f differs "
                    "from set value %f\n",
                    i, auxFloatArray[i], auxFloatArrayW[i]);
        }
    }

#endif /*-- ADDITIONAL_TAGS --*/

#ifdef READ_GPS_TAGS
    /*================== Reading GPS tags =====================*/
    /*-- First get offset to GPS-directory and set it active (this will destroy
     * previously main directory fields in memory!) */
    retCode = TIFFGetField(tif, TIFFTAG_GPSIFD, &read_dir_offset);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFTAG_GPSIFD");
    }
    retCode = TIFFReadGPSDirectory(tif, read_dir_offset);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "TIFFReadGPSDirectory()");
    }

    /*-- Now read some parameters from GPS-directory --*/

    /*-- Fixed Array: GPS-Version is a fixed array (of 4 characters) */
    retCode = TIFFGetField(tif, GPSTAG_VERSIONID, &pGpsVersion);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "GPSTAG_VERSIONID");
    }
    else
    {
        memcpy(auxCharArray, pGpsVersion, sizeof(gpsVersion));
        for (i = 0; i < 4; i++)
        {
            if (auxCharArray[i] != pGpsVersion[i])
            {
                fprintf(stderr,
                        "Read value %d of GPSTAG_VERSIONID %d differs from set "
                        "value %d\n",
                        i, auxCharArray[i], pGpsVersion[i]);
            }
        }
    }
    /*-- LATITUDEREF is a fixed String of one character plus ending zero. */
    retCode = TIFFGetField(tif, GPSTAG_LATITUDEREF, &pAscii);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "GPSTAG_LATITUDEREF");
    }
    retCode2 = strncmp("N", pAscii, 1);
    if (retCode2 != 0)
    {
        fprintf(stderr,
                "Read value %d of GPSTAG_LATITUDEREF %s differs from set value "
                "%s\n",
                i, "N", pAscii);
    }

    /*-- Fixed Array: Latitude is an array of 3 Rational-values. TIFFGetField()
     * returns a pointer to a temporary float-/double-array. */
    /*-- ATTENTION: After the upgrade with Rational2Double, the GPSTAG values
     * are defined as double precision and need to be written and also read in
     * double precision! In order to maintain this code for both cases, it is
     * checked above if the TiffLibrary is compiled with the new interface with
     * Rational2Double or still uses the old definitions, by setting
     * blnIsRational2Double above.
     */
    if (blnIsRational2Double)
    {
        fprintf(stderr, "-- GPS tags are read using Rational2Double --\n");
    }
    else
    {
        fprintf(stderr, "-- GPS tags are read using standard --\n");
    }
    retCode = TIFFGetField(tif, GPSTAG_LATITUDE, &pVoidArray);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "GPSTAG_LATITUDE");
    }
    if (!blnIsRational2Double)
    {
        /* Reset arrays for debugging purpose first */
        memset(auxFloatArray, 0, sizeof(auxFloatArray));
        memcpy(auxFloatArray, pVoidArray, 3 * sizeof(float));
        /* for comparison copy to doubleArray */
        for (i = 0; i < 3; i++)
            auxDoubleArray[i] = (double)auxFloatArray[i];
    }
    else
    {
        /* Rational2Double interface for GPSTAG reads double array */
        memset(auxDoubleArray, 0, sizeof(auxDoubleArray));
        memcpy(auxDoubleArray, pVoidArray, 3 * sizeof(double));
    }
    for (i = 0; i < 3; i++)
    {
        dblDiffLimit = RATIONAL_EPS * auxDoubleArrayGPS1[i];
        dblDiff = auxDoubleArray[i] - auxDoubleArrayGPS1[i];
        if (fabs(dblDiff) > fabs(dblDiffLimit))
        {
            fprintf(stderr,
                    "Read value %d of GPSTAG_LATITUDE %f differs from set "
                    "value %f\n",
                    i, auxDoubleArray[i], auxDoubleArrayGPS1[i]);
        }
    }

    /*-- LONGITUDEREF is a fixed String of one character plus ending zero. */
    retCode = TIFFGetField(tif, GPSTAG_LONGITUDEREF, &pAscii);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "GPSTAG_LONGITUDEREF");
    }
    retCode2 = strncmp("W", pAscii, 1);
    if (retCode2 != 0)
    {
        fprintf(stderr,
                "Read value %d of GPSTAG_LONGITUDEREF %s differs from set "
                "value %s\n",
                i, "W", pAscii);
    }

    retCode = TIFFGetField(tif, GPSTAG_LONGITUDE, &pVoidArray);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "GPSTAG_LONGITUDE");
    }
    if (!blnIsRational2Double)
    {
        /* Reset arrays for debugging purpose first */
        memset(auxFloatArray, 0, sizeof(auxFloatArray));
        memcpy(auxFloatArray, pVoidArray, 3 * sizeof(float));
        /* for comparison copy to doubleArray */
        for (i = 0; i < 3; i++)
            auxDoubleArray[i] = (double)auxFloatArray[i];
    }
    else
    {
        /* Rational2Double interface for GPSTAG reads double array */
        memset(auxDoubleArray, 0, sizeof(auxDoubleArray));
        memcpy(auxDoubleArray, pVoidArray, 3 * sizeof(double));
    }
    for (i = 0; i < 3; i++)
    {
        dblDiffLimit = RATIONAL_EPS * auxDoubleArrayGPS2[i];
        dblDiff = auxDoubleArray[i] - auxDoubleArrayGPS2[i];
        if (fabs(dblDiff) > fabs(dblDiffLimit))
        {
            fprintf(stderr,
                    "Read value %d of GPSTAG_LONGITUDE %f differs from set "
                    "value %f\n",
                    i, auxDoubleArray[i], auxDoubleArrayGPS2[i]);
        }
    }

    /* TIFF_RATIONAL, TIFF_SETGET_DOUBLE */
    if (!TIFFGetField(tif, GPSTAG_ALTITUDE, &auxDblUnion.dbl))
    {
        fprintf(stderr, "Can't read GPSTAG_ALTITUDE\n");
        GOTOFAILURE_GPS
    }
    if (blnIsRational2Double)
    {
        /* New interface allows also double precision for TIFF_RATIONAL */
        auxDouble = auxDblUnion.dbl;
    }
    else
    {
        /* Old interface reads TIFF_RATIONAL defined as TIFF_SETGET_DOUBLE
         * always as FLOAT */
        auxDouble = (double)auxDblUnion.flt1;
    }
    /* compare read values with written ones */
    dblDiffLimit = RATIONAL_EPS * auxDoubleGPSAltitude;
    dblDiff = auxDouble - auxDoubleGPSAltitude;
    if (fabs(dblDiff) > fabs(dblDiffLimit))
    {
        fprintf(stderr,
                "Read value of GPSTAG_ALTITUDE %f differs from set value %f\n",
                auxDouble, auxDoubleGPSAltitude);
        GOTOFAILURE_GPS
    }

    /*-- TimeStamp is only hh:mm:ss. See also DateTime string  3, TIFF_RATIONAL,
     * TIFF_SETGET_C0_DOUBLE */
    retCode = TIFFGetField(tif, GPSTAG_TIMESTAMP, &pVoidArray);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "GPSTAG_TIMESTAMP");
    }
    if (!blnIsRational2Double)
    {
        /* Reset arrays for debugging purpose first */
        memset(auxFloatArray, 0, sizeof(auxFloatArray));
        memcpy(auxFloatArray, pVoidArray, 3 * sizeof(float));
        /* for comparison copy to doubleArray */
        for (i = 0; i < 3; i++)
            auxDoubleArray[i] = (double)auxFloatArray[i];
    }
    else
    {
        /* Rational2Double interface for GPSTAG reads double array */
        memset(auxDoubleArray, 0, sizeof(auxDoubleArray));
        memcpy(auxDoubleArray, pVoidArray, 3 * sizeof(double));
    }
    for (i = 0; i < 3; i++)
    {
        dblDiffLimit = RATIONAL_EPS * auxDoubleArrayGPSTime[i];
        dblDiff = auxDoubleArray[i] - auxDoubleArrayGPSTime[i];
        if (fabs(dblDiff) > fabs(dblDiffLimit))
        {
            fprintf(stderr,
                    "Read value %d of GPSTAG_TIMESTAMP %f differs from set "
                    "value %f\n",
                    i, auxDoubleArray[i], auxDoubleArrayGPS2[i]);
            GOTOFAILURE_GPS
        }
    }

    /* GPSTAG_IMGDIRECTION --- TIFF_RATIONAL, TIFF_SETGET_DOUBLE */
    if (!TIFFGetField(tif, GPSTAG_IMGDIRECTION, &auxDblUnion.dbl))
    {
        fprintf(stderr, "Can't read GPSTAG_IMGDIRECTION\n");
        GOTOFAILURE_GPS
    }
    if (blnIsRational2Double)
    {
        /* New interface allows also double precision for TIFF_RATIONAL */
        auxDouble = auxDblUnion.dbl;
    }
    else
    {
        /* Old interface reads TIFF_RATIONAL defined as TIFF_SETGET_DOUBLE
         * always as FLOAT */
        auxDouble = (double)auxDblUnion.flt1;
    }
    /* compare read values with written ones */
    dblDiffLimit = RATIONAL_EPS * auxDoubleGPSDirection;
    dblDiff = auxDouble - auxDoubleGPSDirection;
    if (fabs(dblDiff) > fabs(dblDiffLimit))
    {
        fprintf(
            stderr,
            "Read value of GPSTAG_IMGDIRECTION %f differs from set value %f\n",
            auxDouble, auxDoubleGPSDirection);
        GOTOFAILURE_GPS
    }

    /*-- GPSTAG_DIFFERENTIAL	, 1, 1,	TIFF_SHORT	, 0,
     * TIFF_SETGET_UINT16
     */
    retCode = TIFFGetField(tif, GPSTAG_DIFFERENTIAL, &auxShort);
    if (!retCode)
    {
        fprintf(stderr, "Can't read %s\n", "GPSTAG_DIFFERENTIAL");
    }
    if (auxShort != auxShortArrayW[5])
    {
        fprintf(
            stderr,
            "Read value of GPSTAG_DIFFERENTIAL %d differs from set value %d\n",
            auxShort, auxShortArrayW[5]);
        GOTOFAILURE_GPS
    }

    /*-- GPSHPOSITIONINGERROR - new tag for EXIF 2.31 --*/
    if (!TIFFGetField(tif, GPSTAG_GPSHPOSITIONINGERROR, &auxDblUnion.dbl))
    {
        fprintf(stderr, "Can't read GPSTAG_GPSHPOSITIONINGERROR\n");
        GOTOFAILURE_GPS
    }
    if (blnIsRational2Double)
    {
        /* New interface allows also double precision for TIFF_RATIONAL */
        auxDouble = auxDblUnion.dbl;
    }
    else
    {
        /* Old interface reads TIFF_RATIONAL defined as TIFF_SETGET_DOUBLE
         * always as FLOAT */
        auxDouble = (double)auxDblUnion.flt1;
    }
    /* compare read values with written ones */
    auxFloat = (float)GPSHPOSITIONINGERROR_VAL;
    dblDiffLimit = RATIONAL_EPS * auxFloat;
    dblDiff = auxDouble - auxFloat;
    if (fabs(dblDiff) > fabs(dblDiffLimit))
    {
        fprintf(stderr,
                "Read value of GPSTAG_GPSHPOSITIONINGERROR %f differs from set "
                "value %f\n",
                auxDouble, auxFloat);
        GOTOFAILURE_GPS
    }

    /*===============  END reading GPS tags ==========================*/
#endif /*-- READ_GPS_TAGS --*/

    /*================== Reading EXIF 2.31 tags =====================*/

    /*--- Firstly, get EXIF directory offset from main directory. */

    /*-- Go back to the first (main) directory, and get value of the EXIFIFD
     * directory- offset.  */
    /*   (directory is reloaded from file!) */
    TIFFSetDirectory(tif, 0);
    retCode = TIFFGetField(tif, TIFFTAG_EXIFIFD, &read_dir_offset);

#ifdef READ_EXIF_TAGS
    /*-- Now read EXIF directory from file into memory --*/
    retCode = TIFFReadEXIFDirectory(tif, read_dir_offset);

    /*-- Now get some parameters from EXIF-directory (already read into memory)
     * --*/
    retCode = TIFFGetField(tif, EXIFTAG_EXIFVERSION, &pAscii);

#ifdef READ_ALL_EXIF_TAGS
    /*-- Get array, where EXIF tag fields are defined --*/
    tFieldArray = _TIFFGetExifFields();
    nTags = tFieldArray->count;
    /*-- Check, if the TiffLibrary is compiled with the new interface with
     * Rational2Double or still uses the old definitions. */
    /* tif points to EXIF tags, so TIFFFindField() can only access the EXIF tag
     * fields */
    fip = TIFFFindField(tif, EXIFTAG_EXPOSURETIME, TIFF_ANY);
    tSetFieldType = fip->set_field_type;
    if (tSetFieldType == TIFF_SETGET_DOUBLE)
    {
        blnIsRational2Double = FALSE;
        fprintf(stderr, "-- EXIF tags read with standard --\n");
    }
    else
    {
        blnIsRational2Double = TRUE;
        fprintf(stderr,
                "-- Rational2Double for reading EXIF tags detected --\n");
    }

    for (i = 0; i < nTags; i++)
    {
        bool deferredSetField = false;
        tTag = tFieldArray->fields[i].field_tag;
        tType = tFieldArray->fields[i].field_type; /* e.g. TIFF_RATIONAL */
        tWriteCount = tFieldArray->fields[i].field_writecount;
        tSetFieldType = tFieldArray->fields[i]
                            .set_field_type; /* e.g. TIFF_SETGET_C0_FLOAT */
        tFieldName = tFieldArray->fields[i].field_name;

        /*-- dependent on set_field_type read value --*/
        switch (tSetFieldType)
        {
            case TIFF_SETGET_ASCII:
                /* Either the stringlength is defined as a fixed length in
                 * .field_writecount or a NULL-terminated string is used. */
                if (!TIFFGetField(tif, tTag, &pAscii))
                {
                    fprintf(stderr, "Can't read %s\n",
                            tFieldArray->fields[i].field_name);
                    GOTOFAILURE_ALL_EXIF
                    break;
                }
                /* Save string from temporary buffer and compare with written
                 * string. */
                strncpy(auxCharArray, pAscii, sizeof(auxCharArray) - 1u);
                auxCharArray[sizeof(auxCharArray) - 1u] = '\0';
                if (tWriteCount > 0)
                    auxInt32 = tWriteCount - 1;
                else
                    auxInt32 = (int32_t)strlen(auxCharArray);
                retCode2 = strncmp(auxCharArray, auxTextArrayW[i], auxInt32);
                if (retCode2 != 0)
                {
                    fprintf(
                        stderr,
                        "%d:Read value of %s %s differs from set value %s\n", i,
                        tFieldName, auxCharArray, auxTextArrayW[i]);
                    GOTOFAILURE_ALL_EXIF
                }
                break;
                /*-- For reading, the parameter size is to be observed !! */
            case TIFF_SETGET_UINT8:
            case TIFF_SETGET_SINT8:
                if (!TIFFGetField(tif, tTag, &auxChar))
                {
                    fprintf(stderr, "Can't read %s\n",
                            tFieldArray->fields[i].field_name);
                    GOTOFAILURE_ALL_EXIF
                    break;
                }
                /* compare read values with written ones */
                auxInt32 = auxChar;
                if (auxInt32 != (char)auxInt32ArrayW[i])
                {
                    fprintf(
                        stderr,
                        "%d:Read value of %s %d differs from set value %d\n", i,
                        tFieldName, auxInt32, auxInt32ArrayW[i]);
                }
                break;
            case TIFF_SETGET_UINT16:
            case TIFF_SETGET_SINT16:
                if (!TIFFGetField(tif, tTag, &auxShort))
                {
                    fprintf(stderr, "Can't read %s\n",
                            tFieldArray->fields[i].field_name);
                    GOTOFAILURE_ALL_EXIF
                    break;
                }
                /* compare read values with written ones */
                auxInt32 = auxShort;
                if (auxInt32 != (short)auxInt32ArrayW[i])
                {
                    fprintf(
                        stderr,
                        "%d:Read value of %s %d differs from set value %d\n", i,
                        tFieldName, auxInt32, auxInt32ArrayW[i]);
                }
                break;
            case TIFF_SETGET_UINT32:
            case TIFF_SETGET_SINT32:
            case TIFF_SETGET_IFD8:
            case TIFF_SETGET_INT:
                if (!TIFFGetField(tif, tTag, &auxUint32))
                {
                    fprintf(stderr, "Can't read %s\n",
                            tFieldArray->fields[i].field_name);
                    GOTOFAILURE_ALL_EXIF
                    break;
                }
                /* compare read values with written ones */
                auxInt32 = auxUint32;
                if (auxInt32 != auxInt32ArrayW[i])
                {
                    fprintf(
                        stderr,
                        "%d:Read value of %s %d differs from set value %d\n", i,
                        tFieldName, auxInt32, auxInt32ArrayW[i]);
                }
                break;
            case TIFF_SETGET_FLOAT:
                if (!TIFFGetField(tif, tTag, &auxFloat))
                {
                    fprintf(stderr, "Can't read %s\n",
                            tFieldArray->fields[i].field_name);
                    GOTOFAILURE_ALL_EXIF
                    break;
                }
                /* compare read values with written ones */
                if (tType == TIFF_RATIONAL || tType == TIFF_SRATIONAL)
                    dblDiffLimit = RATIONAL_EPS * auxDoubleArrayW[i];
                else
                    dblDiffLimit = 1e-6;
                dblDiff = auxFloat - auxDoubleArrayW[i];
                if (fabs(dblDiff) > fabs(dblDiffLimit))
                {
                    /*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of
                     * "-1.0" if numerator equals 4294967295 (0xFFFFFFFF) to
                     * indicate infinite distance! However, there are two other
                     * EXIF tags where numerator indicates a special value and
                     * six other cases where the denominator indicates special
                     * values, which are not treated within LibTiff!!
                     */
                    if (!(tTag == EXIFTAG_SUBJECTDISTANCE && auxFloat == -1.0))
                    {
                        fprintf(stderr,
                                "%d:Read value of %s %f differs from set value "
                                "%f\n",
                                i, tFieldName, auxFloat, auxDoubleArrayW[i]);
                        GOTOFAILURE_ALL_EXIF
                    }
                }
                break;
            case TIFF_SETGET_DOUBLE:
                /*-- Unfortunately, TIFF_SETGET_DOUBLE is used for TIFF_RATIONAL
                 * but those have to be read with FLOAT !!! */
                /*   Only TIFFTAG_STONITS is a TIFF_DOUBLE, which has to be read
                 * as DOUBLE!! */
                /*-- ATTENTION: ----
                 *   Only after update with Rational2Double feature, also
                 TIFF_RATIONAL can be read in double precision!!!
                 *   Therefore, use a union to avoid overflow in TIFFGetField()
                 return value
                 *   and depending on version check for the right interface
                 here:
                 *   - old interface:  correct value should be here a float
                 *   - new interface:  correct value should be here a double
                 *   Interface version (old/new) is determined above.
                 -------------------*/
                if (!TIFFGetField(tif, tTag, &auxDblUnion.dbl))
                {
                    fprintf(stderr, "Can't read %s\n",
                            tFieldArray->fields[i].field_name);
                    GOTOFAILURE_ALL_EXIF
                    break;
                }
                if (tType == TIFF_RATIONAL || tType == TIFF_SRATIONAL)
                {
                    if (blnIsRational2Double)
                    {
                        /* New interface allows also double precision for
                         * TIFF_RATIONAL */
                        auxDouble = auxDblUnion.dbl;
                    }
                    else
                    {
                        /* Old interface reads TIFF_RATIONAL defined as
                         * TIFF_SETGET_DOUBLE always as FLOAT */
                        auxDouble = (double)auxDblUnion.flt1;
                    }
                }
                else
                {
                    auxDouble = auxDblUnion.dbl;
                }
                /* compare read values with written ones */
                if (tType == TIFF_RATIONAL || tType == TIFF_SRATIONAL)
                    dblDiffLimit = RATIONAL_EPS * auxDoubleArrayW[i];
                else
                    dblDiffLimit = 1e-6;
                dblDiff = auxDouble - auxDoubleArrayW[i];
                if (fabs(dblDiff) > fabs(dblDiffLimit))
                {
                    /*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of
                     * "-1.0" if numerator equals 4294967295 (0xFFFFFFFF) to
                     * indicate infinite distance! */
                    if (!(tTag == EXIFTAG_SUBJECTDISTANCE && auxDouble == -1.0))
                    {
                        fprintf(stderr,
                                "%d:Read value of %s %f differs from set value "
                                "%f\n",
                                i, tFieldName, auxDouble, auxDoubleArrayW[i]);
                        GOTOFAILURE_ALL_EXIF
                    }
                }
                break;

            case TIFF_SETGET_C0_FLOAT:
            case TIFF_SETGET_C0_DOUBLE:
            case TIFF_SETGET_C16_FLOAT:
            case TIFF_SETGET_C16_DOUBLE:
            case TIFF_SETGET_C32_FLOAT:
            case TIFF_SETGET_C32_DOUBLE:
                /* _Cxx_ just defines the size of the count parameter for the
                 * array as C0=char, C16=short or C32=long */
                /*-- Check, if it is a single parameter, a fixed array or a
                 * variable array */
                if (tWriteCount == 1)
                {
                    fprintf(stderr,
                            "Reading: WriteCount for .set_field_type %d should "
                            "be -1 or greater than 1!  %s\n",
                            tSetFieldType, tFieldArray->fields[i].field_name);
                }
                else
                {
                    /*-- Either fix or variable array --*/
                    /* For arrays, distinguishing between float or double is
                     * essential. */
                    /* Now decide between fixed or variable array */
                    if (tWriteCount > 1)
                    {
                        /* fixed array with needed arraysize defined in
                         * .field_writecount */
                        if (!TIFFGetField(tif, tTag, &pVoidArray))
                        {
                            fprintf(stderr, "Can't read %s\n",
                                    tFieldArray->fields[i].field_name);
                            GOTOFAILURE_ALL_EXIF
                            break;
                        }
                        /* set tWriteCount to number of read samples for next
                         * steps */
                        auxInt32 = tWriteCount;
                    }
                    else
                    {
                        /* Special treatment of variable array. */
                        /* Dependent on Cxx, the count parameter is char, short
                         * or long. Therefore use unionInt32! */
                        if (!TIFFGetField(tif, tTag, &unionInt32, &pVoidArray))
                        {
                            fprintf(stderr, "Can't read %s\n",
                                    tFieldArray->fields[i].field_name);
                            GOTOFAILURE_ALL_EXIF
                            break;
                        }
                        /* set tWriteCount to number of read samples for next
                         * steps */
                        auxInt32 = unionInt32.Short1;
                    }
                    /* Save values from temporary array */
                    if (tSetFieldType == TIFF_SETGET_C0_FLOAT ||
                        tSetFieldType == TIFF_SETGET_C16_FLOAT ||
                        tSetFieldType == TIFF_SETGET_C32_FLOAT)
                    {
                        memcpy(&auxFloatArray, pVoidArray,
                               (auxInt32 * sizeof(auxFloatArray[0])));
                        /* compare read values with written ones */
                        if (tType == TIFF_RATIONAL || tType == TIFF_SRATIONAL)
                            dblDiffLimit = RATIONAL_EPS * auxDoubleArrayW[i];
                        else
                            dblDiffLimit = 1e-6;
                        for (j = 0; j < auxInt32; j++)
                        {
                            dblDiff = auxFloatArray[j] - auxFloatArrayW[i + j];
                            if (fabs(dblDiff) > fabs(dblDiffLimit))
                            {
                                /*if (auxFloatArray[j] !=
                                 * (float)auxFloatArrayW[i+j]) { */
                                fprintf(stderr,
                                        "Read value %d of %s #%d %f differs "
                                        "from set value %f\n",
                                        i, tFieldName, j, auxFloatArray[j],
                                        auxFloatArrayW[i + j]);
                                GOTOFAILURE_ALL_EXIF
                            }
                        }
                    }
                    else
                    {
                        memcpy(&auxDoubleArray, pVoidArray,
                               (auxInt32 * sizeof(auxDoubleArray[0])));
                        /* compare read values with written ones */
                        if (tType == TIFF_RATIONAL || tType == TIFF_SRATIONAL)
                            dblDiffLimit = RATIONAL_EPS * auxDoubleArrayW[i];
                        else
                            dblDiffLimit = 1e-6;
                        for (j = 0; j < auxInt32; j++)
                        {
                            dblDiff =
                                auxDoubleArray[j] - auxDoubleArrayW[i + j];
                            if (fabs(dblDiff) > fabs(dblDiffLimit))
                            {
                                /*if (auxDoubleArray[j] != auxDoubleArrayW[i+j])
                                 * { */
                                fprintf(stderr,
                                        "Read value %d of %s #%d %f differs "
                                        "from set value %f\n",
                                        i, tFieldName, j, auxDoubleArray[j],
                                        auxDoubleArrayW[i + j]);
                                GOTOFAILURE_ALL_EXIF
                            }
                        }
                    }
                }
                break;
            case TIFF_SETGET_C0_UINT8:
            case TIFF_SETGET_C0_SINT8:
            case TIFF_SETGET_C16_UINT8:
            case TIFF_SETGET_C16_SINT8:
            case TIFF_SETGET_C32_UINT8:
            case TIFF_SETGET_C32_SINT8:
                /* For arrays, distinguishing between float or double is
                 * essential, even for writing */
                deferredSetField = true;
                break;
            case TIFF_SETGET_C0_UINT16:
            case TIFF_SETGET_C0_SINT16:
            case TIFF_SETGET_C16_UINT16:
            case TIFF_SETGET_C16_SINT16:
            case TIFF_SETGET_C32_UINT16:
            case TIFF_SETGET_C32_SINT16:
                deferredSetField = true;
                break;
            case TIFF_SETGET_C0_UINT32:
            case TIFF_SETGET_C0_SINT32:
            case TIFF_SETGET_C16_UINT32:
            case TIFF_SETGET_C16_SINT32:
            case TIFF_SETGET_C32_UINT32:
            case TIFF_SETGET_C32_SINT32:
                deferredSetField = true;
                break;
            default:
                fprintf(stderr,
                        "SetFieldType %d not defined within writing switch for "
                        "%s.\n",
                        tSetFieldType, tFieldName);
                GOTOFAILURE
        }; /*-- switch() --*/

        if (deferredSetField)
        {
            /* _Cxx_ just defines the size of the count parameter for the array
             * as C0=char, C16=short or C32=long */
            /*-- Check, if it is a single parameter, a fixed array or a variable
             * array */
            if (tWriteCount == 1)
            {
                fprintf(stderr,
                        "WriteCount for .set_field_type %d should be -1 or "
                        "greater than 1!  %s\n",
                        tSetFieldType, tFieldArray->fields[i].field_name);
            }
            else
            {
                /*-- Either fix or variable array --*/
                /* Now decide between fixed or variable array */
                if (tWriteCount > 1)
                {
                    /* fixed array with needed arraysize defined in
                     * .field_writecount */
                    if (!TIFFGetField(tif, tTag, &pVoidArray))
                    {
                        fprintf(stderr, "Can't read %s\n",
                                tFieldArray->fields[i].field_name);
                        GOTOFAILURE_ALL_EXIF
                        break;
                    }
                    /* set tWriteCount to number of read samples for next steps
                     */
                    auxInt32 = tWriteCount;
                }
                else
                {
                    /* special treatment of variable array */
                    /* for test, use always arraysize of VARIABLE_ARRAY_SIZE */
                    if (!TIFFGetField(tif, tTag, &unionInt32, &pVoidArray))
                    {
                        fprintf(stderr, "Can't read %s\n",
                                tFieldArray->fields[i].field_name);
                        GOTOFAILURE_ALL_EXIF
                        break;
                    }
                    /* set tWriteCount to number of read samples for next steps
                     */
                    auxInt32 = unionInt32.Short1;
                }
                /* Save values from temporary array */
                if (tSetFieldType == TIFF_SETGET_C0_UINT8 ||
                    tSetFieldType == TIFF_SETGET_C0_SINT8 ||
                    tSetFieldType == TIFF_SETGET_C16_UINT8 ||
                    tSetFieldType == TIFF_SETGET_C16_SINT8 ||
                    tSetFieldType == TIFF_SETGET_C32_UINT8 ||
                    tSetFieldType == TIFF_SETGET_C32_SINT8)
                {
                    memcpy(&auxCharArray, pVoidArray,
                           (auxInt32 * sizeof(auxCharArray[0])));
                    /* Compare and check values  */
                    for (j = 0; j < auxInt32; j++)
                    {
                        if (tTag == EXIFTAG_EXIFVERSION)
                        {
                            /*-- Use exifVersion[] instead of auxCharArrayW[]
                             * for differently set EXIFVERSION tag */
                            if (auxCharArray[j] != exifVersion[j])
                            {
                                fprintf(stderr,
                                        "Read value %d of %s #%d %d differs "
                                        "from set value %d\n",
                                        i, tFieldName, j, auxCharArray[j],
                                        auxCharArrayW[i + j]);
                                GOTOFAILURE_ALL_EXIF
                            }
                        }
                        else
                        {
                            if (auxCharArray[j] != auxCharArrayW[i + j])
                            {
                                fprintf(stderr,
                                        "Read value %d of %s #%d %d differs "
                                        "from set value %d\n",
                                        i, tFieldName, j, auxCharArray[j],
                                        auxCharArrayW[i + j]);
                                GOTOFAILURE_ALL_EXIF
                            }
                        }
                    }
                }
                else if (tSetFieldType == TIFF_SETGET_C0_UINT16 ||
                         tSetFieldType == TIFF_SETGET_C0_SINT16 ||
                         tSetFieldType == TIFF_SETGET_C16_UINT16 ||
                         tSetFieldType == TIFF_SETGET_C16_SINT16 ||
                         tSetFieldType == TIFF_SETGET_C32_UINT16 ||
                         tSetFieldType == TIFF_SETGET_C32_SINT16)
                {
                    memcpy(&auxShortArray, pVoidArray,
                           (auxInt32 * sizeof(auxShortArray[0])));
                    /* Compare and check values  */
                    for (j = 0; j < auxInt32; j++)
                    {
                        if (auxShortArray[j] != auxShortArrayW[i + j])
                        {
                            fprintf(stderr,
                                    "Read value %d of %s #%d %d differs from "
                                    "set value %d\n",
                                    i, tFieldName, j, auxShortArray[j],
                                    auxShortArrayW[i + j]);
                            GOTOFAILURE_ALL_EXIF
                        }
                    }
                }
                else if (tSetFieldType == TIFF_SETGET_C0_UINT32 ||
                         tSetFieldType == TIFF_SETGET_C0_SINT32 ||
                         tSetFieldType == TIFF_SETGET_C16_UINT32 ||
                         tSetFieldType == TIFF_SETGET_C16_SINT32 ||
                         tSetFieldType == TIFF_SETGET_C32_UINT32 ||
                         tSetFieldType == TIFF_SETGET_C32_SINT32)
                {
                    memcpy(&auxInt32Array, pVoidArray,
                           (auxInt32 * sizeof(auxInt32Array[0])));
                    /* Compare and check values  */
                    for (j = 0; j < auxInt32; j++)
                    {
                        if (auxInt32Array[j] != auxInt32ArrayW[i + j])
                        {
                            fprintf(stderr,
                                    "Read value %d of %s #%d %d differs from "
                                    "set value %d\n",
                                    i, tFieldName, j, auxInt32Array[j],
                                    auxInt32ArrayW[i + j]);
                            GOTOFAILURE_ALL_EXIF
                        }
                    }
                }
                else
                {
                    fprintf(stderr,
                            "SetFieldType %d not defined within switch case "
                            "reading for UINT for %s.\n",
                            tSetFieldType, tFieldName);
                    GOTOFAILURE
                }
            }
        }
    } /*-- for() --*/
    /*================= EXIF: END Reading arbitrary data to the EXIF fields END
     * END END ==============*/
#endif /*-- READ_ALL_EXIF_TAGS --*/
#endif /*-- READ_EXIF_TAGS --*/

    TIFFClose(tif);

    /* All tests passed; delete file and exit with success status. */
#ifdef FOR_AUTO_TESTING
    unlink(filenameRead);
#endif
    fprintf(stderr, "-------- Test finished OK ----------\n");
    return 0;

failure:
    /*
     * Something goes wrong; close file and return unsuccessful status.
     * Do not remove the file for further manual investigation.
     */
    TIFFClose(tif);
    fprintf(stderr, "-------- Test finished with FAILURE --------\n");
    return 1;
}
