Bilddatei wird von der Dateigröße kleiner

chris4712

Erfahrenes Mitglied
Moin Moin!

Ich habe eine PHP Bild Upload Funktion die das Bild ggf. dreht und auch ein Thumbnail erzeugt.
Manchmal kommt es vor dass das Original Bild mit voller Auflösung, jedoch nicht in voller Dateigröße auf dem Server gespeichert wird.
Original ist z.B. 6000 x 4000 Pixel groß und hat 8257 KB
Original auf dem Server ist auch 6000 x 4000 Pixel groß, hat aber nur 966 KB.

Manchmal klapp es auch und das Bild hat die richtige Größe.
Ich weiß nicht warum es mal geht und mal nicht geht :-(

Hier mal die Funktionen:
PHP:
   $OriginalImage = $targetPath."orginals/".$Folder."/".$Name.".".$Extension;
    if (move_uploaded_file($_FILES["image"]["tmp_name"], $OriginalImage)) {
      // Wenn das original Bild gut auf dem Server angekommen ist, wird der Rest erledigt

      // Bildverarbeitung: Bild ggf. drehen
      if(isset($exifdata["Orientation"]))
        image_rotation($OriginalImage);

      // Erstelle nun die kleineren Versionen
      image_resize($OriginalImage, $targetPath."thumbs/".$Folder."/".$ThumbName.".".$Extension, 290, 290);
    }

hier die Funktion image_rotation:
PHP:
  function image_rotation($file) {
    GLOBAL $exifdata; // Die EXIF Daten wurden schon ausgelesen. 
    switch($exifdata["Orientation"]) {
      case 8:
        $dst_img = imagerotate(ImageCreateFromJpeg($file), 90, 0);
        break;
      case 3:
        $dst_img = imagerotate(ImageCreateFromJpeg($file), 180, 0);
        break;
      case 6:
        $dst_img = imagerotate(ImageCreateFromJpeg($file), -90, 0);
        break;
    }
    if (isset($dst_img)) {
      imagejpeg($dst_img,  $file); // Ausgabe
      imagedestroy($dst_img); // Löscht die temporär erstellten Bilder
    }
  }

Und hier noch die Funktion image_resize:
PHP:
  // Diese Funktion erstellt eine verkleinerte Variante eines Bildes
  function image_resize($source,  $filename, $maxW, $maxH) {
    list($w, $h) = getimagesize($source); // Größe auslesen

    if ($h >= $w) {
      $wn = round($w/($h/$maxH));
      $hn = $maxH;
    }
    else {
      $hn = round($h/($w/$maxW));
      $wn = $maxW;
    }
    $dst_img=ImageCreateTrueColor($wn,$hn);
    $src_img=ImageCreateFromJpeg($source);
    ImageCopyResampled($dst_img, $src_img, 0, 0, 0, 0, $wn, $hn, $w, $h);
    imagejpeg($dst_img, $filename, 65); // Ausgabe

    // Löscht die temporär erstellten Bilder
    imagedestroy($dst_img);
    imagedestroy($src_img);
  }


Danke und schöne Grüße!
 
Wenn Du ein JPG-Bild auf diese Weise bearbeitest, wird es beim Laden dekomprimiert und beim Speichern wieder komprimiert. Dabei kann sich die Dateigröße ändern. Die Differenz wird umso größer ausfallen, je mehr sich die Kompressionsfaktoren beim früheren Speichern des Bildes und beim Speichern durch dein Skript unterscheiden. Wenn Du sicher gehen willst, dass sich die Qualität nicht stark verschlechtert (ein wenig tut sie es ohnehin bei dieser Prozedur), kannst Du die Qualität, dritter Parameter von imagejpeg, erhöhen.

JPG Bilder lassen sich verlustfrei drehen, und möglicher Weise geht das auch in PHP mit jpgtran, siehe hier:
http://www.imagemagick.org/discourse-server/viewtopic.php?t=5899
 
Zuletzt bearbeitet:
Daran kann es nicht liegen. Habe ein wenig experimentiert:

Wenn ich das temp Bild (also direkt nach dem Hochladen, mit dem temporären Namen) mit der Funktion image_rotation drehe, davon einmal mit der Funktion image_resize das Thumb erzeuge, und zum Schluss erst mit move_uploaded_file die original Datei erst verschiebe ist diese auch von der Dateigröße her richtig!

Finde ich aber doof, da ich eigentlich erst mal sicher gehen wollte dass die original heile da angekommen ist wo sie hin soll.
 
Hab den Fehler weiter lokalisieren können: Die Funktion image_rotation() sorgt für das kleine Bild.
Aber ich weiß noch nicht warum :confused:
 
Daran kann es nicht liegen.
Warum glaubst Du das? Ich bin der Meinung, dass das, was ich geschrieben habe, zutreffend ist.
Dass sich die Bilddatei nicht ändert, wenn nicht rotiert wird, liegt daran, dass sie in diesem Fall gar nicht gespeichert wird (was richtig ist, denn sie wurde nicht geändert).
Code:
if (isset($dst_img))
{imagejpeg($dst_img,  $file); // Ausgabe
 
Okay, Fakt ist dass es nur dann auftritt wenn ein Bild gedreht wird. Da gebe ich dir recht.

Nun kommt aber ein Aber:
  • Teilweise gehen auch die EXIF Daten verloren. Dass sollte ja nicht der Fall sein. Auch wenn die Dateigröße geringer ist.
  • Es tritt nur manchmal auf. Ab und an bleiben die EXIF Daten erhalten, das Bild hat auch die entsprechenden Dateigröße, wurde aber gedreht.
  • Früher hatte ich es so dass ich das Temporäre Bild gedreht habe, und dann erst verschoben habe. Da ging es eigentlich immer.
Finde das Verhalten nach wie vor sehr merkwürdig o_O
 
gehen auch die EXIF Daten verloren
Problem scheint bekannt zu sein und möglicher Weise gibt es eine Lösung:
http://stackoverflow.com/questions/102466/is-it-possible-to-save-metadata-in-an-image
  • Es tritt nur manchmal auf. Ab und an bleiben die EXIF Daten erhalten, das Bild hat auch die entsprechenden Dateigröße, wurde aber gedreht.
Ich muss zugeben, das ist mysteriös und ich habe keine Erklärung! Diese PHP-Funktionen für die Arbeit mit Bildern sind wohl mit Vorsicht zu genießen.
 
Zuletzt bearbeitet:
Ich habe es nun ganz pragmatisch gelöst:
Das Thumbnail wird, wenn nötig, gedreht.
Das hochgeladen Bild bleibt unangetastet, und wir nur dann gedreht wenn es angezeigt werden soll. Dann aber auch nicht gespeichert.
Somit kein Verlust der EXIF Daten

Denke dass ist nun die einfachste Variante
 

Neue Beiträge

Zurück