Пример libexif для добавления небольшого XML-документа в данные exif
Любой пользователь / разработчик libexif, который мог бы указать мне правильное направление в отношении того, как правильно добавить небольшой пользовательский XML-документ в метаданные exif изображения JPG?
Я долго гуглил и не могу понять.
Я открыт для любой другой библиотеки с открытым исходным кодом, которая позволит мне делать это, пока она основана на C.
2 ответа
Вы можете встроить любые данные в блок данных EXIF в JPG. Я не знаю ограничения по размеру, вы просто разбиваете его на несколько блоков данных EXIF, если это необходимо.
Вам даже не нужно libexif. Вы можете сделать все это вручную в коде C, программно выполнив следующее (обратите внимание, что это работает только с файлами JPG, в которых уже есть другие данные EXIF):
По сути, ваш файл JPG (если в нем уже есть заголовок EXIF) будет начинаться примерно так:
0xFF 0xD8
Тогда самый первый заголовок Exif будет начинаться с этого:
0xFF 0xE0
Далее следует длина блока данных Exif, которая здесь составляет два байта:
0x00 0x10 //In this case it is 16 bytes (0x0010) long and it INCLUDES these two bytes of the header
Далее идут фактические данные блока данных Exif (ваши могут отличаться). Обратите внимание, что его длина составляет 14 байтов (или 14+2 = 16 байтов, или 0x0010, как показано выше):
0x4A 0x46 0x49 0x46 0x00 0x01 0x01 0x01 0x00 0x60 0x00 0x60 0x00 0x00
Теперь вы можете вставить свой блок данных XML Exif после этого заголовка, начиная с идентификатора данных exif (всегда одинакового):
0xFF 0xE1
Затем размер вашего XML-файла в байтах + 2 (обратите внимание, что если размер вашего файла больше 0xFFFE, то вы должны разбить его на несколько блоков данных EXIF):
0x07 0x7D //In this case it is 1917bytes long or 0x077D
Затем вставьте ваш XML прямо в JPG на этом этапе и оставьте остальную часть файла как есть.
Смотрите картинку ниже для визуального объяснения (просто щелкните правой кнопкой мыши и просмотрите изображение, если вы не можете его прочитать):
Вот мой JPG с моим фиктивным XML-файлом. Щелкните правой кнопкой мыши, сохраните, откройте его в шестнадцатеричном редакторе и посмотрите сами:
Пример JPG с XML в блоке данных EXIF
В конце просто проверьте, что вы все еще можете открыть JPG, и если вы можете, вы добились успеха.
Вот быстрый пример на C++ (обратите внимание, я не отлаживал код, просто написал его из памяти, так что будьте осторожны!):
char yourdata[]="<xml> contents to </add>";
long yourdatalen = 0x18;
//open file
char * file;
long filelen=0;
std::ifstream infile;
infile.open("yourjpg.jpg",std::ios::binary| std::ios::in);
//find size of file
infile.seekg (0, ios::end);
filelen = infile.tellg();
infile.seekg (0, ios::beg);
//read contents of file
file = new char [filelen];
infile.read(file,filelen);
infile.close();
//lets parse through the file and find any exif headers
long x=0;
if ((file[0]==0xFF) && (file[1]==0xD8)){
//all good lets go!!
while ((file[x]!=0xFF) && (file[x+1]!=0xE1)) {
x++;
}
//were at the first EXIF data block! insert XML here
char * temp=file;
file = new char [filelen+yourdatalen+4];
memcpy(file,temp,x);
file[x+0]=0xFF;
file[x+1]=0xE1;
file[x+2]=int((yourdatalen+2)/0xFF); //note assumes that your xml file is less than 0xFFFE bytes long
file[x+3]=yourdatalen-int((yourdatalen+2)/0xFF);
memcpy(&file[x+4],yourdata,yourdatalen);
memcpy(&file[x+4+yourdatalen],temp[x],filelen-x);
delete [] temp;
//Save to file
std::ofstream ofile;
ofile.open("savejpg.jpg",std::ios::binary| std::ios::out);
ofile.write(file,yourdatalen+4+filelen);
ofile.close();
}
else {
//JPG file does not have exif data in it, you'll need to add it first or find another way of adding your data
}
//Clean up
delete [] file;
Я использовал HxD, но вы можете использовать любой шестнадцатеричный редактор.
Я считаю, что максимальный размер поля EXIF составляет 32 КБ, поэтому этого должно быть более чем достаточно для создания файла XML.
Сгенерируйте ASCII C-строковое представление вашего XML-дерева, возможно, используя libxml2. Затем установите EXIF тег "Комментарий пользователя" к этой строке.
Следующий пример устанавливает этот тег: http://libexif.cvs.sourceforge.net/viewvc/libexif/libexif/contrib/examples/write-exif.c?view=markup
Я думаю, что вам нужно использовать этот префикс ASCII_COMMENT, а FILE_COMMENT будет вашей строкой XML.