How to remove EXIF data without recompressing the JPEG?
我想从JPEG文件中删除EXIF信息(包括缩略图,元数据,相机信息...所有内容!),但是我不想重新压缩它,因为重新压缩JPEG会降低质量,并且通常会增加 文件大小。
我正在寻找Unix / Linux解决方案,如果使用命令行则更好。 如果可能,请使用ImageMagick(转换工具)。 如果这不可能,那么可以使用小型Python,Perl,PHP(或Linux上的其他公共语言)脚本。
有一个类似的问题,但与.NET有关。
exiftool为我完成了工作,它是用perl编写的,因此在任何操作系统上都可以为您工作
https://exiftool.org/
用法:
1 | exiftool -all= image.jpg |
使用imagemagick:
1 | convert <input file> -strip <output file> |
ImageMagick具有-strip参数,但是在保存之前会重新压缩图像。因此,此参数对我的需求毫无用处。
来自ImageMagick论坛的本主题说明,ImageMagick不支持JPEG无损操作(每当更改时,请发表带有链接的评论!),并建议使用jpegtran(来自libjpeg):
1 2 | jpegtran -copy none -progressive image.jpg > newimage.jpg jpegtran -copy none -progressive -outfile newimage.jpg image.jpg |
(如果您不确定我是否回答我自己的问题,请阅读此内容以及该内容)
您可能还想研究一下Exiv2,它确实非常快(C ++,无需重新压缩),它是命令行,并且它还提供了可链接的EXIF操作库。我不知道有多少Linux发行版可以使用它,但是在CentOS中它目前在基本存储库中可用。
用法:
1 | exiv2 rm image.jpg |
我建议
1 2 | man jhead jhead -purejpg image.jpg |
debian / ubuntu上只有123Kb,不会重新压缩。请注意,尽管它会改变图像,但是如果需要,请复制原始图像。
我最近在C中进行了这个项目。下面的代码执行以下操作:
1)获取图像的当前方向。
2)通过消隐删除
3)重新创建
4)查找第一个
首先要注意的是:
1)该程序用于我的尼康相机。尼康的JPEG格式在其创建的每个文件的末尾添加了一些东西。他们通过创建第二个
2)因为这是尼康格式,所以它假定
3)当尝试使用
这是代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | #include <stdio.h> #include <stdlib.h> #include <libgen.h> #include <string.h> #include <errno.h> // Declare constants. #define COMMAND_SIZE 500 #define RETURN_SUCCESS 1 #define RETURN_FAILURE 0 #define WORD_SIZE 15 int check_file_jpg (void); int check_file_path (char *file); int get_marker (void); char * ltoa (long num); void process_image (char *file); // Declare global variables. FILE *fp; int orientation; char *program_name; int main (int argc, char *argv[]) { // Set program name for error reporting. program_name = basename(argv[0]); // Check for at least one argument. if(argc < 2) { fprintf(stderr,"usage: %s IMAGE_FILE...\ ", program_name); exit(EXIT_FAILURE); } // Process all arguments. for(int x = 1; x < argc; x++) process_image(argv[x]); exit(EXIT_SUCCESS); } void process_image (char *file) { char command[COMMAND_SIZE + 1]; // Check that file exists. if(check_file_path(file) == RETURN_FAILURE) return; // Check that file is an actual JPEG file. if(check_file_jpg() == RETURN_FAILURE) { fclose(fp); return; } // Jump to orientation marker and store value. fseek(fp, 55, SEEK_SET); orientation = fgetc(fp); // Recreate the APP1 marker with just the orientation tag listed. fseek(fp, 21, SEEK_SET); fputc(1, fp); fputc(1, fp); fputc(18, fp); fputc(0, fp); fputc(3, fp); fputc(0, fp); fputc(0, fp); fputc(0, fp); fputc(1, fp); fputc(0, fp); fputc(orientation, fp); // Blank the rest of the APP1 marker with '\\0'. for(int x = 0; x < 65506; x++) fputc(0, fp); // Blank the second APP1 marker with '\\0'. fseek(fp, 4, SEEK_CUR); for(int x = 0; x < 2044; x++) fputc(0, fp); // Blank the APP2 marker with '\\0'. fseek(fp, 4, SEEK_CUR); for(int x = 0; x < 4092; x++) fputc(0, fp); // Jump the the SOS marker. fseek(fp, 72255, SEEK_SET); while(1) { // Truncate the file once the first EOI marker is found. if(fgetc(fp) == 255 && fgetc(fp) == 217) { strcpy(command,"truncate -s"); strcat(command, ltoa(ftell(fp))); strcat(command,""); strcat(command, file); fclose(fp); system(command); break; } } } int get_marker (void) { int c; // Check to make sure marker starts with 0xFF. if((c = fgetc(fp)) != 0xFF) { fprintf(stderr,"%s: get_marker: invalid marker start (should be FF, is %2X)\ ", program_name, c); return(RETURN_FAILURE); } // Return the next character. return(fgetc(fp)); } int check_file_jpg (void) { // Check if marker is 0xD8. if(get_marker() != 0xD8) { fprintf(stderr,"%s: check_file_jpg: not a valid jpeg image\ ", program_name); return(RETURN_FAILURE); } return(RETURN_SUCCESS); } int check_file_path (char *file) { // Open file. if((fp = fopen(file,"rb+")) == NULL) { fprintf(stderr,"%s: check_file_path: fopen failed (%s) (%s)\ ", program_name, strerror(errno), file); return(RETURN_FAILURE); } return(RETURN_SUCCESS); } char * ltoa (long num) { // Declare variables. int ret; int x = 1; int y = 0; static char temp[WORD_SIZE + 1]; static char word[WORD_SIZE + 1]; // Stop buffer overflow. temp[0] = '\\0'; // Keep processing until value is zero. while(num > 0) { ret = num % 10; temp[x++] = 48 + ret; num /= 10; } // Reverse the word. while(y < x) { word[y] = temp[x - y - 1]; y++; } return word; } |
希望这对某人有帮助!
对于无损EXIF条带,可以使用cygwin随附的libexif。删除EXIF和缩略图以匿名化图像:
1 | $ exif --remove --tag=0 --remove-thumbnail exif.jpg -o anonymized.jpg |
拖放
1 2 | @ECHO OFF exif --remove --tag=0 --remove-thumbnail %~1 |
为了方便起见:如果您使用的是Windows,则可以将REG文件应用于注册表,以在上下文菜单中安装条目,因此可以通过右键单击文件并选择命令来轻松删除元数据。
例如(记住编辑路径以指向可执行文件在计算机上的安装位置):
对于JPEG,JPG,JPE,JFIF文件:命令"删除元数据"
(使用ExifTool,将原始文件保留为备份)
JPG-RemoveExif.reg
1 2 3 4 5 6 7 8 9 10 | Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\\Software\\Classes\\jpegfile\\shell\ emoveMetadata] @="Remove metadata" [HKEY_CURRENT_USER\\Software\\Classes\\jpegfile\\shell\ emoveMetadata\\command] @="\"C:\\\\Path to\\\\exiftool.exe\" -all= \"%1\"" [HKEY_CURRENT_USER\\Software\\Classes\\jpegfile\\shell\ emoveMetadata] "Icon"="C:\\\\Path to\\\\exiftool.exe,0" |
对于PNG文件:命令"转换为缩小的PNG"
(使用ImageMagick,更改覆盖原始文件的数据)
PNG-Minify.reg
1 2 3 4 5 6 7 | Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\\Software\\Classes\\pngfile\\shell\\ConvertToMinifiedPNG] @="Convert to minified PNG" [HKEY_CURRENT_USER\\Software\\Classes\\pngfile\\shell\\ConvertToMinifiedPNG\\command] @="\"C:\\\\Path to\\\\convert.exe\" -background none -strip -set filename:n \"%%t\" \"%1\" \"%%[filename:n].png\"" [HKEY_CURRENT_USER\\Software\\Classes\\pngfile\\shell\\ConvertToMinifiedPNG] "Icon"="C:\\\\Path to\\\\convert.exe,0" |
相关:在上下文菜单中将PNG转换为ICO。
如果您已经使用jpegoptim,则也可以使用它来删除exif。
1 | jpegoptim -s * |
我们用它从TIFF文件中删除纬度数据:
您可以在其中使用
其他软件:
MetAbility QuickFix
" MetabilityQuickFix只需单击一下鼠标,即可从所有照片中剥离所有个人信息和GPS位置数据。它可以安全地从JPEG文件中清除Exif,Iptc和XMP数据块中的所有元数据项,并自动制作原始文件的备份副本"
JPEG和PNG剥离器
"用于从JPG / JPEG / JFIF和PNG文件中剥离/清除/删除不必要的元数据(垃圾)的工具。图像质量不受影响。包括命令行支持。只需在命令行上指定文件夹或文件(允许使用通配符)"