Как я могу удалить теги tiff с помощью библиотеки LibTiff.Net 2.3

Кажется, я не могу найти документацию о том, как удалить тег tiff с помощью библиотеки LibTiff.Net. Мне нравится библиотека, но этот метод важен для того, что мне нужно делать. В какой-то момент я надеялся, что смогу просто установить тег и установить его значение равным нулю. Я надеялся, что это сработает, но это был минус.

Кто-нибудь знает, как удалить тег tiff с помощью библиотеки LibTiff.Net?


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


Ответы (3)


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

LibTiff.Net не предлагает методов удаления тегов (то же самое верно и для LibTiff). Для этого вам потребуется реализовать часть функциональности TiffCP.

По сути, вам нужно будет скопировать все теги, которые вы хотите сохранить, и скопировать данные пикселей без их декодирования и повторного кодирования.

Также ознакомьтесь с Преобразование многополосного изображения TIFF в один -зачистите один образец. В нем показано, как копировать теги и копировать необработанные (незакодированные данные) из одного изображения в другое. Образец фактически декодирует данные в некоторых случаях, потому что ему нужно изменить количество полос, но вам не нужно декодировать данные.

person Bobrovsky    schedule 24.02.2012
comment
Ух ты! Это похоже именно на то, что мне нужно. Я бы предпочел иметь дело с открытыми методами, чем копаться в частных. Большое спасибо за указание на Бобровского! И я только что получил право голоса... Угадай, где я использую свой первый голос? ;) - person Arvo Bowen; 24.02.2012

Я думаю, вам придется скопировать входной файл в новое изображение TIFF, отфильтровав теги, которые вам не нужны в процессе. Взгляните на утилиту tiffcp, которая является частью обычного дистрибутива libtiff. Это как бы делает это, минус фильтрация.

Отказ от ответственности: я никогда не использовал LibTiff.Net и предполагаю, что он очень похож на LibTiff.

Взгляните на tiffcp.c

Сначала он вручную копирует/устанавливает некоторые известные теги, такие как разрешение, сжатие, цвета и т. д. Затем он копирует весь набор тегов, который можно скопировать без предварительной обработки:

for (p = tags; p < &tags[NTAGS]; p++)
    CopyTag(p->tag, p->count, p->type);

Затем он копирует фактические данные пикселей. Насколько я помню, это приведет к удалению любых тегов, которые не известны tiffcp. Если ваш тег, который вы хотите удалить, находится в списке, вы можете тривиально удалить его, удалив его из этого списка.

person MK.    schedule 24.02.2012
comment
Фильтрующая часть является ключевой. Я не уверен, как бы я это сделал. Посмотрел tiffcp.exe, и кажется, что он просто копирует tiff с другим типом сжатия и т. Д. - person Arvo Bowen; 24.02.2012
comment
Вы должны смотреть на исходный код, а не на exe? Я обновил ответ выше с некоторыми деталями. - person MK.; 24.02.2012
comment
Спасибо, МК, сейчас изучаю код С#. Нашел область, похожую на ту, что вы разместили в c. Время копаться в этом. ;) - person Arvo Bowen; 24.02.2012

Примечание. Поначалу это может выглядеть как большой ответ, но я хотел убедиться, что тот, кто смотрит на это, видит все «собственные классы, которые я создал, чтобы все было упаковано для чистоты. В интересах сохранения ответа в таком виде, как возможно и для большей информативности я вставлю только код метода DeleteTiffTags. Остальной код можно скачать через здесь.

Теперь о хороших вещах... В итоге я потратил около дня на то, чтобы это произошло, и это стало возможным благодаря различным вопросам, на которые ответило большое сообщество stackoverflow. Я написал два маленьких (очень подробных) метода в одном из своих классов, чтобы удалить тег tiff. Первый предназначен для удаления списка заданных тегов, а второй — для удаления одного тега, который работает по указанному методу. Также в этом примере я добавил несколько строк для поддержки своих пользовательских тегов tiff... Всем им будет предшествовать комментарий //ADDED.

Классы:

общедоступный статический класс TIFFTAGS — этот класс является основным классом, который просто вызывается, выполняя что-то вроде TIFFTAGS.DeleteTiffTags(); Поскольку это статический класс, нет необходимости создавать его объект для использования его методов.

частный класс TIFFTAGS_PAGE. Этот класс является частным классом, который находится внутри класса TIFFTAGS. Его цель состоит в том, чтобы содержать всю информацию об одной странице для всех страниц, которые могут быть в TIFF. Он является частным и используется только для внутренних целей.

открытый класс TIFFTAGS_TAG — это класс, который я сделал, чтобы обернуть теги во что-то большее, чем мне нравится. Использование стандартных имен типов тегов, таких как ASCII, SHORT, LONG и RATIONAL.

Методы/Функции:

TagExtender() — эта маленькая жемчужина представляет собой функцию обратного вызова, которая позволяет вам сохранять ваши ПОЛЬЗОВАТЕЛЬСКИЕ теги в TIFF. Без него ВСЕ ваши пользовательские теги исчезли бы при удалении любого тега (даже если вы удалили только один).

DeleteTiffTags() — это основной метод, удаляющий список тегов. Просто передайте список номеров тегов ushort, и все они будут удалены. Имейте в виду, что если не использовать функцию TagExtender, ваши пользовательские теги будут пуф!

DeleteTiffTag() — просто используется для удаления одного тега TIFF. Он вызывает DeleteTiffTags() для обработки черновой работы.

public static bool DeleteTiffTags(string sFileName, List<ushort> ushortTagNumbers)
{
    //Deletes a list of tiff tag from the given image
    //Returns true if successful or false if error occured
     //Define variables
    List<TIFFTAGS_PAGE> ttPage = new List<TIFFTAGS_PAGE>();
     //Check for empty list
    if (ushortTagNumbers.Count == 0) return false;
     try
    {
        //ADDED
        m_lTagsToWrite = new List<TIFFTAGS_TAG>();
        m_lTagsToWrite.Add(new TIFFTAGS_TAG("", 38001, Convert.ToString("")));
        m_lTagsToWrite.Add(new TIFFTAGS_TAG("", 38002, Convert.ToString("")));
        m_parentExtender = Tiff.SetTagExtender(TagExtender);
         //Open the file for reading
        using (Tiff input = Tiff.Open(sFileName, "r"))
        {
            if (input == null) return false;
             //Get page count
            int numberOfDirectories = input.NumberOfDirectories();
             //Go through all the pages
            for (short i = 0; i < numberOfDirectories; ++i)
            {
                //Set the page
                input.SetDirectory(i);
                 //Create a new tags dictionary to store all my tags
                Dictionary<ushort, FieldValue[]> dTags = new Dictionary<ushort, FieldValue[]>();
                 //Get all the tags for the page
                for (ushort t = ushort.MinValue; t < ushort.MaxValue; ++t)
                {
                    TiffTag tag = (TiffTag)t;
                    FieldValue[] tagValue = input.GetField(tag);
                    if (tagValue != null)
                    {
                        dTags.Add(t, tagValue);
                    }
                }
                 //Check if the page is encoded
                bool encoded = false;
                FieldValue[] compressionTagValue = input.GetField(TiffTag.COMPRESSION);
                if (compressionTagValue != null)
                    encoded = (compressionTagValue[0].ToInt() != (int)Compression.NONE);

                //Create a new byte array to store all my image data
                int numberOfStrips = input.NumberOfStrips();
                byte[] byteImageData = new byte[numberOfStrips * input.StripSize()];
                int offset = 0;
                 //Get all the image data for the page
                for (int n = 0; n < numberOfStrips; ++n)
                {
                    int bytesRead;
                    if (encoded)
                        bytesRead = input.ReadEncodedStrip(n, byteImageData, offset, byteImageData.Length - offset);
                    else
                        bytesRead = input.ReadRawStrip(n, byteImageData, offset, byteImageData.Length - offset);
                     //Add to the offset keeping up with where we are
                    offset += bytesRead;
                }
                 //Save all the tags, image data, and height, etc for the page
                TIFFTAGS_PAGE tiffPage = new TIFFTAGS_PAGE();
                tiffPage.Height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
                tiffPage.Tags = dTags;
                tiffPage.PageData = byteImageData;
                tiffPage.Encoded = encoded;
                tiffPage.StripSize = input.StripSize();
                tiffPage.StripOffset = input.GetField(TiffTag.STRIPOFFSETS)[0].ToIntArray()[0];
                ttPage.Add(tiffPage);
            }
        }
         //Open the file for writing
        using (Tiff output = Tiff.Open(sFileName + "-new.tif", "w"))
        {
            if (output == null) return false;
             //Go through all the pages
            for (short i = 0; i < ttPage.Count(); ++i)
            {
                //Write all the tags for the page
                foreach (KeyValuePair<ushort, FieldValue[]> tagValue in ttPage[i].Tags)
                {
                    //Write all the tags except the one's needing to be deleted
                    if (!ushortTagNumbers.Contains(tagValue.Key))
                    {
                        TiffTag tag = (TiffTag)tagValue.Key;
                        output.GetTagMethods().SetField(output, tag, tagValue.Value);
                    }
                }
                 //Set the height for the page
                output.SetField(TiffTag.ROWSPERSTRIP, ttPage[i].Height);
                 //Set the offset for the page
                output.SetField(TiffTag.STRIPOFFSETS, ttPage[i].StripOffset);
                 //Save page data along with tags
                output.CheckpointDirectory();
                 //Write each strip one at a time using the same orginal strip size
                int numberOfStrips = ttPage[i].PageData.Length / ttPage[i].StripSize;
                int offset = 0;
                for (int n = 0; n < numberOfStrips; ++n)
                {
                    //Write all the image data (strips) for the page
                    if (ttPage[i].Encoded)
                        //output.WriteEncodedStrip(n, byteStrip, offset, byteStrip.Length - offset);
                        output.WriteEncodedStrip(0, ttPage[i].PageData, offset, ttPage[i].StripSize - offset);
                    else
                        output.WriteRawStrip(n, ttPage[i].PageData, offset, ttPage[i].StripSize - offset);
                     //Add to the offset keeping up with where we are
                    offset += ttPage[i].StripOffset;
                }
                 //Save the image page
                output.WriteDirectory();
            }
        }
         //ADDED
        Tiff.SetTagExtender(m_parentExtender);
    }
    catch
    {
        //ADDED
        Tiff.SetTagExtender(m_parentExtender);

        //Error occured
        return false;
    }
     //Return success
    return true;
}
person Arvo Bowen    schedule 25.02.2012