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

(New and Improved) Image > Resize tool #361

Merged
merged 24 commits into from
Aug 24, 2021
Merged

Conversation

tannerhelland
Copy link
Owner

This feature has been in the work for several years now: PhotoDemon's Image > Resize tool is fully redesigned with a host of exciting new features, including...

  • Live previews! This makes it much easier to see how different resampling algorithms behave. I am not aware of any other free photo editors that provides this tool (and even Adobe didn't do it until Photoshop CC). Why do so few programs provide this? Because it's horrifically complicated and nasty to develop, of course! Fortunately, I'm a glutton for punishment... 😭
  • A new image resampling engine, custom-built for PhotoDemon, provides 12 - that's right, 12 - different resampling filters. These filters perform very well (5-6 megapixels per second on old hardware), have very low memory requirements, and with the new "live preview" window, you can immediately compare their results to ensure you get the highest-quality up- or down-sampling for your image. (Many thanks to Libor Tinka, whose open-source CodeProject article inspired PD's implementation: https://www.codeproject.com/articles/11143/image-resizing-outperform-gdi)
  • The Resize dialog is now resizeable, and the preview window will auto-resize to fill the available area.
  • The Resize now tells you how big the new image will be (memory-wise) vs its original size, e.g. "200 MB, was 1.7 KB". This is another feature cribbed from Photoshop's design, for better or worse.
  • Resizing is so fast you probably don't need this, but resize operations now correctly update the progress bar while processing. (Old solutions relied on 3rd-party libraries that didn't provide progress updates.)
  • All of the above improvements are also available in the Layer > Resize tool.

I'm quite pleased with the new dialog, especially given that this might be the most-used tool in the entire project for many users. PD's custom-built resampling engine is especially exciting IMO, with higher quality and better performance than pretty much all of the competition.

PD has historically used either built-in Windows libraries (GDI+) or the 3rd-party FreeImage library for image resizing.  This provided nice coverage of standard image resampling algorithms, with good performance to boot.

But sometimes we want even *better* quality than what a 3rd-party library can provide.  That's the goal with this branch: to finally provide a comprehensive, native-to-PhotoDemon image resampling library.

My work here is heavily based on an original image resampling library shared by Libor Tinka:

https://www.codeproject.com/Articles/11143/Image-Resizing-outperform-GDI

Many thanks to Libor for sharing his work under a liberal license.

This first draft is a very rough translation of the original C# source, with myriad changes for VB compatibility and/or performance quirks.  I expect many more changes will be necessary to get this adequately working in PD, but at least this is a start.
Initial tests show things working well, but the test matrix for a feature like this is very large... lots more to do!
This was supposed to already be enabled (as it's a convenient remap for Ctrl+Shift+V to paste an initial image into a session), but an oversight was preventing it from working.  Sorry!
All resampling methods are now *always* available, regardless of FreeImage availability.  If FreeImage is available and certain conditions are met we will still use their algorithms as they're faster (for now), but after I work harder on optimizations, that may change.
- Improved remapping of legacy resize operators
- Fixed the way the batch convert tool relays resize commands to the resampler
- Directly expose option for "approximate" resampling pathways; on some algorithms, this can greatly improve performance at a minor hit to quality
- Automate retrieval of resampler names for UI elements (this is future-proofing against future expansion)
- Migrate resampling macro format to future-proof string representations instead of hard-coded ordinals for various algorithms
- Rework mapping of all resampling options to support new features
- Manually free shared resampling cache after resampling completes
…ection

We can completely bypass a resampling pass in the opposite direction, doubling performance.
Progress bar display during resize hasn't historically worked, because 3rd-party libraries (like GDI+) were handling the resize for us and they don't report progress.  But PD's new internal resamplers fix this!

(Note that the behavior is slightly different when resizing an image with many layers - in this case, the resampler instead uses the number of layers completed as the progress bar tracker, instead of reporting progress on just the *active* layer)
(shlwapi is used for size string formatting)

This mirrors similar behavior in Photoshop, and is now available in all of PD's size dialogs.
- All resampling operators are finally sorted in an intelligent way (grouped by increasing sampling radius, which translates pretty cleanly to performance).
- Lanczos resampling (which provides the sharpest results, typically) now lets you manually specify radius for a deeper quality vs performance trade-off
- unused code and UI elements have been removed from the resize dialog, and the remaining items have been reflowed
- mapping between GDI+, FreeImage, and our new internal resampling engine is now smarter, including in Automatic mode
No dialog was actually consuming these notifications until now, so I didn't notice this before - but now, pdResize will check to ensure that a change has actually occurred (e.g. width/height in pixels has changed) before raising a Change event
Downsampling in particular has received some nice performance tweaks.  The resampler now works great as a standalone resize tool - the remaining challenge is to make it fast enough for real-time previews (sigh).
Previews for this tool have to be designed (and coded) from scratch because they bear no similarity to other effects and adjustments.  That makes this challenge considerable, which is why no other photo editors (aside from the latest editions of Photoshop, I suppose) have attempted it.

I've got this first pass working OK, but there's a lot left to do.  Performance is the biggest challenge, since downsizing a huge image requires processing of pretty much the full source image in order to produce a useful preview.  I have some ideas for improving performance, but they're all complicated and not-guaranteed-to-work... but hey, at least this first step is pretty cool!
This tool is proving difficult to profile accurately, in part because it allocates memory all over the place so cache pressure dominates timing concerns.

Ignore the many commented-out timing bits; I still need those but want to focus on some more prominent performance issues first.
This should be *much* faster than the floating-point version, but I am getting insane measurements on my Ryzen laptop.  Time to try it on some Intel PCs to see if the results change...
This was a real surprise to me, but basically mistyping a single multiplication factor from an integer value to a floating-point value resulted in a 10+X performance hit on my little Ryzen-2 laptop (150 ms to 1.7 seconds).  Sheesh.  I hope I haven't made mistakes like that elsewhere in the project...

Anyway, the cool thing about fixing this is that the new integer-only resampler is 2x faster than the old floating-point one, with no noticeable quality difference!  I'm committing this little fix now because I'm about to attempt a further rework for even better performance.  If *that* works, I'll extend these fixes to the y-direction as well for another small boost.
PD now provides two internal resampling engines for resizing an image: a "perfect accuracy" floating-point-based one, and a "nearly perfect accuracy" integer-based one.  The integer-based one produces results that are 99.8 to 99.9% identical (via PSNR) and it has 2x or better performance on modern CPUs, with even larger gains on older CPUs.  There's really no reason (outside of theoretical curiosity) to not use the integer version, but PD allows users to toggle this using the already existing "allow optimizations" checkbox on the resize dialog.  (Note that for the "live preview", the integer-based transform will always be used due to performance considerations.)

I've got one last potential optimization to try and improve live preview performance, but it will be preview-mode-specific.  The resampling engine itself is pretty much finished and ready for prime-time (barring a bit of static analysis to remove unused variables).
As mentioned in previous commits, the preview box in this dialog needs to be completely custom-built, so little features like this have to be reimplemented from scratch (ugh).

Also in this commit are some UI clean-ups, a refactor of the way previews interact with the "fast" mode toggle, and... I'm officially dropping FreeImage's resampling engine entirely.  It's barely faster than PD's custom-built engine, and it requires more memory (since FreeImage allocates its own buffers, and we have to copy our data into/out of those buffers).  These trade-offs no longer make sense given the quality and performance of PD's new pure-VB resampling engine, so I'm deactivating FreeImage's resize interop in production builds.  (The curious can still re-enable this via a constant at the top of FormResize, if they want.)

The resize dialog has also been made resizable, and the preview area automatically "grows" to match the area of the resized window.

With this, I think the new Resize tool is ready for merging!  I'm very excited to get wider testing on this feature, as it's a rare accomplishment to have live previews of resampling in a free photo editor.  (To my knowledge, only Photoshop provides previews of image resize operations - and even then, they only added it in Photoshop CC.  I am not aware of any free photo editors that provide something similar... until now, hehe)
@tannerhelland tannerhelland merged commit 973852b into master Aug 24, 2021
@tannerhelland tannerhelland deleted the advanced-resize branch August 24, 2021 04:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant