182

I want to remove the EXIF information (including thumbnail, metadata, camera info... everything!) from JPEG files, but I don't want to recompress it, as recompressing the JPEG will degrade the quality, as well as usually increasing the file size.

I'm looking for a Unix/Linux solution, even better if using the command-line. If possible, using ImageMagick (convert tool). If that's not possible, a small Python, Perl, PHP (or other common language on Linux) script would be ok.

There is a similar question, but related to .NET.

Community
  • 1
  • 1
Denilson Sá Maia
  • 47,466
  • 33
  • 109
  • 111
  • 2
    related: https://askubuntu.com/questions/260810/how-can-i-read-and-remove-meta-exif-data-from-my-photos-using-the-command-line – Ciro Santilli OurBigBook.com Sep 06 '19 at 21:43
  • 1
    Are you sure you want to remove *all* EXIF information? The EXIF Orientation information is crucial for displaying the image rotated the right way. If you remove it, you may find that the images are displayed 90 degrees rotated from what you expect. Also, colour profiles are stored in EXIF metadata, which affects how the colours of the image are displayed. – Flimm Mar 04 '22 at 21:56

10 Answers10

232

exiftool does the job for me, it's written in perl so should work for you on any o/s

https://exiftool.org/

usage :

exiftool -all= image.jpg

UPDATED - as PeterCo explains below this will remove ALL of the tags. if you just want to remove the EXIF tags then you should use

exiftool -EXIF= image.jpg
chris
  • 9,745
  • 1
  • 27
  • 27
  • 8
    Some other interesting options: "-o outfile.jpg" or "-out outfile.jpg", "-overwrite_original" or "-overwrite_original_in_place", "-P" or "-preserve", "-r" or "-recurse" – Denilson Sá Maia Apr 17 '10 at 02:05
  • 8
    I just came across this thread looking for the same thing. I just thought I'd add a comment here for Ubuntu users: The script is available in the Ubuntu repos as libimage-exiftool-perl: `sudo apt-get install libimage-exiftool-perl` – user605331 Aug 09 '11 at 13:02
  • Just like Denilson Sá mentioned, there are other interesting opitons. My favorite, to know at least how the meta data look like (before and/or after using the command given by oedo): `exiftool image.jpg` – Iam Zesh Jan 12 '13 at 17:15
  • 9
    Or with homebrew `brew install exiftool` – cwd Dec 29 '13 at 15:55
  • 7
    If you **really** trust the program add `-overwrite_original` switch and the program will not create the backup files. – Salman A Jul 31 '15 at 18:35
  • Seems like all links on the linked site are dead now (HTTP 404). – Mario Mar 14 '16 at 20:19
  • 15
    The accepted usage with the option -all= removes ALL tags from your image.jpg! The correct answer would be `exiftool -EXIF= image.jpg` – PeterCo Sep 04 '16 at 11:34
  • 1
    @PeterCo Technically Exif data can be embedded inside XMP (and GIF images only support XMP). If you're stripping Exif there's a good chance you also want to strip XMP and IPTC, although probably not ICC profiles (which is what would happen when stripping "all"). – Abe Voelker Jul 19 '17 at 14:42
  • 1
    @PeterCo And even then I don't want to strip all EXIF tags.. just the thumbnail! For me at least, that's `exiftool -thumbnailimage= FILE` – Michael Apr 19 '19 at 02:48
  • Note that `exiftool -all= file.jpg` will remove even the "orientation" metadata, which will make some photos appear to be rotated the wrong way. – Flimm Aug 23 '21 at 14:40
106

With imagemagick:

convert <input file> -strip <output file>
JayM
  • 4,798
  • 1
  • 21
  • 15
  • 28
    Sorry, but -strip does not work as expected, since ImageMagick still recompress the JPEG file. – Denilson Sá Maia Apr 16 '10 at 16:06
  • 5
    Note, by the way, that "-strip" might be useful if someone is doing other transformations with the file. Also note that "-thumbnail 123x456" is ALMOST equivalent to "-strip -resize 123x456". – Denilson Sá Maia Apr 17 '10 at 02:08
  • 25
    +1 because this was miles easier than downloading a new tool. – Dave Dopson Feb 12 '12 at 02:17
  • 18
    Note `-strip` removes color profiles. For anyone trying to strip EXIF data without losing profile information, see my solution here: http://stackoverflow.com/a/17516878/1854499 – Robbert Jul 07 '13 at 22:10
  • 5
    OP should update this answer, since it's twice wrong. – berbt Feb 04 '15 at 09:07
  • 2
    When trying to use ImageMagick to strip exif data, I noticed that I ended up with a larger file than what I started with. This leads me to believe that Imagemagick is encoding the data you want stripped away, and is storing it somewhere else in the file. Call me old fashioned, but when I remove something from a file, I want a file size the be smaller if not the same size. Any other results suggest data mining. – Deanie Apr 06 '17 at 19:58
  • Also note that `-strip` works not only with `convert`, but with a lot of other IM commands as well (i.e. I used `mogrify`) – The Godfather Jul 07 '19 at 22:26
50

ImageMagick has the -strip parameter, but it recompresses the image before saving. Thus, this parameter is useless for my need.

This topic from ImageMagick forum explains that there is no support for JPEG lossless operations in ImageMagick (whenever this changes, please post a comment with a link!), and suggests using jpegtran (from libjpeg):

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

(If you are unsure about me answering my own question, read this and this and this)

Tom
  • 2,962
  • 3
  • 39
  • 69
Denilson Sá Maia
  • 47,466
  • 33
  • 109
  • 111
  • 1
    Tried the jpegtran method but in most cases it increase the filesize instead of decreasing it. In most cases you want to do this to decrease the filesize. – Codebeat May 27 '15 at 02:06
  • 1
    When trying to use ImageMagick to strip exif data, I noticed that I ended up with a larger file than what I started with. This leads me to believe that Imagemagick is encoding the data you want stripped away, and is storing it somewhere else in the file. Call me old fashioned, but when I remove something from a file, I want a file size the be smaller if not the same size. Any other results suggest data mining. – Deanie Apr 06 '17 at 19:59
  • 1
    A minor point: for me, none of the 2 commands listed worked, instead the following works: `jpegtran -copy none image.jpg newimage.jpg` – ibic Jun 11 '17 at 10:10
  • @Codebeat You need to add param `-progressive` This will reduce size. – Tom Feb 21 '20 at 19:11
  • Note that `jpegtran -copy none file.jpg` will remove the "orientation" metadata, which will make some photos appear to be rotated the wrong way. – Flimm Aug 23 '21 at 14:42
40

You might also want to look into Exiv2 -- it's really fast (C++ and no recompression), it's command line, and it also provides a library for EXIF manipulation you can link against. I don't know how many Linux distros make it available, but in CentOS it's currently available in the base repo.

Usage:

exiv2 rm image.jpg
Bogdan Stăncescu
  • 5,320
  • 3
  • 24
  • 25
  • 1
    Thanks man, this is the first one that does the job very well without quality loss and blazing fast! Yo deserve a +100! But to remove ALL type of headers I have to specify the -da option otherwise it will not remove adobe photoshop/creator info from jpg's. I'm on Windows anyway. – Codebeat May 27 '15 at 02:38
  • 1
    Thanks! I wanted to confirm that exiv2 would show GPS location info so that I could see that it was gone after. The default option for print is "summary" which excludes GPS info. To see all info you have to use: exiv2 -pa pr image.jpg – Rob Russell Oct 24 '15 at 20:36
  • Please note that this tool destroyed quality of some of my JPEGs, luckily I had a backup – Steel Brain Mar 01 '16 at 20:32
  • 1
    @SteelBrain, that's really strange – can you share one of the JPEG images affected by this? – Bogdan Stăncescu Mar 02 '16 at 14:21
  • This is the safest solution – Mohammed Shareef C Jun 04 '19 at 09:49
  • Easiest solution for batches and comes built into my linux distro, so no need to trust a third party for something like exiftool. – Shadouts Sep 16 '19 at 01:20
  • Note that `exiv2 rm image.jpg` will remove the "orientation" metadata, which will make some photos appear to be rotated the wrong way. – Flimm Aug 23 '21 at 14:42
24

I'd propose jhead:

man jhead
jhead -purejpg image.jpg

Only 123Kb on debian/ubuntu, it's fast, and it only touches EXIF keeping the image itself intact. Note that you need to create a copy if you want to preserve the original file with EXIF in it.

VasiliNovikov
  • 9,681
  • 4
  • 44
  • 62
3

I recently undertook this project in C. The code below does the following:

1) Gets the current orientation of the image.

2) Removes all data contained in APP1 (Exif data) and APP2 (Flashpix data) by blanking.

3) Recreates the APP1 orientation marker and sets it to the original value.

4) Finds the first EOI marker (End of Image) and truncates the file if nessasary.

Some things to note first are:

1) This program is used for my Nikon camera. Nikon's JPEG format adds somthing to the very end of each file it creates. They encode this data on to the end of the image file by creating a second EOI marker. Normally image programs read up to the first EOI marker found. Nikon has information after this which my program truncates.

2) Because this is for Nikon format, it assumes big endian byte order. If your image file uses little endian, some adjustments need to be made.

3) When trying to use ImageMagick to strip exif data, I noticed that I ended up with a larger file than what I started with. This leads me to believe that Imagemagick is encoding the data you want stripped away, and is storing it somewhere else in the file. Call me old fashioned, but when I remove something from a file, I want a file size the be smaller if not the same size. Any other results suggest data mining.

And here is the code:

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

Hope this helps someone!

Deanie
  • 2,316
  • 2
  • 19
  • 35
1

We used this to remove latitude data from TIFF file:

exiv2 mo -M"del Exif.GPSInfo.GPSLatitude" IMG.TIF where you can use exiv2 -pa IMG.TIF to list all metadata.

Muhammet Ali Asan
  • 1,486
  • 22
  • 39
  • OP asked for removing _everything_ from a JPEG, not for removing just GPSLatitude from a tiff file. Thus, this doesn't answer the question. – maxschlepzig Jan 09 '21 at 11:08
0

Hint for convenience: If you are on Windows, you can apply a REG file to the registry, to install an entry in the context menu, so you can easily remove metadata by right-clicking the file and selecting the command.

For example (remember to edit the paths to point to where the executables are installed on your computer):


For JPEG,JPG,JPE,JFIF files: command "Remove metadata"
(using ExifTool, preserves original file as 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"

For PNG files: command "Convert to minified PNG"
(using ImageMagick, changes data overwriting original file)
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: convert PNGs to ICO in context menu.

geekley
  • 1,231
  • 10
  • 27
  • OP explicitly asked for a UNIX/Linux solution thus this is pretty much irrelevant to this question. – maxschlepzig Jan 09 '21 at 11:49
  • Even though the question has unix tag, this is still SO, not Unix SE or Ask Ubuntu. I can think of a lot of times where I found an answer (that wasn't totally specific to the question) that helped me in someone else's question. We don't give answers solely for the benefit of the ones asking, you know... IMHO There's no need to be so strict with the rules; the question already has great answers at the top. – geekley Jan 09 '21 at 16:36
  • This is not how SO works. This is a Q&A site where answers should actually answer the question. And not a web-forum where it's common to post random apropos comments in any thread. For your use case, on SO, a better way is to post a new question regarding windows registry specifics, possibly directly together with your answer. Then you can add a comment for reference to a related question. – maxschlepzig Jan 09 '21 at 22:41
0

For lossless EXIF strip you can use libexif, which is available with cygwin. Remove both EXIF and thumbnail to anonymize an image:

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

Drag-n-drop .bat file for use with cygwin:

@ECHO OFF
exif --remove --tag=0 --remove-thumbnail %~1
radioxoma
  • 426
  • 5
  • 16
0

If you already use jpegoptim you can use it to remove the exif, too.

jpegoptim -s *
strifel
  • 46
  • 4
  • This doesn't work, it modifies the image (and there doesn't seem to be a `copy` option, and using the `-n` switch to not optimize the image also doesn't strip the EXIF data). – Synetech Aug 10 '21 at 16:03