Как удалить данные EXIF ​​без повторного сжатия JPEG?

127

Я хочу удалить информацию EXIF ​​(включая миниатюры, метаданные, информацию о камере ... все!) Из файлов JPEG, но я не хочу повторно сжимать ее, так как повторное сжатие JPEG ухудшит качество, а также обычно увеличивает размер файла.

Я ищу решение для Unix / Linux, даже лучше, если использовать командную строку. Если возможно, используйте ImageMagick (инструмент преобразования). Если это невозможно, подойдет небольшой скрипт Python, Perl, PHP (или другой распространенный язык в Linux).

Есть аналогичный вопрос, но связанный с .NET .

Денилсон Са Майя
источник
1
связанные: askubuntu.com/questions/260810/…
Ciro Santilli 郝海东 冠状 病 六四 事件

Ответы:

166

exiftool выполняет эту работу за меня, он написан на Perl, поэтому должен работать для вас при любых операциях

https://exiftool.org/

использование :

exiftool -all= image.jpg
Крис
источник
6
Еще несколько интересных вариантов: «-o outfile.jpg» или «-out outfile.jpg», «-overwrite_original» или «-overwrite_original_in_place», «-P» или «-preserve», «-r» или «-recurse»
Денилсон Са Майя
6
Я только что наткнулся на эту ветку в поисках того же. Я просто подумал, что добавлю здесь комментарий для пользователей Ubuntu: сценарий доступен в репозиториях Ubuntu как libimage-exiftool-perl: sudo apt-get install libimage-exiftool-perl
user605331,
7
Или с домашним brew install exiftool
пивом
6
Если вы действительно доверяете программе, добавьте -overwrite_originalпереключатель, и программа не будет создавать файлы резервных копий.
Salman A
10
Принятое использование с параметром -all = удаляет ВСЕ теги из вашего image.jpg! Правильный ответexiftool -EXIF= image.jpg
PeterCo
85

С помощью imagemagick:

convert <input file> -strip <output file>
JayM
источник
21
Извините, но -strip не работает должным образом, поскольку ImageMagick все еще повторно сжимает файл JPEG.
Denilson Sá Maia
5
Обратите внимание, кстати, что «-strip» может быть полезен, если кто-то выполняет другие преобразования с файлом. Также обратите внимание, что «-thumbnail 123x456» ПОЧТИ эквивалентно «-strip -resize 123x456».
Denilson Sá Maia
15
+1 потому что это было намного проще, чем загрузить новый инструмент.
Дэйв Допсон,
13
Примечание -stripудаляет цветовые профили. Для тех, кто пытается удалить данные EXIF ​​без потери информации профиля, см. Мое решение здесь: stackoverflow.com/a/17516878/1854499
Робберт
2
OP должен обновить этот ответ, поскольку он дважды неверен.
berbt
49

ImageMagick имеет параметр -strip , но он повторно сжимает изображение перед сохранением. Таким образом, этот параметр мне не нужен.

В этой теме на форуме ImageMagick объясняется, что в ImageMagick нет поддержки операций JPEG без потерь (всякий раз, когда это изменяется, отправляйте комментарий со ссылкой!), И предлагается использовать jpegtran (из libjpeg):

jpegtran -copy none -progressive image.jpg > newimage.jpg
jpegtran -copy none -progressive -outfile newimage.jpg image.jpg

(Если вы не знаете обо мне , отвечая на мой собственный вопрос, прочтите это и это и это )

Денилсон Са Майя
источник
1
Пробовал метод jpegtran, но в большинстве случаев он увеличивает размер файла, а не уменьшает его. В большинстве случаев вы хотите сделать это, чтобы уменьшить размер файла.
Codebeat
1
При попытке использовать ImageMagick для удаления данных exif я заметил, что в итоге получил файл большего размера, чем тот, с которого я начал. Это наводит меня на мысль, что Imagemagick кодирует данные, которые вы хотите удалить, и хранит их где-то еще в файле. Считайте меня старомодным, но когда я удаляю что-то из файла, я хочу, чтобы размер файла был меньше, если не того же размера. Любые другие результаты предполагают интеллектуальный анализ данных.
Deanie
1
Незначительный момент: для меня ни одна из 2 перечисленных команд не сработала, вместо этого работают следующие: jpegtran -copy none image.jpg newimage.jpg
ibic
@Codebeat Вам нужно добавить параметр. -progressiveЭто уменьшит размер.
Том
31

Вы также можете изучить Exiv2 - он очень быстрый (C ++ и без повторного сжатия), это командная строка, а также предоставляет библиотеку для манипуляций с EXIF, с которой вы можете ссылаться. Я не знаю, сколько дистрибутивов Linux делают его доступным, но в CentOS он сейчас доступен в базовом репозитории.

Использование:

exiv2 rm image.jpg
Богдан Станческу
источник
1
Спасибо, чувак, это первый прибор, который отлично справляется со своей работой без потери качества и работает очень быстро! Йо заслуживает +100! Но чтобы удалить ВСЕ типы заголовков, я должен указать параметр -da, иначе он не удалит информацию Adobe Photoshop / Creator из jpg. Я все равно на Windows.
Codebeat
Спасибо! Я хотел подтвердить, что exiv2 будет отображать информацию о местоположении GPS, чтобы я мог видеть, что она исчезла после. Параметр по умолчанию для печати - «сводка», исключающая данные GPS. Чтобы увидеть всю информацию, вам нужно использовать: exiv2 -pa pr image.jpg
Роб Рассел
Обратите внимание, что этот инструмент испортил качество некоторых моих JPEG-файлов, к счастью, у меня была резервная копия
Steel Brain
@SteelBrain, это действительно странно - не могли бы вы поделиться одним из изображений JPEG, затронутых этим?
Богдан Станческу 02
Это самое безопасное решение
Мохаммед Шариф C
20

Я бы предложил jhead:

man jhead
jhead -purejpg image.jpg

Только 123 КБ на debian / ubuntu, повторное сжатие не выполняется. Обратите внимание, что он изменяет изображение, поэтому скопируйте оригинал, если он вам нужен.

VasiliNovikov
источник
2

Недавно я реализовал этот проект на C. Код ниже делает следующее:

1) Получает текущую ориентацию изображения.

2) Удаляет все данные, содержащиеся в APP1(данные Exif) иAPP2 (данные Flashpix), путем очистки.

3) воссоздает APP1 создает маркер ориентации и устанавливает для него исходное значение.

4) Находит первый EOI маркер (Конец изображения) и обрезает файл, если это необходимо.

Прежде всего следует отметить следующие моменты:

1) Эта программа используется для моей камеры Nikon. Формат JPEG от Nikon добавляет что-то в самый конец каждого создаваемого файла. Они кодируют эти данные до конца файла изображения, создавая второй EOIмаркер. Обычно графические программы читают до первого EOIнайденного маркера. У Nikon есть информация, которую моя программа обрезает.

2) Поскольку это формат Nikon, предполагается 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;
}

Надеюсь, это кому-то поможет!

Дини
источник
1

Подсказка для удобства: если вы работаете в 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"

Для файлов PNG: команда « Преобразовать в уменьшенный PNG »
(с помощью ImageMagick изменяет данные, перезаписывая исходный файл)
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 в контекстном меню .

geekley
источник
1

Мы использовали это для удаления данных о широте из файла TIFF:

exiv2 mo -M"del Exif.GPSInfo.GPSLatitude" IMG.TIF где вы можете использовать exiv2 -pa IMG.TIFдля перечисления всех метаданных.

Мухаммет Али Асан
источник
1

Для полосы EXIF ​​без потерь вы можете использовать libexif , который доступен с cygwin . Удалите EXIF ​​и миниатюру, чтобы сделать изображение анонимным:

$ exif --remove --tag=0 --remove-thumbnail exif.jpg -o anonymized.jpg

Перетащите .batфайл для использования с cygwin:

@ECHO OFF
exif --remove --tag=0 --remove-thumbnail %~1
radioxoma
источник
0

Другое программное обеспечение:

MetAbility QuickFix

"MetabilityQuickFix удаляет всю вашу личную информацию и данные о местоположении GPS со всех ваших фотографий одним щелчком мыши. Он безопасно удаляет все элементы метаданных из блоков данных Exif, Iptc и XMP из ваших файлов JPEG и автоматически делает резервные копии исходных файлов. "

Стриппер JPEG и PNG

«Инструмент для удаления / очистки / удаления ненужных метаданных (мусора) из файлов JPG / JPEG / JFIF и PNG. Качество изображения НЕ ВЛИЯЕТСЯ. Включает поддержку командной строки. Просто укажите папку или файл в командной строке (разрешены подстановочные знаки)»

Ремус Риго
источник
0

Если вы уже используете jpegoptim, вы также можете использовать его для удаления exif.

jpegoptim -s *
strifel
источник