Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only resize an image if it results in a smaller image size #32787

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 55 additions & 17 deletions apps/theming/lib/ImageManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,29 +232,67 @@ public function updateImage(string $key, string $tmpFile): string {
}

if ($key === 'background' && strpos($detectedMimeType, 'image/svg') === false && strpos($detectedMimeType, 'image/gif') === false) {
// Optimize the image since some people may upload images that will be
// either to big or are not progressive rendering.
$newImage = @imagecreatefromstring(file_get_contents($tmpFile));
$tmpFile = $this->getResizedFilePath($tmpFile, $detectedMimeType);
}

// Preserve transparency
imagesavealpha($newImage, true);
imagealphablending($newImage, true);
$target->putContent(file_get_contents($tmpFile));
return $detectedMimeType;
}

$tmpFile = $this->tempManager->getTemporaryFile();
$newWidth = (int)(imagesx($newImage) < 4096 ? imagesx($newImage) : 4096);
$newHeight = (int)(imagesy($newImage) / (imagesx($newImage) / $newWidth));
$outputImage = imagescale($newImage, $newWidth, $newHeight);
/**
* For png and webp files: Returns the file path of the file resized to a maximum of 4096 pixels wide (preserving aspect ratio)
* but only if the resizing results in an image that has a smaller file size than the uploaded file. For jpeg files:
* Will always re-save the file at quality 80 (not too low, not too high to create large files).
*
* @param string $originalTmpFile The tmpFile(path) as uploaded by the user
* @param string $detectedMimeType The the MIME type of the file as uploaded by the user
* @return string Location of the resized file, or the original if that was the smaller of the two
*/
private function getResizedFilePath(string $originalTmpFile, string $detectedMimeType): string
{
// Optimize the image since some people may upload images that will be
// either to big or are not progressive rendering.
$newImage = @imagecreatefromstring(file_get_contents($originalTmpFile));

imageinterlace($outputImage, 1);
imagepng($outputImage, $tmpFile, 8);
imagedestroy($outputImage);
// Preserve transparency
imagesavealpha($newImage, true);
imagealphablending($newImage, true);

$target->putContent(file_get_contents($tmpFile));
} else {
$target->putContent(file_get_contents($tmpFile));
$newImageTmpFile = $this->tempManager->getTemporaryFile();
$newWidth = (int)(imagesx($newImage) < 4096 ? imagesx($newImage) : 4096);
$newHeight = (int)(imagesy($newImage) / (imagesx($newImage) / $newWidth));
$outputImage = imagescale($newImage, $newWidth, $newHeight);

imageinterlace($outputImage, 1);

$checkIfFileSizeWasReduced = false;

// Preserve the original file format
switch($detectedMimeType) {
case 'image/png':
imagepng($outputImage, $newImageTmpFile, 8);
$checkIfFileSizeWasReduced = true;
break;
case 'image/webp':
imagewebp($outputImage, $newImageTmpFile, 80);
$checkIfFileSizeWasReduced = true;
break;
case 'image/jpeg':
imagejpeg($outputImage, $newImageTmpFile, 80);
// we have no convenient way if knowing if the original file was a progressive
// jpeg, so we just need to re-save it.
$checkIfFileSizeWasReduced = false;
break;
}

return $detectedMimeType;
imagedestroy($outputImage);

$newImageIsLarger = filesize($newImageTmpFile) >= filesize($originalTmpFile);
if($checkIfFileSizeWasReduced && $newImageIsLarger) {
return $originalTmpFile;
}

return $newImageTmpFile;
}

/**
Expand Down