Compare commits
6 commits
c3f63ee79a
...
1a82462d0a
Author | SHA1 | Date | |
---|---|---|---|
1a82462d0a | |||
e47623cdf6 | |||
d00f34a96b | |||
7367cf4b7e | |||
d5b4f2cd0f | |||
322543a2e0 |
6 changed files with 86 additions and 19 deletions
|
@ -21,4 +21,40 @@ class Exif {
|
|||
public static function exifOrientationOnSide(int $exif_orientation): bool {
|
||||
return $exif_orientation >= 5 && $exif_orientation <= 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the rotation in degrees of the given exif orientation.
|
||||
*
|
||||
* @param int $exif_orientation One of the EXIF_ORIENTATION_* constants.
|
||||
* @return int Rotation in degrees.
|
||||
*/
|
||||
public static function exifOrientationDegrees(int $exif_orientation): int {
|
||||
switch ($exif_orientation) {
|
||||
case self::EXIF_ORIENTATION_UNDEFINED:
|
||||
case self::EXIF_ORIENTATION_0_UPRIGHT:
|
||||
case self::EXIF_ORIENTATION_0_FLIPPED:
|
||||
return 0;
|
||||
case self::EXIF_ORIENTATION_180_UPRIGHT:
|
||||
case self::EXIF_ORIENTATION_180_FLIPPED:
|
||||
return 180;
|
||||
case self::EXIF_ORIENTATION_90_UPRIGHT:
|
||||
case self::EXIF_ORIENTATION_90_FLIPPED:
|
||||
return 90;
|
||||
case self::EXIF_ORIENTATION_270_UPRIGHT:
|
||||
case self::EXIF_ORIENTATION_270_FLIPPED:
|
||||
return 270;
|
||||
default:
|
||||
throw new \RuntimeException("Invalid exif orientation '$exif_orientation'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given exif orientation flips the image.
|
||||
*
|
||||
* @param int $exif_orientation One of the EXIF_ORIENTATION_* constants.
|
||||
* @return bool If the image is flipped.
|
||||
*/
|
||||
public static function exifOrientationIsFlipped(int $exif_orientation): bool {
|
||||
return $exif_orientation % 2 == 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
namespace Vichan\Data;
|
||||
|
||||
|
||||
class ImageMetadataResult {
|
||||
class ImageMetadata {
|
||||
// NOT affected by the exit orientation.
|
||||
public int $width;
|
||||
// NOT affected by the exif orientation.
|
||||
public int $height;
|
||||
public string $mime;
|
||||
public ?int $exif_orientation;
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Vichan\Service\Media;
|
||||
|
||||
use Vichan\Data\{Exif, ImageMetadataResult};
|
||||
use Vichan\Data\{Exif, ImageMetadata};
|
||||
use Vichan\Functions\Mime;
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ class CmdMagickImageMetadataReader implements ImageMetadataReader {
|
|||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
public function getMetadata(string $file_path): ImageMetadataResult {
|
||||
public function getMetadata(string $file_path): ImageMetadata {
|
||||
$arg = \escapeshellarg("$file_path[0]");
|
||||
$ret_exec = shell_exec_error("{$this->prefix} identify -format \"%w %h %m\" $arg");
|
||||
|
||||
|
@ -65,6 +65,6 @@ class CmdMagickImageMetadataReader implements ImageMetadataReader {
|
|||
|
||||
$mime = Mime\ext_to_mime($ext) ?? 'application/octet-stream';
|
||||
$exif_orientation = self::parseOrientation($orientation_str);
|
||||
return new ImageMetadataResult($width, $height, $mime, $exif_orientation);
|
||||
return new ImageMetadata($width, $height, $mime, $exif_orientation);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
namespace Vichan\Service\Media;
|
||||
|
||||
use Vichan\Data\Driver\Metadata\ExifReaderFactory;
|
||||
use Vichan\Data\{Exif, ImageMetadataResult};
|
||||
use Vichan\Data\ImageMetadata;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ class DefaultImageMetadataReader implements ImageMetadataReader {
|
|||
$this->exif_reader_factory = $exif_reader_factory;
|
||||
}
|
||||
|
||||
public function getMetadata(string $file_path): ImageMetadataResult {
|
||||
public function getMetadata(string $file_path): ImageMetadata {
|
||||
$ret = \getimagesize($file_path, $info);
|
||||
if ($ret === false) {
|
||||
throw new \RuntimeException("Could not read image sizes of '$file_path'");
|
||||
|
@ -38,13 +38,8 @@ class DefaultImageMetadataReader implements ImageMetadataReader {
|
|||
$exif_reader = $this->exif_reader_factory->getReader($mime);
|
||||
if ($exif_reader !== null) {
|
||||
$orientation = $exif_reader->getOrientation($file_path);
|
||||
if ($orientation !== null && Exif::exifOrientationOnSide($orientation)) {
|
||||
$tmp = $width;
|
||||
$width = $height;
|
||||
$height = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return new ImageMetadataResult($width, $height, $mime, $orientation);
|
||||
return new ImageMetadata($width, $height, $mime, $orientation);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Vichan\Service\Media;
|
||||
|
||||
use Vichan\Data\ThumbGenerationResult;
|
||||
use Vichan\Data\{Exif, ThumbGenerationResult};
|
||||
use Vichan\Functions\{Fs, Mime};
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@ class GdMediaHandler implements MediaHandler {
|
|||
|
||||
|
||||
private bool $strip_redraw;
|
||||
private ImageMetadataReader $image_metadate_reader;
|
||||
|
||||
|
||||
private static function imageCreateFrom(string $file, string $mime): mixed {
|
||||
|
@ -33,7 +34,7 @@ class GdMediaHandler implements MediaHandler {
|
|||
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...
|
||||
// Won't be me.
|
||||
switch ($mime) {
|
||||
|
@ -53,8 +54,7 @@ class GdMediaHandler implements MediaHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static function createCanvas(string $mime, int $width, int $height) {
|
||||
$gd = \imagecreatetruecolor($width, $height);
|
||||
private static function enableTransparency(mixed $gd, string $mime) {
|
||||
switch ($mime) {
|
||||
case 'image/png':
|
||||
\imagecolortransparent($gd, \imagecolorallocatealpha($gd, 0, 0, 0, 0));
|
||||
|
@ -66,6 +66,11 @@ class GdMediaHandler implements MediaHandler {
|
|||
\imagesavealpha($gd, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static function createCanvas(string $mime, int $width, int $height) {
|
||||
$gd = \imagecreatetruecolor($width, $height);
|
||||
self::enableTransparency($gd, $mime);
|
||||
return $gd;
|
||||
}
|
||||
|
||||
|
@ -130,8 +135,9 @@ class GdMediaHandler implements MediaHandler {
|
|||
* @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.
|
||||
*/
|
||||
public function __construct(bool $strip_redraw) {
|
||||
public function __construct(bool $strip_redraw, ImageMetadataReader $image_metadate_reader) {
|
||||
$this->strip_redraw = $strip_redraw;
|
||||
$this->image_metadate_reader = $image_metadate_reader;
|
||||
}
|
||||
|
||||
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 {
|
||||
$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);
|
||||
if ($gd === false) {
|
||||
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 ];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<?php
|
||||
namespace Vichan\Service\Media;
|
||||
|
||||
use Vichan\Data\ImageMetadataResult;
|
||||
use Vichan\Data\ImageMetadata;
|
||||
|
||||
|
||||
interface ImageMetadataReader {
|
||||
/**
|
||||
* @param string $file_path Image file path.
|
||||
*/
|
||||
public function getMetadata(string $file_path): ImageMetadataResult;
|
||||
public function getMetadata(string $file_path): ImageMetadata;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue