我正在寻找一个Unix/Linux解决方案,最好使用命令行。如果可能的话,使用ImageMagick(convert工具)。如果不可能,一个小的Python、Perl、PHP(或其他Linux上常见的语言)脚本也可以。
有一个类似的问题,但与.NET相关。
exiftool对我来说是一种适合的工具,它是用perl编写的,因此在任何操作系统上都应该能够使用。
用法:
exiftool -all= image.jpg
更新 - 正如PeterCo在下面解释的那样,这将删除所有标签。如果您只想删除EXIF标签,则应使用
exiftool -EXIF= image.jpg
sudo apt-get install libimage-exiftool-perl
- user605331brew install exiftool
安装。 - cwd-overwrite_original
开关,该程序将不会创建备份文件。 - Salman Aexiftool -EXIF= image.jpg
。 - PeterCo使用ImageMagick:
convert <input file> -strip <output file>
-strip
会移除颜色配置文件。如果有人想要去除 EXIF 数据但不丢失配置文件信息,请参考我的解决方案,链接在这里:https://dev59.com/3WYr5IYBdhLWcg3wdqGw#17516878 - Robbertjpegtran -copy none -progressive image.jpg > newimage.jpg
jpegtran -copy none -progressive -outfile newimage.jpg image.jpg
jpegtran -copy none image.jpg newimage.jpg
- ibic-progressive
。这将减小文件大小。 - Tomjpegtran -copy none file.jpg
将会删除“方向”元数据,这将导致一些照片显示为错误的旋转方向。 - Flimm你可能还想查看 Exiv2 -- 它非常快速(使用 C++,且不重新压缩),它是命令行工具,并且还提供了一个可供链接的 EXIF 操作库。我不知道有多少 Linux 发行版可以使用它,但在 CentOS 中,它目前可以在基础库中获取。
使用方法:
exiv2 rm image.jpg
exiv2 rm image.jpg
将删除“方向”元数据,这会导致一些照片看起来旋转了错误的方向。 - Flimm我建议使用 jhead
:
man jhead
jhead -purejpg image.jpg
在Debian/Ubuntu上只有123Kb,速度快,仅会触及EXIF信息而不会影响图片本身。请注意,如果你想保留带有EXIF信息的原始文件,你需要创建一个副本。
我最近在C语言中进行了这个项目。下面的代码执行以下操作:
1)获取图像的当前方向。
2)通过清空,删除所有包含在APP1
(Exif数据)和APP2
(Flashpix数据)中的数据。
3)重新创建APP1
方向标记,并将其设置为原始值。
4)查找第一个EOI
标记(图像结束),并根据需要截断文件。
首先需要注意以下几点:
1)此程序用于我的尼康相机。尼康的JPEG格式在每个创建的文件的末尾添加了一些内容。他们通过创建第二个EOI
标记将这些数据编码到图像文件的末尾。通常图像程序读取找到的第一个EOI
标记。尼康在此之后有信息,我的程序会截断它。
2)因为这是尼康格式,所以它假定big endian
字节顺序。如果您的图像文件使用little endian
,则需要进行一些调整。
3)当尝试使用ImageMagick
去除Exif数据时,我发现最终的文件比起始文件要大。这使我相信Imagemagick
正在编码您想要去除的数据,并将其存储在文件的其他位置。请原谅我有点守旧,但是当我从文件中删除某些内容时,如果不是相同大小,我希望文件大小会变小。任何其他结果都会暗示数据挖掘。
以下是代码:
#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...\n", 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)\n", 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\n", 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)\n", 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;
}
exiv2 mo -M"del Exif.GPSInfo.GPSLatitude" IMG.TIF
您可以使用exiv2 -pa IMG.TIF
列出所有元数据。方便提示:如果您使用的是Windows系统,您可以将REG文件应用于注册表中,以安装上下文菜单中的条目,这样您只需右键单击文件并选择命令即可轻松删除元数据。
例如(记得编辑路径,指向计算机上安装可执行文件的位置):
对于JPEG、JPG、JPE、JFIF文件:使用命令"删除元数据"
(使用ExifTool,保留原始文件作为备份)
exiftool -all= image.jpg
JPG-RemoveExif.reg
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\jpegfile\shell\RemoveMetadata]
@="Remove metadata"
[HKEY_CURRENT_USER\Software\Classes\jpegfile\shell\RemoveMetadata\command]
@="\"C:\\Path to\\exiftool.exe\" -all= \"%1\""
[HKEY_CURRENT_USER\Software\Classes\jpegfile\shell\RemoveMetadata]
"Icon"="C:\\Path to\\exiftool.exe,0"
convert -background none -strip -set filename:n "%t" image.png "%[filename:n].png"
PNG-Minify.reg
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 -s *