165

JPEG ファイルから EXIF 情報 (サムネイル、メタデータ、カメラ情報などすべてを含む) を削除したいのですが、再圧縮したくありません。ファイルサイズ。

コマンドラインを使用する場合は、Unix/Linux ソリューションを探しています。可能であれば、ImageMagick (変換ツール) を使用します。それが不可能な場合は、小さな Python、Perl、PHP (または Linux 上の他の共通言語) スクリプトで問題ありません。

同様の質問がありますが、.NET に関連しています

4

10 に答える 10

205

exiftool は私のために仕事をします。それは perl で書かれているので、どんな O/S でもあなたのために働くはずです

https://exiftool.org/

利用方法 :

exiftool -all= image.jpg

更新 - PeterCo が以下で説明しているように、これによりすべてのタグが削除されます。EXIF タグを削除するだけの場合は、使用する必要があります

exiftool -EXIF= image.jpg
于 2010-04-16T15:46:19.983 に答える
106

imagemagick を使用:

convert <input file> -strip <output file>
于 2010-04-16T15:54:54.253 に答える
50

ImageMagick には-stripパラメータがありますが、保存する前に画像を再圧縮します。したがって、このパラメーターは私のニーズには役に立ちません。

ImageMagick フォーラムのこのトピックでは、ImageMagickでは JPEG ロスレス操作がサポートされていないことを説明しており (これが変更されるたびに、リンク付きのコメントを投稿してください!)、jpegtran (libjpeg から) の使用を提案しています。

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

(私が自分の質問に答えているかどうかわからない場合は、これこれこれを読んでください)

于 2010-04-16T16:06:17.213 に答える
23

私は提案しjheadます:

man jhead
jhead -purejpg image.jpg

debian/ubuntu では 123Kb しかなく、高速で、イメージ自体をそのまま維持して EXIF に触れるだけです。EXIF を含む元のファイルを保持する場合は、コピーを作成する必要があることに注意してください。

于 2013-07-30T21:05:40.790 に答える
3

私は最近、C でこのプロジェクトに着手しました。以下のコードは次のことを行います。

1) 画像の現在の向きを取得します。

2) APP1(Exif データ) とAPP2(Flashpix データ) に含まれるすべてのデータを消去します。

3)APP1方向マーカーを再作成し、元の値に設定します。

4) 最初のEOIマーカー (画像の終わり) を見つけ、必要がある場合はファイルを切り捨てます。

最初に注意すべき点は次のとおりです。

1) このプログラムは、私のニコン カメラに使用されます。Nikon の JPEG 形式は、作成する各ファイルの最後に何かを追加します。EOI2 番目のマーカーを作成して、このデータを画像ファイルの末尾にエンコードします。通常、画像プログラムは最初にEOI見つかったマーカーまで読み取ります。ニコンには、この後に私のプログラムが切り捨てる情報があります。

big endian2) ニコンフォーマットのため、バイトオーダを前提としています。画像ファイルで を使用している場合は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;
}

これが誰かを助けることを願っています!

于 2016-10-27T22:23:48.917 に答える