Question

Note: When creating a new tiff image that has never been altered by the LibTiff.Net library, I can use the LibTiff.Net library to add/alter tags with no issues (the first time).

After I have used the LibTiff.Net library to alter the tiff tags in anyway, when I try to alter them a second time the image becomes corrupt. The tags seem to be fine but the image itself shows up as a black image (corrupt).

This is currently my tag extender used in my class...

private static Tiff.TiffExtendProc m_parentExtender;
private static List<TIFFTAGS_TAG> m_lTagsToWrite;

private static void TagExtender(Tiff tif)
{
    List<TiffFieldInfo> tfInfo = new List<TiffFieldInfo>();
    Int16 readCount = 0;
    Int16 writeCount = 0;
    bool okToChange = false;
    bool passCount = false;

    //Make sure to create a new tiff field info for all the tags to be written
    foreach (TIFFTAGS_TAG ttTag in m_lTagsToWrite)
    {
        switch (ttTag.TagType)
        {
            case TIFFTAGS_TAG_DATATYPE.ASCII:
                readCount = -1;
                writeCount = -1;
                okToChange = true;
                passCount = false;

                break;
            case TIFFTAGS_TAG_DATATYPE.LONG:
            case TIFFTAGS_TAG_DATATYPE.RATIONAL:
            case TIFFTAGS_TAG_DATATYPE.SHORT:
                readCount = 2;
                writeCount = 2;
                okToChange = false;
                passCount = true;

                break;
        }

        if (ttTag.TagType != TIFFTAGS_TAG_DATATYPE.UNKNOWN)
        {
            //Add the new item to the list
            tfInfo.Add(new TiffFieldInfo((TiffTag)ttTag.TagNumber, readCount, writeCount, (TiffType)ttTag.TagType, FieldBit.Custom, okToChange, passCount, ttTag.TagName));
        }
    }

    //Turn the list into an array again
    TiffFieldInfo[] tfInfoArray = tfInfo.ToArray();

    //Add the fields to the main field info area
    tif.MergeFieldInfo(tfInfoArray, tfInfoArray.Length);

    //Propergate the chain if needed
    if (m_parentExtender != null)
        m_parentExtender(tif);
}

And this is currently my function used to set tiff tags on a given tiff

public static bool SetTiffTags(string sFileName, List<TIFFTAGS_TAG> ttTagsInfo)
{
    //Sets all the tiff tags in the image given.
    //Returns true if successful or false if error occured

    //Check if the file exists
    if (!File.Exists(sFileName))
    {
        //File does not exist
        return false;
    }

    try
    {
        //Set the tag info so that it can be carried over to the extender callback
        m_lTagsToWrite = new List<TIFFTAGS_TAG>();
        m_parentExtender = Tiff.SetTagExtender(TagExtender);
        m_lTagsToWrite = ttTagsInfo;

        using (Tiff tImage = Tiff.Open(sFileName, "a"))
        {
            if (tImage != null)
            {
                //Go to the first page
                tImage.SetDirectory(0);

                foreach (TIFFTAGS_TAG ttTag in ttTagsInfo)
                {
                    switch (ttTag.TagType)
                    {
                        case TIFFTAGS_TAG_DATATYPE.ASCII:
                            try
                            {
                                //string
                                string sValue = ttTag.Value.ToString();
                                tImage.SetField((TiffTag)ttTag.TagNumber, sValue);
                            }
                            catch
                            {
                                //Could not convert to a string
                                return false;
                            }
                            break;
                        case TIFFTAGS_TAG_DATATYPE.LONG:
                            try
                            {
                                //long
                                int[] iValues;
                                if (ttTag.Value.GetType().ToString() == "System.Int32")
                                {
                                    iValues = new int[] { (int)ttTag.Value };
                                }
                                else if (ttTag.Value.GetType().ToString() == "System.Int32[]")
                                {
                                    iValues = (int[])ttTag.Value;
                                }
                                else return false;
                                tImage.SetField((TiffTag)ttTag.TagNumber, iValues.Count(), iValues);
                            }
                            catch
                            {
                                //Could not convert to a long
                                return false;
                            }
                            break;
                        case TIFFTAGS_TAG_DATATYPE.SHORT:
                            try
                            {
                                //short
                                Int16[] iValues;
                                if (ttTag.Value.GetType().ToString() == "System.Int16")
                                {
                                    iValues = new Int16[] { (Int16)ttTag.Value };
                                }
                                else if (ttTag.Value.GetType().ToString() == "System.Int16[]")
                                {
                                    iValues = (Int16[])ttTag.Value;
                                }
                                else return false;
                                tImage.SetField((TiffTag)ttTag.TagNumber, iValues.Count(), iValues);
                            }
                            catch
                            {
                                //Could not convert to a short
                                return false;
                            }
                            break;
                        case TIFFTAGS_TAG_DATATYPE.RATIONAL:
                            try
                            {
                                //float
                                Single[] iValues;
                                if (ttTag.Value.GetType().ToString() == "System.Single")
                                {
                                    iValues = new Single[] { (Single)ttTag.Value };
                                }
                                else if (ttTag.Value.GetType().ToString() == "System.Single[]")
                                {
                                    iValues = (Single[])ttTag.Value;
                                }
                                else return false;
                                tImage.SetField((TiffTag)ttTag.TagNumber, iValues.Count(), iValues);
                            }
                            catch
                            {
                                //Could not convert to a single
                                return false;
                            }
                            break;
                        default:
                            //This type of tag is not supported so error out
                            return false;
                    }
                }

                //Write the information to the tiff
                tImage.CheckpointDirectory();
            }
            else
            {
                //Restore previous tag extender
                Tiff.SetTagExtender(m_parentExtender);

                return false;
            }
        }

        //Restore previous tag extender
        Tiff.SetTagExtender(m_parentExtender);
    }
    catch
    {
        //Restore previous tag extender
        Tiff.SetTagExtender(m_parentExtender);

        return false;
    }

    //Return success
    return true;
}
Was it helpful?

Solution

Quick look at your code makes me think that the cause of the issue is call to tImage.CheckpointDirectory();

With this call you effectively write directory data to the file without any respect to what might be already put there.

I guess that sooner or later the directory being written by the call to CheckpointDirectory starts to occupy more space than was previously allocated for the directory data in a file and beginning of raster data gets overwritten.

Please try using RewriteDirectory method instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top