GdMediaHandler.php: correct exif orientation if possible

This commit is contained in:
Zankaria 2025-03-22 01:40:30 +01:00
parent d00f34a96b
commit e47623cdf6

View file

@ -1,7 +1,7 @@
<?php <?php
namespace Vichan\Service\Media; namespace Vichan\Service\Media;
use Vichan\Data\ThumbGenerationResult; use Vichan\Data\{Exif, ThumbGenerationResult};
use Vichan\Functions\{Fs, Mime}; use Vichan\Functions\{Fs, Mime};
@ -13,6 +13,7 @@ class GdMediaHandler implements MediaHandler {
private bool $strip_redraw; private bool $strip_redraw;
private ImageMetadataReader $image_metadate_reader;
private static function imageCreateFrom(string $file, string $mime): mixed { private static function imageCreateFrom(string $file, string $mime): mixed {
@ -33,7 +34,7 @@ class GdMediaHandler implements MediaHandler {
return false; return false;
} }
public static function imageSaveTo(mixed $gd, string $file, string $mime) { private static function imageSaveTo(mixed $gd, string $file, string $mime) {
// Somebody should tune the quality and speed values... // Somebody should tune the quality and speed values...
// Won't be me. // Won't be me.
switch ($mime) { switch ($mime) {
@ -53,8 +54,7 @@ class GdMediaHandler implements MediaHandler {
return false; return false;
} }
private static function createCanvas(string $mime, int $width, int $height) { private static function enableTransparency(mixed $gd, string $mime) {
$gd = \imagecreatetruecolor($width, $height);
switch ($mime) { switch ($mime) {
case 'image/png': case 'image/png':
\imagecolortransparent($gd, \imagecolorallocatealpha($gd, 0, 0, 0, 0)); \imagecolortransparent($gd, \imagecolorallocatealpha($gd, 0, 0, 0, 0));
@ -66,6 +66,11 @@ class GdMediaHandler implements MediaHandler {
\imagesavealpha($gd, true); \imagesavealpha($gd, true);
break; break;
} }
}
private static function createCanvas(string $mime, int $width, int $height) {
$gd = \imagecreatetruecolor($width, $height);
self::enableTransparency($gd, $mime);
return $gd; return $gd;
} }
@ -130,8 +135,9 @@ class GdMediaHandler implements MediaHandler {
* @param bool $strip_redraw If the EXIF metadata should be stripped by redrawing it. * @param bool $strip_redraw If the EXIF metadata should be stripped by redrawing it.
* May cause the loss of color profiles. Orientation is still handled. * May cause the loss of color profiles. Orientation is still handled.
*/ */
public function __construct(bool $strip_redraw) { public function __construct(bool $strip_redraw, ImageMetadataReader $image_metadate_reader) {
$this->strip_redraw = $strip_redraw; $this->strip_redraw = $strip_redraw;
$this->image_metadate_reader = $image_metadate_reader;
} }
public function supportsMime(string $mime): bool { public function supportsMime(string $mime): bool {
@ -145,10 +151,38 @@ class GdMediaHandler implements MediaHandler {
} }
public function openHandle(string $file_path, string $file_mime, int $file_kind): mixed { public function openHandle(string $file_path, string $file_mime, int $file_kind): mixed {
$metadata = $this->image_metadate_reader->getMetadata($file_path);
if ($file_mime !== $file_mime) {
throw new \RuntimeException("Mime mismatch on '$file_path'");
}
$gd = self::imageCreateFrom($file_path, $file_mime); $gd = self::imageCreateFrom($file_path, $file_mime);
if ($gd === false) { if ($gd === false) {
throw new \RuntimeException("Could not open '$file_path'"); throw new \RuntimeException("Could not open '$file_path'");
} }
// Fix the orientation once and for all.
if ($metadata->exif_orientation !== null) {
$degrees = Exif::exifOrientationDegrees($metadata->exif_orientation);
$flipped = Exif::exifOrientationIsFlipped($metadata->exif_orientation);
if ($degrees !== 0) {
self::enableTransparency($gd, $file_mime);
$gd_other = \imagerotate($gd, $degrees, \imagecolorallocatealpha($gd, 0, 0, 0, 127));
\imagedestroy($gd);
if ($gd_other === false) {
throw new \RuntimeException("Error while correcting rotation of '$file_path'");
}
$gd = $gd_other;
}
if ($flipped) {
if (!\imageflip($gd, \IMG_FLIP_HORIZONTAL)) {
throw new \RuntimeException("Error while correcting flipping of '$file_path'");
}
}
}
return [ $gd, $file_path, $file_mime, $file_kind ]; return [ $gd, $file_path, $file_mime, $file_kind ];
} }