Como remover dados EXIF ​​sem recomprimir o JPEG?

127

Quero remover as informações EXIF ​​(incluindo miniaturas, metadados, informações da câmera ... tudo!) Dos arquivos JPEG, mas não quero recomprimi-las, pois a recompressão do JPEG prejudicará a qualidade e, geralmente, aumentará a tamanho do arquivo.

Estou procurando uma solução Unix / Linux, ainda melhor se estiver usando a linha de comando. Se possível, use o ImageMagick (ferramenta de conversão). Se isso não for possível, um pequeno script Python, Perl, PHP (ou outra linguagem comum no Linux) estaria ok.

Existe uma pergunta semelhante, mas relacionada ao .NET .

Denilson Sá Maia
fonte
1
related: askubuntu.com/questions/260810/…
Ciro Santilli escreveu

Respostas:

166

exiftool faz o trabalho para mim, está escrito em perl, portanto, deve funcionar para você em qualquer

https://exiftool.org/

uso:

exiftool -all= image.jpg
chris
fonte
6
Algumas outras opções interessantes: "-o outfile.jpg" ou "-out outfile.jpg", "-overwrite_original" ou "-overwrite_original_in_place", "-P" ou "-preserve", "-r" ou "-recurse"
Denilson Sá Maia
6
Acabei de encontrar este tópico procurando a mesma coisa. Eu apenas pensei em adicionar um comentário aqui para usuários do Ubuntu: O script está disponível nos repositórios Ubuntu como libimage-exiftool-perl: sudo apt-get install libimage-exiftool-perl
#
7
Ou com homebrewbrew install exiftool
cwd
6
Se você realmente confiar no programa, adicione a -overwrite_originalopção e o programa não criará os arquivos de backup.
Salman A
10
O uso aceito com a opção -all = remove TODAS as tags do seu image.jpg! A resposta correta seriaexiftool -EXIF= image.jpg
PeterCo 4/16
85

Com imagemagick:

convert <input file> -strip <output file>
JayM
fonte
21
Desculpe, mas -strip não funciona conforme o esperado, pois o ImageMagick ainda recompacta o arquivo JPEG.
Denilson Sá Maia
5
Observe, a propósito, que "-strip" pode ser útil se alguém estiver fazendo outras transformações com o arquivo. Observe também que "123x456 na miniatura é QUASE equivalente a" 123x456 na redimensionamento de faixa ".
Denilson Sá Maia
15
+1 porque era mais fácil do que fazer o download de uma nova ferramenta.
Dave Dopson
13
Nota -stripremove perfis de cores. Para qualquer um que tenta retirar dados EXIF sem perder informações de perfil, consulte a minha solução aqui: stackoverflow.com/a/17516878/1854499
Robbert
2
O OP deve atualizar esta resposta, pois está duas vezes errada.
berbt
49

O ImageMagick possui o parâmetro -strip , mas recompacta a imagem antes de salvar. Assim, este parâmetro é inútil para minha necessidade.

Este tópico do fórum ImageMagick explica que não há suporte para operações sem perdas JPEG no ImageMagick (sempre que isso mudar, poste um comentário com um link!) E sugere o uso de jpegtran (da libjpeg):

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

(Se você não tiver certeza de que eu respondo minha própria pergunta, leia isto e isto e isto )

Denilson Sá Maia
fonte
1
Tentei o método jpegtran, mas na maioria dos casos, aumenta o tamanho do arquivo em vez de diminuí-lo. Na maioria dos casos, você deseja fazer isso para diminuir o tamanho do arquivo.
Codebeat
1
Ao tentar usar o ImageMagick para remover dados exif, notei que acabei com um arquivo maior do que o que comecei. Isso me leva a acreditar que o Imagemagick está codificando os dados que você deseja remover e os armazenando em outro lugar do arquivo. Me chame de antiquado, mas quando removo algo de um arquivo, quero que o tamanho seja menor, se não do mesmo tamanho. Quaisquer outros resultados sugerem mineração de dados.
217 Deanie
1
Um ponto secundário: para mim, nenhum dos 2 comandos listados funcionou, mas o seguinte funciona: jpegtran -copy none image.jpg newimage.jpg
ibic
@ Codebeat Você precisa adicionar param. -progressiveIsso reduzirá o tamanho.
Tom
31

Você também pode querer examinar o Exiv2 - é muito rápido (C ++ e sem recompressão), é a linha de comando e também fornece uma biblioteca para manipulação EXIF ​​à qual você pode se conectar. Não sei quantas distribuições Linux disponibilizam, mas no CentOS está atualmente disponível no repositório base.

Uso:

exiv2 rm image.jpg
Bogdan Stăncescu
fonte
1
Obrigado cara, este é o primeiro que faz o trabalho muito bem, sem perda de qualidade e rápido! Você merece um +100! Mas para remover TODOS os tipos de cabeçalhos, tenho de especificar a opção -da, caso contrário não removerá as informações do Adobe Photoshop / Criador dos jpg. Estou no Windows de qualquer maneira.
Codebeat
Obrigado! Eu queria confirmar que o exiv2 mostraria as informações de localização do GPS para que eu pudesse ver que elas foram embora. A opção padrão para impressão é "resumo", que exclui as informações do GPS. Para ver todas as informações que você tem que usar: exiv2 -PA pr image.jpg
Rob Russell
Por favor, note que esta ferramenta destruída qualidade de alguns dos meus JPEGs, felizmente eu tinha um backup
Aço Cérebro
@SteelBrain, isso é realmente estranho - você pode compartilhar uma das imagens JPEG afetadas por isso?
Bogdan Stăncescu
Esta é a solução mais segura
Mohammed Shareef C
20

Eu proporia jhead:

man jhead
jhead -purejpg image.jpg

Apenas 123Kb no debian / ubuntu, não é compactado novamente. Observe que ele modifica a imagem; portanto, copie o original, se necessário.

VasiliNovikov
fonte
2

Recentemente, assumi esse projeto em C. O código abaixo faz o seguinte:

1) Obtém a orientação atual da imagem.

2) Remove todos os dados contidos em APP1(dados Exif) e APP2(dados Flashpix) apagando.

3) Recria o APP1marcador de orientação e o define para o valor original.

4) Localiza o primeiro EOImarcador (Fim da imagem) e trunca o arquivo, se necessário.

Algumas coisas a serem observadas primeiro são:

1) Este programa é usado para minha câmera Nikon. O formato JPEG da Nikon acrescenta algo ao final de cada arquivo que ele cria. Eles codificam esses dados no final do arquivo de imagem, criando um segundo EOImarcador. Normalmente, os programas de imagem são lidos até o primeiro EOImarcador encontrado. Depois disso, a Nikon possui informações que meu programa trunca.

2) Como é para o formato Nikon, ele assume a big endianordem dos bytes. Se o seu arquivo de imagem usar little endian, é necessário fazer alguns ajustes.

3) Ao tentar usar ImageMagickpara extrair dados exif, notei que acabei com um arquivo maior do que o que comecei. Isso me leva a acreditar que Imagemagickestá codificando os dados que você deseja remover e os armazenando em outro lugar do arquivo. Me chame de antiquado, mas quando removo algo de um arquivo, quero que o tamanho seja menor, se não do mesmo tamanho. Quaisquer outros resultados sugerem mineração de dados.

E aqui está o código:

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

Espero que isso ajude alguém!

Deanie
fonte
1

Dica de conveniência: se você estiver no Windows, poderá aplicar um arquivo REG ao registro, instalar uma entrada no menu de contexto, para remover facilmente os metadados clicando com o botão direito do mouse no arquivo e selecionando o comando.

Por exemplo (lembre-se de editar os caminhos para apontar para onde os executáveis ​​estão instalados no seu computador):


Para arquivos JPEG, JPG, JPE, JFIF: comando " Remover metadados "
(usando o ExifTool , preserva o arquivo original como backup)
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"

Para arquivos PNG: comando " Converter em PNG reduzido "
(usando o ImageMagick , altera os dados substituindo o arquivo original)
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"

Relacionado: converta PNGs em ICO no menu de contexto .

geekley
fonte
1

Usamos isso para remover dados de latitude do arquivo TIFF:

exiv2 mo -M"del Exif.GPSInfo.GPSLatitude" IMG.TIF onde você pode usar exiv2 -pa IMG.TIFpara listar todos os metadados.

Muhammet Ali Asan
fonte
1

Para a faixa EXIF ​​sem perdas, você pode usar o libexif , disponível no cygwin . Remova o EXIF ​​e a miniatura para anonimizar uma imagem:

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

Arraste e solte o .batarquivo para usar com o cygwin:

@ECHO OFF
exif --remove --tag=0 --remove-thumbnail %~1
radioxoma
fonte
0

Outro software:

MetAbility QuickFix

"O MetabilityQuickFix retira todas as suas informações pessoais e dados de localização GPS de todas as suas fotos, com apenas um clique do mouse. Ele limpa todos os itens de metadados dos blocos de dados Exif, Iptc e XMP com segurança dos seus arquivos JPEG e faz automaticamente cópias de backup dos arquivos originais "

Stripper JPEG e PNG

"Uma ferramenta para remover / limpar / remover metadados desnecessários (lixo eletrônico) de arquivos JPG / JPEG / JFIF e PNG. A qualidade da imagem NÃO É AFETADA. Inclui suporte à linha de comando. Basta especificar uma pasta ou arquivo na linha de comando (caracteres curinga são permitidos)"

Remus Rigo
fonte
0

Se você já usa o jpegoptim, também pode removê-lo.

jpegoptim -s *
strifel
fonte