-
-
Notifications
You must be signed in to change notification settings - Fork 82
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
add memories.image.highres/convert_all_images_formarts/format/quality/_max_x/_max_y/ #653
base: master
Are you sure you want to change the base?
Changes from 2 commits
e613076
21b8a28
437e00b
267a0e6
3e6ffcc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -276,7 +276,8 @@ public function decodable(string $id): Http\Response | |
$blob = $file->getContent(); | ||
|
||
// Convert image to JPEG if required | ||
if (!\in_array($mimetype, ['image/png', 'image/webp', 'image/jpeg', 'image/gif'], true)) { | ||
$highres_enabled = $this->config->getSystemValueString('memories.image.highres_convert_all_images_formarts_enabled', 'false'); | ||
if (!\in_array($mimetype, ['image/png', 'image/webp', 'image/jpeg', 'image/gif'], true) || $highres_enabled == 'true') { | ||
[$blob, $mimetype] = $this->getImageJPEG($blob, $mimetype); | ||
} | ||
|
||
|
@@ -377,14 +378,75 @@ private function getImageJPEG($blob, $mimetype): array | |
} catch (\ImagickException $e) { | ||
throw Exceptions::Forbidden('Imagick failed to read image: '.$e->getMessage()); | ||
} | ||
|
||
// Convert to JPEG | ||
try { | ||
$image->autoOrient(); | ||
$image->setImageFormat('jpeg'); | ||
$image->setImageCompressionQuality(95); | ||
$format = $this->config->getSystemValueString('memories.highres_format', 'jpeg'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The config values need to be correctly scoped, e.g. |
||
switch ($format) { | ||
case 'jpeg': | ||
$format = 'jpeg'; | ||
break; | ||
case 'webp': | ||
$format = 'webp'; | ||
break; | ||
/*case 'avif': //CPU Benchmark | ||
//$format = 'avif'; | ||
break*/ | ||
default: | ||
$format = 'jpeg'; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't need this check. If the admin sets the value to something invalid, it's not our problem. |
||
$image->setImageFormat($format); | ||
|
||
$quality = (int)$this->config->getSystemValue('memories.image.highres_quality', '95'); | ||
if ($quality < 0 || $quality > 100) { | ||
//throw Exceptions::Forbidden('Warning: You have set an invalid quality value for image conversion'); | ||
} | ||
$image->setImageCompressionQuality($quality); | ||
|
||
// Set maximum width and height | ||
$maxWidth = (int)$this->config->getSystemValue('memories.image.highres_max_x', '0'); | ||
$maxHeight = (int)$this->config->getSystemValue('memories.image.highres_max_y', '0'); | ||
|
||
// Get current dimensions | ||
$width = (int)$image->getImageWidth(); | ||
$height = (int)$image->getImageHeight(); | ||
|
||
// Calculate new dimensions while maintaining aspect ratio | ||
if ($maxWidth > 0 && $maxHeight > 0) { | ||
if ($width > $maxWidth || $height > $maxHeight) { | ||
$aspectRatio = $width / $height; | ||
if ($width > $height) { | ||
$newWidth = $maxWidth; | ||
$newHeight = $maxWidth / $aspectRatio; | ||
} else { | ||
$newHeight = $maxHeight; | ||
$newWidth = $maxHeight * $aspectRatio; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// Resize the image | ||
$image->scaleImage((int)$newWidth, (int)$newHeight); | ||
} | ||
} | ||
|
||
$blob = $image->getImageBlob(); | ||
$mimetype = $image->getImageMimeType(); | ||
|
||
//getImageMimeType() dont work for webp you can use pathinfo() and strtolower() but i make it shorter | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ImageMagick 6.9.11-60 Q16 x86_64 2021-01-25 https://imagemagick.org |
||
$extension = pathinfo("file.".$format, PATHINFO_EXTENSION); | ||
$extension = strtolower($extension); | ||
|
||
$mimeTypes = [ | ||
'jpeg' => 'image/jpeg', | ||
'jpg' => 'image/jpeg', | ||
'webp' => 'image/webp', | ||
'avif' => 'image/avif', | ||
]; | ||
|
||
if (isset($mimeTypes[$extension])) { | ||
$mimetype = $mimeTypes[$extension]; | ||
} | ||
|
||
//$mimetype = 'image/'.$format; | ||
|
||
} catch (\ImagickException $e) { | ||
throw Exceptions::Forbidden('Imagick failed to convert image: '.$e->getMessage()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not desirable. What we really want is a cap on the resolution, so the original image should be used to determine if we want to scale it.
E.g. if the cap is set to 12MP, then scaling a 4MP image is meaningless (even decoding it is a resource waste)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also need to always exclude GIF, since webp animation depends on library support
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I just noticed it when testing that the webp image wasn't really animated.
Then I wrote code for each case.
But it was so terribly big that I deleted it and the best was this:
I think I should go to sleep. :D
Have to admit, if a user loads this with always always full screen, he has a PC from the future.
PHP makes an effort to let the script run as long as possible as it is in the config and thus allows an infinite number of calls.
So always full you should be very careful.
But I think it's more of an experimental feature anyway.
Thank you for your support. :)
Learned some new things, using the bitmap to divide the image into parts, which google does, was very interesting.
I try to finish adapting the code after sleeping.
I think you've tried what I do before, heard the experience? :D
Edit: I added the funny code, so you should always sleep enough, otherwise you will do such funny things. :D
Update:
https://imagemagick.org/script/resources.php
https://www.php.net/manual/de/imagick.setresourcelimit.php
putenv("MAGICK_THREAD_LIMIT=maxcores");
$image->setResourceLimit($image::RESOURCETYPE_THREAD, maxcores);
putenv("MAGICK_THROTTLE_LIMIT=limit");
putenv("MAGICK_TIME_LIMIT=sec");
These parameters can be used to speed up the process and set a timeout.
However, a limit must be set for conversions, database entries, or a JSON file.
This stores the current number of running conversions and the timestamp of the last one, deleting the value after the timeout period. Resetting after a certain time helps avoid errors during server restarts.
This was the only way I could prevent server overload due to multiple users.
However, it does require a few lines of code and is only useful in environments that need protection against such attacks or have a high number of users using this function.
The resolutions are stored in the database for each image, for whatever purpose I needed them back then.