2010-09-01 63 views
12

¿Hay alguna forma de eliminar los datos EXIF ​​de un JPG usando PHP? He oído hablar de PEL, pero espero que haya una manera más simple. Estoy cargando imágenes que se mostrarán en línea y me gustaría que se eliminen los datos EXIF.Eliminar datos EXIF ​​de JPG usando PHP

Gracias!

EDITAR: No puedo/no puedo instalar ImageMagick.

Respuesta

7

Uso gd para recrear la parte gráfica de la imagen en una nueva, que guarde con otro nombre.

Ver PHP gd


edición 2017

utilizar la nueva característica Imagick.

Abrir imagen:

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

Asegúrese de mantener cualquier perfil ICC en la imagen

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

luego tira de imágenes, y poner el perfil de vuelta si ningún

$img->stripImage(); 

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

Comes de this PHP page, vea el comentario de Max Eremin en la página.

+2

¿no es esto una recompresión del jpg? Gracias. – tau

+1

Utilice '$ res = imagecreatefromjpeg ($ filename)' para cargar la imagen, luego 'imagejpeg ($ res, $ filename, QUALITY)', ponga 100 en Calidad - la pérdida, si la hay, debe ser mínima. –

+0

@ ring0: gracias! intentaré esto tan pronto como tenga la oportunidad (más tarde hoy). – tau

1

Entiendo mal tu pregunta.

Puede usar alguna herramienta de línea de comandos para hacer este trabajo. o escribe tu propia extensión de php para hacerlo. echar un vistazo a este lib que sería útil: http://www.sno.phy.queensu.ca/~phil/exiftool/

Cheers,

VFN

+0

gracias, pero no veo cómo puede usar exif.php para eliminar los datos. – tau

1

No estoy muy seguro de ello, pero si es posible usar GD o ImageMagick, lo primero que me viene a la mente es crear una nueva imagen y agregar la anterior a la nueva.

15

Una forma rápida de hacerlo en PHP utilizando ImageMagick (suponiendo que lo tiene instalado y habilitado).

<?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

gracias, pero no lo tengo instalado. – tau

+1

un posible problema con este enfoque es que stripImage() también borrará la información relacionada con el perfil de color. Por lo tanto, la imagen puede resultar no como esperabas. – maraspin

+1

En teoría, para conservar el perfil de color, puede hacer '$ profilesArray = $ image-> getImageProfiles (" * ", false);' para obtener una matriz de los perfiles presentes, luego recorra eso y ejecute '$ image-> removeImageProfile ('nombre de perfil'); 'a menos que nombre de perfil sea 'icc'. Aunque no lo he probado. – jamesinealing

2

Lo siguiente eliminará todos los datos EXIF ​​de un archivo jpeg. Esto hará una copia del archivo original sin EXIF ​​y eliminará el archivo anterior. Use 100 calidad para no perder ningún detalle de calidad de la imagen.

$path = "/image.jpg"; 

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

(simple aproximación a la gráfica se puede encontrar here)

+1

"Use 100 calidad para no perder ningún detalle de calidad de la imagen". - estrictamente hablando, esto no es verdad. JPEG usa compresión con pérdida, incluso con un 100% de calidad. – Pocketsand

+0

Sí, tiene toda la razón Pocketsand, prácticamente lo enfrenté, por eso utilizo ImageMagick en lugar de hacerlo. –

1

esta es la forma más simple:

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

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

que estaba buscando una solución para esto también. Al final usé PHP para reescribir el JPEG con TODOS los datos Exif eliminados. No necesitaba nada para mis propósitos.

Esta opción tiene varias ventajas ...

  • El archivo es más pequeño porque los datos EXIF ​​se ha ido.
  • No hay pérdida de calidad de imagen (porque los datos de la imagen no se modifican).

También una nota sobre el uso de imagecreatefromjpeg: Intenté esto y mis archivos crecieron. Si establece la calidad en 100, su archivo será MÁS GRANDE, porque la imagen ha sido remuestreada y luego almacenada de manera sin pérdida. Y si no usa calidad 100, pierde calidad de imagen. La ÚNICA forma de evitar el remuestreo es no usar imagecreatefromjpeg.

Aquí está mi función ...

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

Es un prototipo de una llamada desde una línea de comandos.

Cuestiones relacionadas