Проблема при попытке обновить теги на изображении в формате TIFF

Примечание. При создании нового изображения в формате tiff, которое никогда не изменялось библиотекой LibTiff.Net, я могу использовать библиотеку LibTiff.Net для добавления/изменения тегов без проблем (в первый раз).

После того, как я использовал библиотеку LibTiff.Net для изменения тегов tiff, когда я пытаюсь изменить их во второй раз, изображение становится поврежденным. Теги кажутся в порядке, но само изображение отображается как черное изображение (повреждено).

В настоящее время это мой расширитель тегов, используемый в моем классе...

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

И это в настоящее время моя функция, используемая для установки тегов tiff для данного 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;
}

person Arvo Bowen    schedule 11.08.2012    source источник


Ответы (1)


Беглый взгляд на ваш код заставляет меня думать, что причиной проблемы является вызов tImage.CheckpointDirectory();

С помощью этого вызова вы эффективно записываете данные каталога в файл, не обращая внимания на то, что там уже может быть помещено.

Я предполагаю, что рано или поздно каталог, записываемый вызовом CheckpointDirectory, начинает занимать больше места, чем было ранее отведено под данные каталога в файле, и начало растровых данных перезаписывается.

Попробуйте использовать RewriteDirectory метод вместо этого.

person Bobrovsky    schedule 20.08.2012
comment
Как обычно, Бобровский - мой герой LibTiff.Net!!! Большое спасибо за то, что показали мне простое решение. Совершенно логично, я просто не знал, что такой метод вообще существует. ;) - person Arvo Bowen; 20.08.2012