Не удается прочитать данные Exif из изображения JPEG, преобразованного из Base64

#java #metadata-extractor

#java #метаданные-экстрактор

Вопрос:

В настоящее время я разрабатываю небольшую оболочку вокруг библиотеки извлечения метаданных, чтобы иметь доступ к нескольким атрибутам метаданных в формате JPEG из кода ColdFusion. Данные JPEG поступают в ColdFusion с конечной точки REST в виде строки base64. Я хотел преобразовать эту строку в массив байтов и прочитать метаданные Exif из JPEG, вернув исходную дату создания в ColdFusion в виде строки. Однако я не могу прочитать блок Exif из преобразованного массива байтов.

Я пытался использовать оба java.utils.Base64 и javax.xml.bind.DatatypeConverter для преобразования в base64, но в обоих случаях metadata-extractor не может найти данные Exif. Я открыл исходное исходное изображение в шестнадцатеричном редакторе, и данные Exif присутствуют. Я также попытался использовать metadata-extractor для исходного файла изображения, и это сработало нормально, заголовки Exif присутствовали, когда я распечатывал каталоги и теги.

Это конструктор для класса, который я использую для чтения метаданных:

 public ImageMetaDataReader(String base64ImageData) throws IOException, ImageProcessingException {
        // create the image object from the provided string data

        byte [] imageBytes = java.util.Base64.getDecoder().decode(base64ImageData);
        javax.xml.bind.DatatypeConverter.parseBase64Binary(lexicalXSDBase64Binary)
        ByteArrayInputStream imageBytesReader = new ByteArrayInputStream(imageBytes);
        fileMetaData = JpegMetadataReader.readMetadata(imageBytesReader);

        imageBytesReader.reset();

        // read the exif data as well
        exifMetaData = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageBytes), imageBytes.length, FileType.Jpeg);
        return;
    }
  

Я также попытался, в тщетной попытке, напрямую использовать ExifReader, но получал исключение, неясное различие между порядком байтов Intel и Motorola.

Когда я запускаю код для исходного изображения, я получаю все заголовки файлов, данные Exif и все другие теги, которые фактически присутствуют в данных JPEG. Когда я запускаю его со строкой base64, как показано в конструкторе, я получаю несколько каталогов JPEG, несколько каталогов JFIF и каталог таблицы Хаффмана, больше ничего.

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

Ответ №1:

Ответ на самом деле оказался в том, как я изначально создавал строку base64 в своем тестовом коде. Сначала я собирал изображение в виде BufferedImage, а затем считывал его в массив байтов, используя методы ImageIO. Я упростил тестовый код, чтобы он выглядел примерно так:

         byte [] fileContent = Files.readAllBytes(new File("duck.jpeg").toPath());
        String base64Image = java.util.Base64.getEncoder().encodeToString(fileContent);

        ImageMetaDataReader reader = new ImageMetaDataReader(base64Image);
        printResult(reader.getImageMetaData(), "imageMetaDataTest()");
  

И теперь я получаю все метаданные. Единственное, что я могу понять, это то, что функции ImageIO каким-то образом уничтожали / искажали данные Exif, когда я считывал данные изображения в массив байтов.