Question

Je suis assez nouveau à Libtiff, mais j'ai réussi à obtenir des fichiers TIFF sauvegarder et ouvrir sans trop de problèmes.

Maintenant, je suis ambitieux et j'essaie d'ajouter des balises personnalisées dans mes fichiers.J'ai Lisez la documentation ( voir ici ) et écrit du code de test qui compile sans erreurs, mais échoue au moment de l'exécution avec une violation d'accès au premier appel à Tiffsetfield qui comporte un champ personnalisé (appels à Tiffsetfield avec Les champs standard vont bien).

Mon code de test suit: Un peu moins de 100 lignes, avec le seul externe dépendance (en plus de libtiff) étant mon code pour ouvrir une image de test d'un fichier .pgm.Quelqu'un peut-il souligner ce que je fais mal?Au fait, j'utilise libtiff 4.0.3.

#include "stdafx.h"
#include "PGM.h"      // Just for reading in the test image
#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[] = {
    { 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 void registerCustomTIFFTags(TIFF *tif)
{
    /* Install the extended Tag field info */
    TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
}

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 = TIFFOpen(filename, "w");

    // 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; if we comment out this next block then everything
    // works as it should and we successfully save the image:
    registerCustomTIFFTags(tif);
    TIFFSetField(tif, TIFFTAG_INCIDENTPOWER, Power1);   // Access violation here
    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 = nullptr;

    // Information we'd like to put into our custom tags:
    int Power1 = 1000000;
    int Power2 = 8;
    float T1 = 23.5f;
    float T2 = -18.7f;
    float Humidity = 0.98f;
    float Exposure = 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;
}

Était-ce utile?

La solution

Après quelques conseils d'un gentleman aimable appelé Paul Heckbert sur la liste de diffusion des utilisateurs TIFF, voici le code qui a finalement fonctionné pour moi.Il y avait deux clés:

(1) définissant correctement les champs TIFFFFIEDINFO correctement, de manière différente de l'exemple donné dans la documentation. (2) Utilisation du modèle "Extender" pour encapsuler l'appel à tiffmergefieldinfo, mais ce avant ouvrir le fichier.Si j'ai quitté l'appel jusqu'à l'ouverture du fichier, alors lors de la lecture d'un fichier avec des balises personnalisées, un certain nombre de messages "AVERTISSEMENT, FILE INCONNUS" seront publiés immédiatement lors de l'ouverture du fichier.

Voici le 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[] = {
        { TIFFTAG_INCIDENTPOWER,  1, 1, TIFF_LONG,  FIELD_CUSTOM, 0, 0, const_cast<char*>("LaserIncidentPower") },
        { TIFFTAG_REFLECTEDPOWER, 1, 1, TIFF_LONG,  FIELD_CUSTOM, 0, 0, const_cast<char*>("LaserReflectedPower") },
        { TIFFTAG_T1,             1, 1, TIFF_FLOAT, FIELD_CUSTOM, 0, 0, const_cast<char*>("Temperature_1") },
        { TIFFTAG_T2,             1, 1, TIFF_FLOAT, FIELD_CUSTOM, 0, 0, const_cast<char*>("Temperature_2") },
        { TIFFTAG_HUMIDITY,       1, 1, TIFF_FLOAT, FIELD_CUSTOM, 0, 0, const_cast<char*>("Humidity") },
        { TIFFTAG_EXPOSURE,       1, 1, TIFF_FLOAT, FIELD_CUSTOM, 0, 0, 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 = NULL;  // In case we want a chain of extensions

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

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

static void augment_libtiff_with_custom_tags() {
    static bool first_time = true;
    if (!first_time) return;
    first_time = false;
    parent_extender = 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:
    augment_libtiff_with_custom_tags();
    TIFF* tif = TIFFOpen(filename, "w");

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

void readFromTiff(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:
    augment_libtiff_with_custom_tags();
    TIFF* tif = TIFFOpen(filename, "r");
    if (NULL == tif)
    {
        *nx = -1;
        *ny = -1;
        return;
    }

    // Read in the image size and metadata:
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, nx);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, ny);
    TIFFGetField(tif, TIFFTAG_INCIDENTPOWER, Power1);
    TIFFGetField(tif, TIFFTAG_REFLECTEDPOWER, Power2);
    TIFFGetField(tif, TIFFTAG_T1, T1);
    TIFFGetField(tif, TIFFTAG_T2, T2);
    TIFFGetField(tif, TIFFTAG_HUMIDITY, Humidity);
    TIFFGetField(tif, TIFFTAG_EXPOSURE, Exposure);

    // Dimension the buffer, and read in the image data itself:
    *image = new unsigned short[(*nx) * (*ny)];
    TIFFReadEncodedStrip(tif, static_cast<tstrip_t>(0), static_cast<void *>(*image), static_cast<tsize_t>(-1));
    TIFFClose(tif);
}

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

    // Information we'd like to put into our custom tags:
    int Power1 = 1000000;
    int Power2 = 8;
    float T1 = 23.5f;
    float T2 = -18.7f;
    float Humidity = 0.98f;
    float Exposure = 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);

    // Prepare to read back in: first clear the various fields
    Power1 = 0;
    Power2 = 0;
    T1 = 0.0f;
    T2 = 0.0f;
    Humidity = 0.0f;
    Exposure = 0.0f;
    nx = 0;
    ny = 0;
    delete [] image;

    readFromTiff(&nx, &ny, &image, "TestImage.tif", &Power1, &Power2, &T1, &T2, &Humidity, &Exposure);

    printf("Image size = %d, %d\r\n", ny, ny);
    printf("Power1 = %d\r\n", Power1);
    printf("Power2 = %d\r\n", Power2);
    printf("T1 = %6.3f\r\n", T1);
    printf("T2 = %6.3f\r\n", T2);
    printf("Humidity = %6.3f\r\n", Humidity);
    printf("Exposure = %6.3f\r\n", Exposure);
    return 0;
}

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top