2010-04-16 19 views
78

Voglio rimuovere le informazioni EXIF ​​(comprese le anteprime, i metadati, le informazioni della fotocamera ... tutto!) Dai file JPEG, ma non voglio ricomprimerlo, in quanto ricomprimere il JPEG peggiorerà la qualità, così come di solito aumentando la dimensione del file.Come rimuovere i dati EXIF ​​senza ricomprimere il JPEG?

Sto cercando una soluzione Unix/Linux, ancora meglio se si utilizza la riga di comando. Se possibile, utilizzare ImageMagick (strumento di conversione). Se ciò non è possibile, un piccolo script Python, Perl, PHP (o altro linguaggio comune su Linux) sarebbe ok.

C'è una domanda simile, ma related to .NET.

risposta

114

exiftool fa il lavoro per me, è scritto in perl così dovrebbe funzionare per voi su o/s

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

utilizzo qualsiasi:

exiftool -all= image.jpg 
+0

Cura di modificare il post e aggiungere un esempio di riga di comando? –

+0

sicuro :) anche se è piuttosto semplice – oedo

+3

Alcune altre opzioni interessanti: "-o outfile.jpg" o "-out outfile.jpg", "-overwrite_original" o "-overwrite_original_in_place", "-P" o "-preserve", "-r" o "-recurse" –

67

Con ImageMagick:

convert <input file> -strip <output file> 
+10

Ci scusiamo, ma -strip non funziona come previsto, dal momento che ImageMagick ricomprime ancora il file JPEG. –

+4

Nota, a proposito, che "-strip" potrebbe essere utile se qualcuno sta facendo altre trasformazioni con il file. Si noti inoltre che "-thumbnail 123x456" è ALMOST equivalente a "-strip -resize 123x456". –

+10

+1 perché questo era più facile che scaricare un nuovo strumento. –

35

ImageMagick ha il parametro -strip, ma è consigliabile preme l'immagine prima di salvare. Quindi, questo parametro è inutile per il mio bisogno.

This topic from ImageMagick forum spiega che non v'è alcun supporto per JPEG operazioni senza perdita di dati in ImageMagick (ogni volta che questo cambia, si prega di inviare un commento con un link!), E suggerisce di utilizzare jpegtran (da libjpeg):

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

(Se non siete sicuri su di me rispondere alla mia domanda, leggere this e this e this)

+1

Ho provato il metodo jpegtran ma nella maggior parte dei casi aumenta la dimensione del file invece di diminuirlo. Nella maggior parte dei casi si desidera eseguire questa operazione per ridurre la dimensione del file. – Codebeat

+1

Quando provo ad usare ImageMagick per eliminare i dati exif, ho notato che ho finito con un file più grande di quello che ho iniziato. Questo mi porta a credere che Imagemagick stia codificando i dati che vuoi togliere e li stia conservando da qualche altra parte nel file. Chiamami vecchio stile, ma quando rimuovo qualcosa da un file, voglio una dimensione del file più piccola se non della stessa dimensione. Qualsiasi altro risultato suggerisce il data mining. – Deanie

+0

Un punto minore: per me, nessuno dei 2 comandi elencati funzionava, invece i seguenti lavori: 'jpegtran -copy none image.jpg newimage.jpg' – ibic

16

avrei propongo jhead:

man jhead 
jhead -purejpg image.jpg 
  • il pacchetto su Debian (/ ubuntu) è solo 123Kb dimensioni
  • non perde la qualità perché non ri-comprimere
  • il programma muta l'immagine, quindi è meglio fare un backup se si vuole
21

si potrebbe anche voler guardare in Exiv2 - è veramente veloce (C++ e senza ricompressione), è da riga di comando, e fornisce anche una libreria per la manipolazione EXIF ​​è possibile collegare contro. Non so quante distribuzioni Linux lo rendono disponibile, ma in CentOS è attualmente disponibile nel repository di base.

Usage:

exiv2 rm image.jpg 
+0

Grazie amico, questo è il primo che fa il lavoro molto bene senza perdita di qualità e veloce velocità! Ti meriti un +100! Ma per rimuovere TUTTI i tipi di intestazioni devo specificare l'opzione -da altrimenti non rimuoverò le informazioni su Adobe Photoshop/creator da jpg. Sono su Windows comunque. – Codebeat

+0

Grazie! Volevo confermare che exiv2 mostrava le informazioni sulla posizione GPS in modo che potessi vedere che era andato dopo. L'opzione predefinita per la stampa è "riepilogo" che esclude le informazioni GPS. Per vedere tutte le informazioni che devi usare: exiv2 -pa pr image.jpg –

+0

Si prega di notare che questo strumento ha distrutto la qualità di alcuni dei miei file JPEG, per fortuna ho avuto un backup –

0

altro software:

MetAbility QuickFix

"MetabilityQuickFix strisce tutte le informazioni personali e dati di localizzazione GPS da tutte le vostre foto, con un semplice clic del mouse.Si sfrega tutti gli elementi di metadati formano blocchi di dati Exif, IPTC e XMP in modo sicuro dai file JPEG e fa copie di backup dei file originali "

JPEG & PNG Stripper

" Uno strumento per lo stripping/pulizia/rimozione dei metadati uncessary automaticamente (junk) da file JPG/JPEG/JFIF & PNG. La qualità dell'immagine NON VIENE INTERESSATA. Include il supporto della riga di comando. Basta specificare una cartella o un file sulla riga di comando (caratteri jolly consentiti)"

1

Recentemente ho intrapreso questo progetto in C. Il codice di seguito esegue le seguenti operazioni:.

1) Ottiene l'orientamento corrente dell'immagine

2) rimuove tutti i dati contenuti nel APP1 (dati Exif) e APP2 (dati Flashpix) per tranciatura.

3) ricrea il marcatore APP1 orientamento e imposta al valore originale.

4) Trova il primo indicatore EOI (Fine dell'immagine) e tronca il file se necessario.

Alcune cose da notare prima sono:

1) Questo programma viene utilizzato per la mia macchina fotografica Nikon. Il formato JPEG di Nikon aggiunge qualcosa alla fine di ogni file che crea. Codificano questi dati fino alla fine del file immagine creando un secondo indicatore EOI. Normalmente i programmi di immagine leggono fino al primo marker EOI trovato. Nikon ha informazioni dopo ciò che il mio programma tronca.

2) Poiché questo è per il formato Nikon, assume l'ordine dei byte big endian. Se il file immagine utilizza little endian, è necessario apportare alcune modifiche.

3) Quando si tenta di utilizzare ImageMagick per eliminare i dati exif, ho notato che ho finito con un file più grande di quello che ho iniziato con. Questo mi porta a credere che codifichi i dati che vuoi togliere e li stia conservando da qualche altra parte nel file. Chiamami vecchio stile, ma quando rimuovo qualcosa da un file, voglio una dimensione del file più piccola se non della stessa dimensione. Qualsiasi altro risultato suggerisce il data mining.

Ed ecco il codice:

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

Spero che questo aiuti qualcuno!

Problemi correlati