Image mummifiers need the ability to scale images if they are beyond some configurable threshold.
A user will likely want to dump a bunch of full-size, original images into the source tree without bothering to individually scale or otherwise manipulate them. But they probably don't want the full-size image being deployed to the size, primarily because of file size. Thus there needs to be some configurable threshold, probably based on file size, above which the image mummifier would automatically scale the image.
The Apache Commons Imaging seems like a new library that might eventually providing scaling and such, with independence from AWT. For the moment it's only in alpha and it's not immediately clear if it provides scaling yet.
Although I found an interesting history of aspect ratios, if we maintain the original aspect ratio when scaling down the aspect ratio of the constraining bounds is of little interest; if we want merely to constrain the maximum dimension of the image (not knowing in advance if it is in portrait or landscape orientation), then we can simply constrain to a square area that matches a resolution matching the higher range of modern monitors. Thus we can simply scale images down to a constrained square of 2560 x 2560. This will still give a good quality image and probably ensure that the image file is reduced somewhat.
In addition to scaleThresholdSize, we need to configure the width/height for scaling as discussed previously. Using "length" as a general term for geometrical extent, we can have a configuration scaleLength of 2560.
Perhaps it would be helpful to be clear that we are scaling to try to reduce file size:
I just realized that instead of mummy.page.namesBare we have mummy.pageNamesBare. 😮
But now that we are having artifact type-specific settings, mummy.page.namesBare may be more appropriate. I'll go ahead and use the separate mummy.image.scale… config settings for this ticket, and we may want to go back and change mummy.pageNamesBare to make it consistent.
We might also want to consider renaming the entire mummy section to mummify, which would correspond to the factoring out of the io.guise.mummy.mummify classes (e.g. for ….page and ….image), and also would be more consistent with the deploy section in the config. This might (or might not) mean that we would rename the in-source-directory .guise-mummy.turf file.
On the other hand, if Guise becomes a larger building, deploying, and even orchestration platform, then maybe the deploy config section (and in fact the entire deployment subsystem) might be split out into a separate subproject. Thus mummy would be an appropriate name for the config section, and we might even move the artifact types down to the io.guise.mummy level, e.g. io.guise.mummy.image and io.guise.mummy.page. If that happens then Guise project settings such as mummy.page.namesBare and mummy.image.scaleThresholdFileSize would make perfect sense. So let's stick with a mummy.image config section for now.
I'm thinking that the "length" as a general term for either width or height could be confusing. Moreover I'm reconsidering something I discussed above:
… if we maintain the original aspect ratio when scaling down the aspect ratio of the constraining bounds is of little interest; if we want merely to constrain the maximum dimension of the image (not knowing in advance if it is in portrait or landscape orientation), then we can simply constrain to a square area that matches a resolution matching the higher range of modern monitors.
While it is true that the aspect ratio of the end-user's monitor will not affect the aspect ratio of the scaled image, this does not necessarily mean that the dimensions of the end monitor is of no consequence at all. Put another way, it would be useful to know the typical width and typical height of monitors and their rough aspect ratio (insofar as it affects whether they are portrait or landscape). If most monitors are landscape, it would not be helpful to scale a portrait image down with extra height to accommodate landscape monitor widths.
But now that I think about modern displays, it's clear that many phones and tablets are portrait and have very high vertical resolutions, so we would not want to unnecessarily scale down portrait images thinking they would go on landscape monitors. Thus the original idea of scaling to a 2560 x 2560 area seems right after all.
Now I just need to decide for sure what to call it.
Wow, I'm impressed at the result! It's taking an ~8MB full-color 5467 x 3644 JPEG file and at 80% compression quality it's turning out a 2560 x 1706 file that's only ~330K. If you zoom in a lot you can see some JPEG blocky effects, but at that resolution I wouldn't expect it to be noticeable on a normal screen, and especially not on a mobile phone. This is really good—better than I expected, especially since I haven't worked with this image scaling code in well over a decade.
It's tempting to want to lower the default scaleMaxLength down to 1280 because that would undoubtedly bring a big savings in file space. But in worldwide desktop screen stats a width of over 1280 pixels is almost ubiquitous. And photo sites such as Flickr have lightboxes that show full screen on big monitors. So at least 2560 is probably best. Maybe another approach would be to add some facility for automatically generating preview versions of only 1024 or something. We would need to work out how we indicate whether previews are generated or not.
Already there is some sort of a semantic overloading of scaleThresholdFileSize as a toggle for reducing photo size, with a toggle for general photo processing. Maybe we should change this to be processThresholdFileSize as a threshold for general processing. The idea is that we only want to process big images; presumably the smaller images are of a different type or role (icons? previews?) and area already "the way we want them". This processThresholdFileSize might be the most typical way to turn on image processing across the board, but may be too coarse in some cases; another way to turn processing on or off for individual images would be useful. The scaleMaxLength setting would also make more sense, as we may want to process the image but may wind up not scaling it if it is already small enough.
This new way of looking at the toggle will fit will with the realization that we probably need to update the destination metadata of the scaled images. In the current development implementation, all metadata is being stripped.
As discussed in GUISE-169, here are some sample image compression sizes, assuming embedded metadata and a max scale length of 2560:
Dropping down to a max scale length of 1920 drastically reduces the image size:
2560 Quality 0.8
2560 Quality 0.6
1920 Quality 0.8
1920 Quality 0.6
As 1080p is 1920x1080, and WUXGA is 1920x1080 (see TV resolution confusion: 1080p, 2K, UHD, 4K, 8K, and what they all mean), it might be beneficial to drop the default scale settings to a scale length of 1920 and a compression quality of 0.6. If more and more people have 4K displays, users can always change the settings (or we can raise the defaults) and regenerate the images.