Speedup raw view of images by changing detect_image_exif_orientation default to Off

and loadImage() uses stream instead of string.
This commit is contained in:
the-djmaze 2022-03-23 17:09:25 +01:00
parent 22472ea1f1
commit 70d6d398be
6 changed files with 94 additions and 81 deletions

View file

@ -139,7 +139,7 @@ trait Raw
$sFileNameIn = isset($aValues['FileName']) ? (string) $aValues['FileName'] : '';
$sFileHashIn = isset($aValues['FileHash']) ? (string) $aValues['FileHash'] : '';
$bDetectImageOrientation = !!$this->Config()->Get('labs', 'detect_image_exif_orientation', true);
$bDetectImageOrientation = !!$this->Config()->Get('labs', 'detect_image_exif_orientation', false);
if (!empty($sFileHashIn))
{
@ -217,17 +217,33 @@ trait Raw
$self->cacheByKey($sRawKey);
$sLoadedData = null;
if (!$bDownload)
{
if ($bThumbnail)
{
try
{
$oImage = static::loadImage(\stream_get_contents($rResource), $bDetectImageOrientation, 60);
$oImage = static::loadImage($rResource, $bDetectImageOrientation, 60);
\header('Content-Disposition: inline; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut.'_thumb60x60.png')));
$oImage->show('png');
// $oImage->show('webp'); // Little Britain: "Safari says NO"
}
catch (\Throwable $oException)
{
$self->Logger()->WriteExceptionShort($oException);
}
exit;
}
else if ($bDetectImageOrientation &&
\in_array($sContentTypeOut, array('image/png', 'image/jpeg', 'image/jpg', 'image/webp')))
{
try
{
$oImage = static::loadImage($rResource, $bDetectImageOrientation);
\header('Content-Disposition: inline; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut)));
$oImage->show();
// $oImage->show('webp'); // Little Britain: "Safari says NO"
exit;
}
@ -235,108 +251,73 @@ trait Raw
{
$self->Logger()->WriteExceptionShort($oException);
}
}
else if ($bDetectImageOrientation &&
\in_array($sContentTypeOut, array('image/png', 'image/jpeg', 'image/jpg', 'image/webp')))
{
try
{
$sLoadedData = \stream_get_contents($rResource);
$oImage = static::loadImage($sLoadedData, $bDetectImageOrientation);
\header('Content-Disposition: inline; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut)));
$oImage->show();
}
catch (\Throwable $oException)
{
$self->Logger()->WriteExceptionShort($oException);
}
}
else
{
$sLoadedData = \stream_get_contents($rResource);
exit;
}
}
if ($bDownload || $sLoadedData)
{
if (!headers_sent()) {
\header('Content-Type: '.$sContentTypeOut);
\header('Content-Disposition: '.($bDownload ? 'attachment' : 'inline').'; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut)));
if (!\headers_sent()) {
\header('Content-Type: '.$sContentTypeOut);
\header('Content-Disposition: '.($bDownload ? 'attachment' : 'inline').'; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileNameOut)));
\header('Accept-Ranges: bytes');
\header('Content-Transfer-Encoding: binary');
}
\header('Accept-Ranges: bytes');
\header('Content-Transfer-Encoding: binary');
}
if ($bIsRangeRequest && !$sLoadedData)
{
$sLoadedData = \stream_get_contents($rResource);
}
$sLoadedData = null;
if ($bIsRangeRequest || !$bDownload) {
$sLoadedData = \stream_get_contents($rResource);
}
\MailSo\Base\Utils::ResetTimeLimit();
\MailSo\Base\Utils::ResetTimeLimit();
if ($sLoadedData)
{
if ($bIsRangeRequest && (\strlen($sRangeStart) || \strlen($sRangeEnd)))
{
$iFullContentLength = \strlen($sLoadedData);
if ($sLoadedData) {
if ($bIsRangeRequest && (\strlen($sRangeStart) || \strlen($sRangeEnd))) {
$iFullContentLength = \strlen($sLoadedData);
\MailSo\Base\Http::StatusHeader(206);
\MailSo\Base\Http::StatusHeader(206);
$iRangeStart = (int) $sRangeStart;
$iRangeEnd = (int) $sRangeEnd;
$iRangeStart = (int) $sRangeStart;
$iRangeEnd = (int) $sRangeEnd;
if ('' === $sRangeEnd)
{
if ('' === $sRangeEnd) {
$sLoadedData = 0 < $iRangeStart ? \substr($sLoadedData, $iRangeStart) : $sLoadedData;
} else {
if ($iRangeStart < $iRangeEnd) {
$sLoadedData = \substr($sLoadedData, $iRangeStart, $iRangeEnd - $iRangeStart);
} else {
$sLoadedData = 0 < $iRangeStart ? \substr($sLoadedData, $iRangeStart) : $sLoadedData;
}
else
{
if ($iRangeStart < $iRangeEnd)
{
$sLoadedData = \substr($sLoadedData, $iRangeStart, $iRangeEnd - $iRangeStart);
}
else
{
$sLoadedData = 0 < $iRangeStart ? \substr($sLoadedData, $iRangeStart) : $sLoadedData;
}
}
$iContentLength = \strlen($sLoadedData);
if (0 < $iContentLength)
{
\header('Content-Length: '.$iContentLength);
\header('Content-Range: bytes '.$sRangeStart.'-'.(0 < $iRangeEnd ? $iRangeEnd : $iFullContentLength - 1).'/'.$iFullContentLength);
}
echo $sLoadedData;
}
else
{
echo $sLoadedData;
}
unset($sLoadedData);
}
else
{
\MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource);
$iContentLength = \strlen($sLoadedData);
if (0 < $iContentLength) {
\header('Content-Length: '.$iContentLength);
\header('Content-Range: bytes '.$sRangeStart.'-'.(0 < $iRangeEnd ? $iRangeEnd : $iFullContentLength - 1).'/'.$iFullContentLength);
}
} else {
\header('Content-Length: '.\strlen($sLoadedData));
}
echo $sLoadedData;
unset($sLoadedData);
} else {
\MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource);
}
}
}, $sFolder, $iUid, $sMimeIndex);
}
private static function loadImage(string $data, bool $bDetectImageOrientation = true, int $iThumbnailBoxSize = 0) : \SnappyMail\Image
private static function loadImage($resource, bool $bDetectImageOrientation = true, int $iThumbnailBoxSize = 0) : \SnappyMail\Image
{
if (\extension_loaded('gmagick')) { $handler = 'gmagick'; }
else if (\extension_loaded('imagick')) { $handler = 'imagick'; }
else if (\extension_loaded('gd')) { $handler = 'gd2'; }
else { return null; }
$handler = 'SnappyMail\\Image\\'.$handler.'::createFromString';
$oImage = $handler($data);
$handler = 'SnappyMail\\Image\\'.$handler.'::createFromStream';
$oImage = $handler($resource);
// rotateImageByOrientation
if ($bDetectImageOrientation) {

View file

@ -381,7 +381,7 @@ Enables caching in the system'),
'fast_cache_redis_host' => array('127.0.0.1'),
'fast_cache_redis_port' => array(6379),
'use_local_proxy_for_external_images' => array(true),
'detect_image_exif_orientation' => array(true),
'detect_image_exif_orientation' => array(false),
'cookie_default_path' => array(''),
'cookie_default_secure' => array(false),
'check_new_messages' => array(true),

View file

@ -6,6 +6,8 @@ interface Image
{
public static function createFromString(string &$data);
public static function createFromStream(/*resource*/$fp);
public function getOrientation() : int;
public function rotate(float $degrees) : bool;

View file

@ -55,6 +55,12 @@ class GD2 implements \SnappyMail\Image
return $gd2;
}
public static function createFromStream($fp)
{
$data = \stream_get_contents($fp);
return static::createFromString($data);
}
public function getOrientation() : int
{
return $this->orientation;

View file

@ -28,6 +28,20 @@ class GMagick extends \Gmagick implements \SnappyMail\Image
return $gmagick;
}
public static function createFromStream($fp)
{
if (!\method_exists($gmagick, 'getImageOrientation')) {
$data = \stream_get_contents($fp);
return static::createFromString($data);
}
$gmagick = new static();
if (!$gmagick->readimagefile($fp)) {
throw new \InvalidArgumentException('Failed to load image');
}
$gmagick->orientation = $gmagick->getImageOrientation();
return $gmagick;
}
public function getOrientation() : int
{
return $this->orientation;

View file

@ -21,6 +21,16 @@ class IMagick extends \Imagick implements \SnappyMail\Image
return $imagick;
}
public static function createFromStream($fp)
{
$imagick = new static();
if (!$imagick->readImageFile($fp)) {
throw new \InvalidArgumentException('Failed to load image');
}
$imagick->setImageMatte(true);
return $imagick;
}
public function getOrientation() : int
{
return $this->getImageOrientation();