Как читать теги изображений в VB.NET, используя раздел описания

Я пытаюсь извлечь теги изображения из раздела описания изображения с помощью VB.NET. Теги изображений хранятся в разделе описания:

Теги, которые я сохранил:

StyleShootsModel=sam001;StyleShootsAspectRatio=2_3;StyleShootsPreset=Jacqueline;StyleShootsProducts=21FKA00012;StyleShootsFraming=CRP;StyleShootsEquipment=StyleShoots Live ();

Я попробовал следующий пример кода:

Public Shared Function GetDMetaTagFromImage(ByVal path As String) As DateTime
    Using fs As FileStream = New FileStream(path, FileMode.Open, FileAccess.Read)
        Using myImage As Image = Image.FromStream(fs, False, False)
            Dim tagsValue As String = ""

            Dim tags = myImage.PropertyItems.FirstOrDefault(Function(pi) pi.Id = &H9C9E)
            If tags IsNot Nothing Then
                tagsValue = Encoding.Unicode.GetString(tags.Value)
            End If
            Return tagsValue
        End Using
    End Using
End Function

Однако код, похоже, не работает должным образом. Как правильно извлечь теги изображений из раздела описания с помощью VB.NET?

Прочтите примечания здесь: Дополнительный нулевой символ между символами в метаданных, кодирующих изображение JPG. Также есть ссылка на предыдущий аналогичный вопрос.

Jimi 28.04.2024 21:15

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

Salman 29.04.2024 04:24

'Public Enum PropertyItemType As Short PropertyTagTypeByte = 1 PropertyTagTypeASCII = 2 PropertyTagTypeShort = 3 PropertyTagTypeLong = 4 PropertyTagTypeRational = 5 PropertyTagTypeUndefined = 7 PropertyTagTypeSLONG = 9 PropertyTagTypeSRational = 10 Конец перечисления'

Salman 29.04.2024 06:19

Использование myImage As Image = Image.FromFile(path) Dim propItems As PropertyItem() = myImage.PropertyItems Dim propItem As PropertyItem = propItems.FirstOrDefault(Function(pi) pi.Id = &H9C9E) If propItem IsNot Nothing then ' Декодируем значение свойства и удалите все теги нулевых символов = Encoding.UTF8.GetString(propItem.Value).Replace(vbNullChar, "").Trim() End If End using

Salman 29.04.2024 06:20

Я предложил всегда проверять тип PropertyItem перед его обработкой. В любом случае, тип этого PropertyItem — byte[] (Byte()), поэтому использование Encoding.Unicode.GetString() правильно. Неправильно то, что, поскольку результирующее значение представляет собой строку с нулевым завершением, вы пытаетесь вернуть объект DateTime в своей функции. Если вы сохранили дату в строковом формате, вам нужно получить значение как строку, удалить нулевой знак-терминатор, а затем преобразовать строку в объект DateTime, например, с помощью DateTime.TryParse() -- Если у вас есть Option Strict OFF, сразу установите его ON.

Jimi 29.04.2024 14:41

@jimi, не могли бы вы просмотреть код, который я разместил ниже?

Salman 30.04.2024 04:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как @Jimi Как уже упоминалось в комментарии, я попробовал использовать Bitmapframe и успешно прочитал все теги.

  Using stream = File.OpenRead(path)
        Dim frame = BitmapFrame.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)
        Dim metadata = DirectCast(frame.Metadata, BitmapMetadata)
        Dim Keywords = metadata?.Keywords
        If Keywords IsNot Nothing Then
            For Each keyword As String In Keywords
                Console.WriteLine(keyword)
            Next
        End If
    End Using

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

Imports MetadataExtractor
Imports MetadataExtractor.Formats.Iptc

Public Shared Function GetKeywordsFromImage(ByVal path As String) As String
    Dim directories As IEnumerable(Of MetadataExtractor.Directory) = ImageMetadataReader.ReadMetadata(path)
    Dim keywordsValue As String = ""

    Dim iptcDirectory = directories.OfType(Of IptcDirectory).FirstOrDefault()
    If iptcDirectory IsNot Nothing Then
        Dim tag = iptcDirectory.GetString(IptcDirectory.TagKeywords)
        If tag IsNot Nothing Then
            keywordsValue = tag
        End If
    End If

    Return keywordsValue
End Function

Если вы сохранили теги с помощью диалогового окна «Система», то строки имеют кодировку Unicode (UTF16-LE). Следовательно, чтобы извлечь строку и удалить завершающий нулевой символ, у вас есть Encoding.Unicode.GetString(propItem.Value).TrimEnd(ChrW(0)). Затем разделите содержимое на основе разделителя по умолчанию (;).

Jimi 30.04.2024 06:29

@jimi Я попробовал несколько способов, но все равно постоянно получаю нулевое значение в поле propItem

Salman 30.04.2024 08:44

Здесь нет полей, только локальные переменные. Если propItem имеет значение null, набор свойств 0x09C9E отсутствует. Как вы сохранили данные в этом PropertyItem? Вы уверены, что проверяете правильное изображение? -- Вероятно, вам следует опубликовать изображение где-нибудь (внутри ZIP-архива, чтобы избежать возможных изменений), чтобы его можно было протестировать. -- Кстати, вам не следует публиковать здесь свои попытки в качестве ответов, поскольку код не решает проблему. Вместо этого измените вопрос, добавив выполненные вами тесты. И, пожалуйста, укажите все подробности о процедуре, используемой для установки значений PropertyItem(s).

Jimi 30.04.2024 21:09

Более того, во время отладки кода прочитайте содержимое изображений PropertyItems и укажите в теле вопроса, какие свойства содержит эта коллекция.

Jimi 30.04.2024 21:14

Я посмотрел на изображение, которое вы разместили. GDI+ не распознает этот фрагмент метаданных. Возможно, потому, что он был установлен в системе, отличной от Windows (в свойствах программного обеспечения указано Capture One 16 Macintosh). Если вас устраивает пакет, который вы используете (вы на самом деле не публиковали ссылку на этот NuGet (?)), используйте его. Если вам интересно, System.Windows.Media.Imaging может прочитать эту информацию. Передайте поток файла в BitmapFrame, а затем прочитайте свойство Metadata.Keywords.

Jimi 01.05.2024 11:14

Например: using stream = File.OpenRead([Image Path]) dim frame = BitmapFrame.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None) dim tags = DirectCast(frame.Metadata, BitmapMetadata)?.Keywords end using

Jimi 01.05.2024 11:15

это отличный ответ @jimi. Поскольку я сохраняю несколько тегов, я могу прочитать каждый тег, просто повторяя ключевые слова. Using stream = File.OpenRead(path) Dim frame = BitmapFrame.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None) Dim metadata = DirectCast(frame.Metadata, BitmapMetadata) Dim Keywords = metadata?.Keywords If Keywords IsNot Nothing Then For Each keyword As String In Keywords MessageBox.Show(keyword) Next End If End Using

Salman 01.05.2024 13:04

Другие вопросы по теме