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



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



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



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

686   7  

7 ответов:

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

http://www.sno.phy.queensu.ca / ~Фил / exiftool

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

exiftool -all= image.jpg

С imagemagick:

convert <input file> -strip <output file>

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

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

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

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

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

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

exiv2 rm image.jpg

Я предлагаю jhead:

man jhead
jhead -purejpg image.jpg
  • размер пакета в debian (/ubuntu) составляет всего 123 КБ
  • он не теряет качество, потому что он не повторно сжимается
  • программа изменяет изображения, так что вам лучше сделать резервную копию, если вы хотите

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

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

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

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

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

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

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 ''.
    for(int x = 0; x < 65506; x++)
        fputc(0, fp);

// Blank the second APP1 marker with ''.
    fseek(fp, 4, SEEK_CUR);

    for(int x = 0; x < 2044; x++)
        fputc(0, fp);

// Blank the APP2 marker with ''.
    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] = '';

// 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;
}

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

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

MetAbility QuickFix

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

JPEG & PNG Стриппер

"инструмент для зачистка / очистка / удаление ненужных метаданных (мусора) из файлов JPG/JPEG/JFIF & PNG. На качество изображения это не влияет. Включает поддержку командной строки. Просто укажите папку или файл в командной строке (подстановочные знаки разрешены)"

Comments

    Ничего не найдено.