使用 PHP 从 JPG 中删除 EXIF 数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3614925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 10:25:30  来源:igfitidea点击:

Remove EXIF data from JPG using PHP

phpimage-processingimagemagickexif

提问by tau

Is there any way to remove the EXIF data from a JPG using PHP? I have heard of PEL, but I'm hoping there's a simpler way. I am uploading images that will be displayed online and would like the EXIF data removed.

有没有办法使用 PHP 从 JPG 中删除 EXIF 数据?我听说过 PEL,但我希望有一种更简单的方法。我正在上传将在线显示的图像,并希望删除 EXIF 数据。

Thanks!

谢谢!

EDIT: I don't/can't install ImageMagick.

编辑:我不/不能安装 ImageMagick。

采纳答案by e2-e4

Use gdto recreate the graphical part of the image in a new one, that you save with another name.

用于gd在新的图像中重新创建图像的图形部分,并使用另一个名称保存。

See PHP gd

PHP gd



edit 2017编辑 2017

Use the new Imagick feature.

使用新的 Imagick 功能。

Open Image:

打开图片:

<?php
    $incoming_file = '/Users/John/Desktop/file_loco.jpg';
    $img = new Imagick(realpath($incoming_file));

Be sure to keep any ICC profile in the image

确保在图像中保留任何 ICC 配置文件

    $profiles = $img->getImageProfiles("icc", true);

then strip image, and put the profile back if any

然后剥离图像,如果有的话,把配置文件放回去

    $img->stripImage();

    if(!empty($profiles)) {
       $img->profileImage("icc", $profiles['icc']);
    }

Comes from this PHP page, see comment from Max Eremin down the page.

来自此 PHP 页面,请参阅页面下方 Max Eremin 的评论。

回答by Bill H

A fast way to do it in PHP using ImageMagick (Assuming you have it installed and enabled).

一种使用 ImageMagick 在 PHP 中执行此操作的快速方法(假设您已安装并启用它)。

<?php

$images = glob('*.jpg');

foreach($images as $image) 
{   
    try
    {   
        $img = new Imagick($image);
        $img->stripImage();
        $img->writeImage($image);
        $img->clear();
        $img->destroy();

        echo "Removed EXIF data from $image. \n";

    } catch(Exception $e) {
        echo 'Exception caught: ',  $e->getMessage(), "\n";
    }   
}
?>

回答by xtempore

I was looking for a solution to this as well. In the end I used PHP to rewrite the JPEG with ALL Exif data removed. I didn't need any of it for my purposes.

我也在寻找解决方案。最后,我使用 PHP 重写了 JPEG,并删除了所有 Exif 数据。为了我的目的,我不需要任何东西。

This option has several advantages...

此选项有几个优点...

  • The file is smaller because the EXIF data is gone.
  • There is no loss of image quality (because the image data is unchanged).
  • 该文件较小,因为 EXIF 数据不见了。
  • 没有图像质量损失(因为图像数据不变)。

Also a note on using imagecreatefromjpeg: I tried this and my files got bigger. If you set quality to 100, your file will be LARGER, because the image has been resampled, and then stored in a lossless way. And if you don't use quality 100, you lose image quality. The ONLY way to avoid resampling is to not use imagecreatefromjpeg.

还有一个关于使用 imagecreatefromjpeg 的说明:我试过了,我的文件变大了。如果您将质量设置为 100,您的文件将更大,因为图像已经过重新采样,然后以无损方式存储。如果你不使用质量 100,你就会失去图像质量。避免重采样的唯一方法是不使用 imagecreatefromjpeg。

Here is my function...

这是我的功能...

/**
 * Remove EXIF from a JPEG file.
 * @param string $old Path to original jpeg file (input).
 * @param string $new Path to new jpeg file (output).
 */
function removeExif($old, $new)
{
    // Open the input file for binary reading
    $f1 = fopen($old, 'rb');
    // Open the output file for binary writing
    $f2 = fopen($new, 'wb');

    // Find EXIF marker
    while (($s = fread($f1, 2))) {
        $word = unpack('ni', $s)['i'];
        if ($word == 0xFFE1) {
            // Read length (includes the word used for the length)
            $s = fread($f1, 2);
            $len = unpack('ni', $s)['i'];
            // Skip the EXIF info
            fread($f1, $len - 2);
            break;
        } else {
            fwrite($f2, $s, 2);
        }
    }

    // Write the rest of the file
    while (($s = fread($f1, 4096))) {
        fwrite($f2, $s, strlen($s));
    }

    fclose($f1);
    fclose($f2);
}

The code is pretty simple. It opens the input file for reading and the output file for writing, and then starts reading the input file. It data from one to the other. Once it reaches the EXIF marker, it reads the length of the EXIF record and skips over that number of bytes. It then continues by reading and writing the remaining data.

代码非常简单。它打开用于读取的输入文件和用于写入的输出文件,然后开始读取输入文件。它从一个到另一个数据。一旦到达 EXIF 标记,它就会读取 EXIF 记录的长度并跳过该字节数。然后继续读取和写入剩余数据。

回答by Naveen Web Solutions

The following will remove all EXIF data of a jpeg file. This will make a copy of original file without EXIF and remove the old file. Use 100 quality not to loose any quality details of picture.

以下将删除 jpeg 文件的所有 EXIF 数据。这将制作一个没有 EXIF 的原始文件的副本并删除旧文件。使用 100 质量不会丢失图片的任何质量细节。

$path = "/image.jpg";

$img = imagecreatefromjpeg ($path);
imagejpeg ($img, $path, 100);
imagedestroy ($img);

(simple approximation to the graph can be found here)

(可以在此处找到图形的简单近似值)

回答by semaca2005

this is the simplest way:

这是最简单的方法:

$images = glob($location.'/*.jpg');

foreach($images as $image) {   
    $img = imagecreatefromjpeg($image);
    imagejpeg($img,$image,100);
}

回答by Dmitry Bugrov

function remove_exif($in, $out)
{
    $buffer_len = 4096;
    $fd_in = fopen($in, 'rb');
    $fd_out = fopen($out, 'wb');
    while (($buffer = fread($fd_in, $buffer_len)))
    {
        //  \xFF\xE1\xHH\xLLExif\x00\x00 - Exif 
        //  \xFF\xE1\xHH\xLLhttp://      - XMP
        //  \xFF\xE2\xHH\xLLICC_PROFILE  - ICC
        //  \xFF\xED\xHH\xLLPhotoshop    - PH
        while (preg_match('/\xFF[\xE1\xE2\xED\xEE](.)(.)(exif|photoshop|http:|icc_profile|adobe)/si', $buffer, $match, PREG_OFFSET_CAPTURE))
        {
            echo "found: '{$match[3][0]}' marker\n";
            $len = ord($match[1][0]) * 256 + ord($match[2][0]);
            echo "length: {$len} bytes\n";
            echo "write: {$match[0][1]} bytes to output file\n";
            fwrite($fd_out, substr($buffer, 0, $match[0][1]));
            $filepos = $match[0][1] + 2 + $len - strlen($buffer);
            fseek($fd_in, $filepos, SEEK_CUR);
            echo "seek to: ".ftell($fd_in)."\n";
            $buffer = fread($fd_in, $buffer_len);
        }
        echo "write: ".strlen($buffer)." bytes to output file\n";
        fwrite($fd_out, $buffer, strlen($buffer));
    }
    fclose($fd_out);
    fclose($fd_in);
}

It is a prototype for a call from a command line.

它是从命令行调用的原型。

回答by vfn

I completely misunderstood your question.

我完全误解了你的问题。

You could use some command line tool to do this job. or write your own php extension to do it. have a look at this lib that would be useful: http://www.sno.phy.queensu.ca/~phil/exiftool/

您可以使用一些命令行工具来完成这项工作。或编写您自己的 php 扩展来做到这一点。看看这个有用的库:http: //www.sno.phy.queensu.ca/~phil/exiftool/

Cheers,

干杯,

vfn

虚拟机

回答by Garis M Suero

I'm not pretty sure about it, but if its possible using GDo ImageMagick, the first thing that come to my mind is to create a new Image and add the old image to the new one.

我不太确定,但如果可以使用GDo ImageMagick,我想到的第一件事就是创建一个新图像并将旧图像添加到新图像中。