Извлечение информации IPTC из JPEG с помощью Javascript

#javascript #image-processing #exif #iptc

#javascript #обработка изображений #exif #iptc

Вопрос:

Я пытаюсь извлечь информацию о подписи к фотографии IPTC из файла JPEG с помощью Javascript. (Я знаю, что могу сделать это на стороне сервера, но я специально ищу решение на Javascript.)

Я нашел этот скрипт, который извлекает информацию EXIF… но я не уверен, как адаптировать ее для получения данных IPTC.

Существуют ли какие-либо существующие скрипты, которые предлагают такую функциональность? Если нет, то как бы вы изменили скрипт EXIF, чтобы он также анализировал данные IPTC?

Обновить

Я модифицировал скрипт EXIF, на который я ссылался выше. Это вроде делает то, что я хочу, но не в 100 процентах случаев захватывает нужные данные.

После строки 401 я добавил:

 else if (iMarker == 237) {
        // 0xED = Application-specific 13 (Photoshop IPTC)                
        if (bDebug) log("Found 0xFFED marker");   
        return readIPTCData(oFile, iOffset   4, getShortAt(oFile, iOffset 2, true)-2);                       
}
  

И затем в другом месте скрипта я добавил эту функцию:

 function readIPTCData(oFile, iStart, iLength) {
    exif = new Array();

if (getStringAt(oFile, iStart, 9) != "Photoshop") {
    if (bDebug) log("Not valid Photoshop data! "   getStringAt(oFile, iStart, 9));
    return false;
}

var output = '';
var count = 0;
two = new Array();
for (i=0; i<iLength; i  ) {
   if (getByteAt(oFile, iStart   i) == 2 amp;amp; getByteAt(oFile, iStart   i   1) == 120) {
      var caption = getString2At(oFile, iStart   i   2, 800);
   }
   if (getByteAt(oFile, iStart   i) == 2 amp;amp; getByteAt(oFile, iStart   i   1) == 80) {
      var credit = getString2At(oFile, iStart   i   2, 300);
   }       
}

exif['ImageDescription'] = caption;
exif['Artist'] = credit;

return exif;

}
  

Итак, позвольте мне теперь немного изменить свой вопрос. Как можно улучшить описанную выше функцию?

Комментарии:

1. Это будет возможно только в браузерах, которые поддерживают новые файловые API HTML5. Появляется скрипт, на который вы ссылаетесь, для получения данных изображения путем извлечения их с сервера, что, вероятно, не то, что вы хотите сделать.

2. Да, это совершенно нормально — я разрабатываю это только для внутреннего использования, и у всех нас новейшие браузеры, так что это не проблема.

3. У меня это не работает. У вас есть пример jsfiddle?

4. Для всех, кому нужна кроссбраузерная поддержка, jDataView — это хороший способ работы с двоичными данными в JavaScript.

Ответ №1:

Как бы то ни было, я немного экстраполировал это… Я не проводил большого тестирования, но несколько тестовых изображений, которые у меня есть, похоже, работают.

     var bDebug = false;

    var fieldMap = {
        120 : 'caption',
        110 : 'credit',
        25 : 'keywords',
        85 : 'byline',
        122 : 'captionWriter',
        105 : 'headline',
        116 : 'copyright',
        15 : 'category'
    };

    function readIPTCData(oFile, iStart, iLength) {
        var data = {};

        if (oFile.getStringAt(iStart, 9) != "Photoshop") {
            if (bDebug) log("Not valid Photoshop data! "   oFile.getStringAt(iStart, 9));
            return false;
        }

        var fileLength = oFile.getLength();

        var length, offset, fieldStart, title, value;
        var FILE_SEPARATOR_CHAR = 28,
            START_OF_TEXT_CHAR = 2;

        for (var i = 0; i < iLength; i  ) {

            fieldStart = iStart   i;
            if(oFile.getByteAt(fieldStart) == START_OF_TEXT_CHAR amp;amp; oFile.getByteAt(fieldStart   1) in fieldMap) {
                length = 0;
                offset = 2;

                while(
                    fieldStart   offset < fileLength amp;amp;
                    oFile.getByteAt(fieldStart   offset) != FILE_SEPARATOR_CHAR amp;amp;
                    oFile.getByteAt(fieldStart   offset   1) != START_OF_TEXT_CHAR) { offset  ; length  ; }

                if(!length) { continue; }

                title = fieldMap[oFile.getByteAt(fieldStart   1)];
                value = oFile.getStringAt(iStart   i   2, length) || '';
                value = value.replace('00','').trim();

                data[title] = value;
                i =length-1;
            }
        }

        return data;

    }

    function findIPTCinJPEG(oFile) {
        var aMarkers = [];

        if (oFile.getByteAt(0) != 0xFF || oFile.getByteAt(1) != 0xD8) {
            return false; // not a valid jpeg
        }

        var iOffset = 2;
        var iLength = oFile.getLength();
        while (iOffset < iLength) {
            if (oFile.getByteAt(iOffset) != 0xFF) {
                if (bDebug) console.log("Not a valid marker at offset "   iOffset   ", found: "   oFile.getByteAt(iOffset));
                return false; // not a valid marker, something is wrong
            }

            var iMarker = oFile.getByteAt(iOffset 1);

            if (iMarker == 237) {
                if (bDebug) console.log("Found 0xFFED marker");
                return readIPTCData(oFile, iOffset   4, oFile.getShortAt(iOffset 2, true)-2);

            } else {
                iOffset  = 2   oFile.getShortAt(iOffset 2, true);
            }

        }

    }

    IPTC.readFromBinaryFile = function(oFile) {
        return findIPTCinJPEG(oFile);
    }
  

Комментарии:

1. что ожидает получить ‘oFile’? Где определение для IPTC? Будет ли это работать и для PNG?

Ответ №2:

Я хотел бы предложить библиотеку exifr, которая работает в обоих Node.js и браузера. И он также поддерживает новый формат изображения HEIC.

 exifr.parse(input, {iptc: true}).then(output => {
  console.log('IPTC', output)
})
  

Он анализирует несколько форматов данных (TIFF / EXIF, ICC, IPTC, XMP, JFIF), но IPTC по умолчанию не включен, поэтому вам нужно включить его в настройках, как показано в примере.

Ответ №3:

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

http://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata(200907)_1.pdf