【问题标题】:Remove EXIF data from JPG using PHP使用 PHP 从 JPG 中删除 EXIF 数据
【发布时间】:2011-04-06 14:35:25
【问题描述】:

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

谢谢!

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

【问题讨论】:

    标签: php image-processing imagemagick exif


    【解决方案1】:

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

    PHP gd


    编辑 2017

    使用新的 Imagick 功能。

    打开图片:

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

    请务必在图片中保留任何 ICC 配置文件

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

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

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

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

    【讨论】:

    • 使用 $res = imagecreatefromjpeg($filename) 加载图像,然后使用 imagejpeg ($res, $filename, QUALITY),将 100 设置为质量 - 损失(如果有的话)应该是最小的。
    • @ring0:谢谢!我一有机会就试试这个(今天晚些时候)。
    • @ring0: 抱歉回复晚了,但这个方法确实有效。不幸的是,它确实会重新压缩,所以只要我没有安装 imagemagick,我就必须弄清楚什么对我来说更重要。
    • 是的,这将重新采样图像并导致轻微的质量损失,并可能对图像中的红色产生 JPEG“魔法”。
    • 这是否也会删除图像方向数据?我的用户可能会上传不是来自 0º 设备方向的图像。
    【解决方案2】:

    在 PHP 中使用 ImageMagick 的快速方法(假设您已安装并启用它)。

    <?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";
        }   
    }
    ?>
    

    【讨论】:

    • 这种方法的一个可能问题是 stripImage() 也会删除颜色配置文件相关信息。因此,图像可能与您的预期不同。
    • 理论上要保留颜色配置文件,您可以执行$profilesArray = $image-&gt;getImageProfiles("*",false); 以获取存在的配置文件数组,然后循环遍历并运行$image-&gt;removeImageProfile('profilename');,除非配置文件名称为“icc”。不过还没有测试过。
    • 做 $image->removeImageProfile('exif'); 不是更容易吗? @jamesinealing ?
    • 虽然 OP 明确表示 exif,但我推测他们出于隐私、文件大小等原因想要删除所有此类配置文件
    • 这也会删除 EXIF 方向元数据,这可能会使一些照片在用户看来以错误的方向旋转。
    【解决方案3】:

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

    这个选项有几个优点...

    • 文件变小了,因为 EXIF 数据消失了。
    • 图像质量没有损失(因为图像数据没有改变)。

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

    这是我的功能...

    /**
     * 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);
    }
    

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

    【讨论】:

    • 谢谢你!我在末尾添加了copy($new, $old);unlink($new);以保留原始文件名,非常有用的代码=)
    • 虽然这很好,但有些图像确实会变大。 118k 变成 270k
    • @ShawnRebelo 应该不可能让它变大。该代码实际上只是从一个文件中读取字节并写入另一个文件。假设它找到 EXIF 数据,它会更小。如果不是,它应该是相同的大小。可以发你的图吗?
    • @ShawnRebelo 只有几张图片?我想在我自己的课堂上实现这个,你会推荐吗?
    • @iiiml0sto1 我在原始文件中添加了一些额外的 cmets。该功能基于读取 JPEG 文件,然后写入新文件。如果您直接从数据中工作,则需要稍微不同地对待它,但想法是一样的。一次读取 2 个字节(=1 个字),找到 EXIF 标记 (0xFFE1),读取接下来的 2 个字节的长度,然后跳过那么多字节。
    【解决方案4】:

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

    $path = "/image.jpg";
    
    $img = imagecreatefromjpeg ($path);
    imagejpeg ($img, $path, 100);
    imagedestroy ($img);
    

    (图的简单近似可以找到here

    【讨论】:

    • "使用 100 质量不丢失图片的任何质量细节。" ——严格来说,这不是真的。 JPEG 使用有损压缩,即使质量为 100%。
    • 是的,你说得对,Pocketsand,我几乎遇到过,这就是我使用 ImageMagick 来代替它的原因。
    • 这不再起作用了。我正在使用 PHP 7。我会尝试 ImageMagick,而不是像许多人建议的那样。
    【解决方案5】:
    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);
    }
    

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

    【讨论】:

      【解决方案6】:

      这是最简单的方法:

      $images = glob($location.'/*.jpg');
      
      foreach($images as $image) {   
          $img = imagecreatefromjpeg($image);
          imagejpeg($img,$image,100);
      }
      

      【讨论】:

      • 但是文件会很大...比原来的大
      【解决方案7】:

      我完全误解了你的问题。

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

      干杯,

      vfn

      【讨论】:

      • 谢谢,但我不明白如何使用 exif.php 删除数据。
      【解决方案8】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-17
        • 2012-05-16
        • 1970-01-01
        • 1970-01-01
        • 2012-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多