昔のエントリでXMPってのが何ぞや、というのはわかったんですが、
じゃあその無駄なXMPメタデータをどげんかせんといかん、と。
そういうわけで、GIF画像からXMPデータを削除するプログラムを書いてみました。
//rmxmp.c
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define TYPE_GIF 1
int fileType(char*);
int removeXmp_GIF(char*);
int main(int argc, char *argv[])
{
if(0 < argc){
for(int i=1; i < argc; i++){
switch(fileType(argv[i])){
case TYPE_GIF:
removeXmp_GIF(argv[i]);
break;
}
}
}
return 0;
}
int fileType(char* fileName){
FILE* fp = NULL;
if((fp = fopen(fileName, "r")) == NULL){
return -1;
}
char data[7] = {0};
fread(data, 1, 6, fp);
if(strcmp("GIF89a", data) == 0){
//GIF
return TYPE_GIF;
};
// other files
fclose(fp);
return -1;
}
int removeXmp_GIF(char* fileName){
char xmp[] = {0x0b, 0x58, 0x4d, 0x50, 0x20, 0x44,
0x61, 0x74, 0x61, 0x58, 0x4d, 0x50};
bool exists = false;
int c;
long s, e, f;
FILE* fp = NULL;
if((fp = fopen(fileName, "r")) == NULL){
return -1;
}
fseek(fp, 0, SEEK_END);
f = ftell(fp);
rewind(fp);
while((c=fgetc(fp)) != EOF){
if(c == 0x21 && fgetc(fp) == 0xff){
// application extension
char data[12] = {0};
fread(data, 1, 12, fp);
if(memcmp(data, xmp, 12) == 0){
s = ftell(fp) - 14;
exists = true;
break;
}
}
}
if(!exists){
return 1;
}
// XMPデータサイズの計測
while((c=fgetc(fp)) != EOF){
if(c != 0x00){
fseek(fp, c, SEEK_CUR);
}
else{
e = ftell(fp);
break;
}
}
char* remain = (char *)malloc((size_t)(f - (e - s)));
// XMP以外を読み込み
fseek(fp, 0, SEEK_SET);
fread(remain, 1, s, fp);
fseek(fp, e, SEEK_SET);
fread(remain+s, 1, f-e, fp);
fclose(fp);
// 新規作成
char tmp[ L_tmpnam ];
tmpnam(tmp);
if((fp = fopen(tmp, "w+")) == NULL){
return -1;
}
fwrite(remain, 1, (f - (e - s)), fp);
free(remain);
fclose(fp);
// 置き換え
remove(fileName);
rename(tmp, fileName);
return 0;
}
久しぶりのC言語。
マジックナンバー入りまくってますが、クレームは受け付けません。
cygwinからコンパイルして出来た実行ファイルに対象のファイルを引数に渡せば、
XMPが削除されたファイルに置き換えられます。
$ gcc -std=c99 -o rmxmp.exe rmxmp.c
$ ./rmxmp *.gif
試した感じではとりあえず動くっぽいです。
テストはあんまりしてないので利用は自己責任で。
なおGIF以外の画像には対応してません。私には必要なかったので。
気が向いたら対応するかもです。