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

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

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

Есть похожий вопрос, но относится к .NET .

Ответы [ 10 ]

142 голосов
/ 16 апреля 2010

exiftool делает работу за меня, она написана на perl, поэтому должна работать для вас на любом o / s

http://www.sno.phy.queensu.ca/~phil/exiftool

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

* +1007 *
75 голосов
/ 16 апреля 2010

с изображением:

convert <input file> -strip <output file>
45 голосов
/ 16 апреля 2010

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

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

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

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

26 голосов
/ 01 марта 2014

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

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

exiv2 rm image.jpg
20 голосов
/ 31 июля 2013

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

man jhead
jhead -purejpg image.jpg

Только 123Kb в Debian / Ubuntu, не сжимается повторно. Обратите внимание, что оно изменяет изображение, поэтому скопируйте оригинал, если вам это нужно.

2 голосов
/ 03 апреля 2019

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

Related: конвертировать PNG в ICO в контекстном меню .

2 голосов
/ 28 октября 2016

Я недавно предпринял этот проект в 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;
}

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

0 голосов
/ 17 мая 2019

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

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

Drag-n-drop .bat файл для использования с cygwin:

@ECHO OFF
exif --remove --tag=0 --remove-thumbnail %~1
0 голосов
/ 29 апреля 2019

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

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

0 голосов
/ 18 апреля 2016

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

MetAbility QuickFix

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

JPEG & PNG Stripper

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

...