libexif: запись нового exif в образ с помощью IPTC/XMP
Я пытаюсь записать EXIF метаданные в изображения JPEG с помощью libexif. Я столкнулся с проблемой с изображениями без EXIF, но с метаданными IPTC/XMP. После записи EXIF для изображений с IPTC/XMP я не могу прочитать EXIF. Утилита командной строки exif (которая также использует libexif) сообщает о повреждении EXIF. Если я делаю то же самое для изображений без метаданных, все работает нормально.
Вот небольшое тестовое приложение, которое демонстрирует проблему (предполагается, что мы работаем с изображением без EXIF).
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <libexif/exif-data.h>
#include <libexif/exif-loader.h>
#include <jpeglib.h>
#include "jpegexif/jpeg-data.h"
#include "jpegexif/jpeg-marker.h"
#include "jpegexif/jpeg-data.c"
#include "jpegexif/jpeg-marker.c"
static ExifEntry *create_ascii_tag(ExifData *exif, ExifIfd ifd, ExifTag tag, size_t len) {
void *buf;
ExifEntry *entry;
// Create a memory allocator to manage this ExifEntry.
ExifMem *mem = exif_mem_new_default();
// Create a new ExifEntry using our allocator.
entry = exif_entry_new_mem(mem);
// Allocate memory to use for holding the tag data.
buf = exif_mem_alloc(mem, len);
// Fill in the entry.
entry->data = (unsigned char*) buf;
entry->size = len;
entry->tag = tag;
entry->components = len;
entry->format = EXIF_FORMAT_ASCII;
// Attach the ExifEntry to an IFD.
exif_content_add_entry(exif->ifd[ifd], entry);
// The ExifMem and ExifEntry are now owned elsewhere.
exif_mem_unref(mem);
exif_entry_unref(entry);
return entry;
}
int create_exif_and_set_software(const char* const filename, const char* const tagvalue) {
// For simplification we assume here that file has no EXIF, so we create new.
ExifData* exif = exif_data_new();
exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
exif_data_set_byte_order(exif, EXIF_BYTE_ORDER_INTEL);
exif_data_fix(exif);
// Create entry for "Software" and set it's data.
ExifEntry* entry = create_ascii_tag(exif, EXIF_IFD_0, EXIF_TAG_SOFTWARE, strlen(tagvalue) + 1);
memcpy(entry->data, tagvalue, strlen(tagvalue) + 1);
// Write exif to JPEG.
JPEGData* image = jpeg_data_new_from_file(filename);
jpeg_data_set_exif_data(image, exif);
jpeg_data_save_file(image, filename);
// Unreference exif.
exif_data_unref(exif);
return 0;
}
int main(int argc, char ** argv) {
char* filename = argv[1];
// Create EXIF, set software and write EXIF to file.
create_exif_and_set_software(filename, "Awesome image editor.");
// Check that EXIF exists in file.
ExifData* exif = exif_data_new_from_file(filename);
printf("EXIF exists: %d\n", exif != NULL);
return 0;
}
Здесь вы можете скачать проект и образцы изображений. Я использовал следующую команду для сборки его на Mac с libxif, установленным через macports: gcc exif.c -I/opt/local/include -L/opt/local/lib -lexif
1 ответ
Самый простой способ - начать писать JPEG с нуля: сначала напишите JPEG без разделов APP1, затем добавьте раздел Exif, а затем добавьте все остальные разделы XMP APP1.
Обратите внимание, что смещения IFD должны обновляться соответствующим образом.