2010-09-01 27 views
12

Có cách nào để xóa dữ liệu EXIF ​​khỏi JPG bằng PHP không? Tôi đã nghe nói về PEL, nhưng tôi hy vọng có một cách đơn giản hơn. Tôi đang tải lên hình ảnh sẽ được hiển thị trực tuyến và muốn xóa dữ liệu EXIF.Xóa dữ liệu EXIF ​​khỏi JPG bằng cách sử dụng PHP

Cảm ơn!

EDIT: Tôi không/không thể cài đặt ImageMagick.

Trả lời

7

Sử dụng gd để tái tạo phần đồ họa của hình ảnh trong một hình mới, giúp bạn tiết kiệm với tên khác.

Xem PHP gd


chỉnh sửa 2017

Sử dụng tính năng Imagick mới.

Mở ảnh:

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

Hãy chắc chắn để giữ bất kỳ hồ sơ ICC trong hình ảnh

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

sau đó dải hình ảnh, và đưa hồ sơ cá nhân trở lại nếu có

$img->stripImage(); 

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

Đi kèm từ this PHP page, xem nhận xét từ Max Eremin xuống trang.

+2

wont này gây ra một recompression của jpg ?? cảm ơn. – tau

+1

Sử dụng '$ res = imagecreatefromjpeg ($ filename)' để tải hình ảnh, sau đó 'imagejpeg ($ res, $ filename, QUALITY)', đặt 100 thành Chất lượng - sự mất mát, nếu có, nên tối thiểu. –

+0

@ ring0: cảm ơn! bệnh cố gắng này ngay sau khi tôi có cơ hội (sau này ngày hôm nay). – tau

1

Tôi hoàn toàn hiểu nhầm câu hỏi của bạn.

Bạn có thể sử dụng một số công cụ dòng lệnh để thực hiện công việc này. hoặc viết phần mở rộng php của riêng bạn để làm điều đó. có một cái nhìn tại lib này mà có thể hữu ích: http://www.sno.phy.queensu.ca/~phil/exiftool/

Chúc mừng,

vfn

+0

cảm ơn, nhưng tôi không thấy cách bạn có thể sử dụng exif.php để xóa dữ liệu. – tau

1

Tôi không chắc chắn về nó, nhưng nếu có thể sử dụng GD o ImageMagick, điều đầu tiên tôi nghĩ là tạo một hình ảnh mới và thêm hình ảnh cũ vào hình mới.

15

Cách nhanh chóng để thực hiện việc này bằng PHP bằng ImageMagick (Giả sử bạn đã cài đặt và bật).

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

cảm ơn bạn, nhưng tôi chưa cài đặt. – tau

+1

một vấn đề có thể xảy ra với phương pháp này là stripImage() cũng sẽ xóa thông tin liên quan đến cấu hình màu. Do đó hình ảnh có thể bật ra không như thế nào bạn mong đợi. – maraspin

+1

Về lý thuyết để bảo toàn cấu hình màu bạn có thể làm '$ profilesArray = $ image-> getImageProfiles (" * ", false);' để lấy một mảng các cấu hình hiện tại, sau đó lặp lại và chạy '$ image-> removeImageProfile ('profilename'); 'trừ khi profilename là' icc '. Chưa thử nghiệm nó. – jamesinealing

2

Sau đây sẽ xóa tất cả dữ liệu EXIF ​​của tệp jpeg. Thao tác này sẽ tạo một bản sao của tệp gốc mà không có EXIF ​​và xóa tệp cũ. Sử dụng 100 chất lượng không để mất bất kỳ chi tiết chất lượng của hình ảnh.

$path = "/image.jpg"; 

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

(đơn giản xấp xỉ để đồ thị có thể được tìm thấy here)

+1

"Sử dụng 100 chất lượng không để mất bất kỳ chi tiết chất lượng của hình ảnh." - nói đúng, điều này không đúng. JPEG sử dụng tính năng nén mất dữ liệu, ngay cả ở chất lượng 100%. – Pocketsand

+0

Vâng, bạn hoàn toàn đúng Pocketsand, tôi thực tế phải đối mặt với nó, đó là lý do tại sao tôi sử dụng ImageMagick thay vì nó. –

1

đây là cách đơn giản nhất:

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

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

tôi đang tìm kiếm một giải pháp cho điều này là tốt. Cuối cùng, tôi đã sử dụng PHP để viết lại ảnh JPEG với dữ liệu TẤT CẢ Exif bị loại bỏ. Tôi không cần nó vì mục đích của mình.

Tùy chọn này có nhiều ưu điểm ...

  • Các tập tin nhỏ hơn vì dữ liệu EXIF ​​đã biến mất.
  • Không làm giảm chất lượng hình ảnh (vì dữ liệu hình ảnh không thay đổi).

Ngoài ra lưu ý khi sử dụng imagecreatefromjpeg: Tôi đã thử tệp này và tệp của tôi lớn hơn. Nếu bạn đặt chất lượng thành 100, tệp của bạn sẽ LỚN hơn, vì hình ảnh đã được lấy lại và sau đó được lưu trữ theo cách không bị mất. Và nếu bạn không sử dụng chất lượng 100, bạn sẽ mất chất lượng hình ảnh. Cách duy nhất để tránh resampling là không sử dụng imagecreatefromjpeg.

Đây là chức năng của tôi ...

function removeExif($old, $new) 
{ 
    $f1 = fopen($old, 'rb'); 
    $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); 
} 
1
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); 
} 

Nó là một nguyên mẫu cho một cuộc gọi từ một dòng lệnh.

Các vấn đề liên quan