Updated on 2024-02-09
Image Resizer automatically resizes images you drop in a monitored folder based on criteria you give it. It can also change image formats.
I love CodeProject. It's on my shortlist of favorite places on the Internet, and I produce a lot of content for this place. One thing I do not like about it is the insistence that article images be no wider than 640 pixels. It's a time sink. I finally did something about it by making a little utility, and generalizing the utility enough to be useful in scenarios other than preparing content for CodeProject articles.
The application is a .NET Framework 4.8 app since it relies on Windows specific features - mainly GDI+. Technically, it should run on Linux under Mono if you ditch WinForms, so some modification would be involved but the logic is all there.
Essentially you just run it, and choose a folder either by typing it in or browsing. Once you do, that folder is monitored for the entire time the application is running.
Under that folder, it looks for folders with particular names. Here's the grammar/format of the folder name in XBNF:
integer = '[0-9]+';
size = integer [ "x" integer ] | "x" integer ;
format = "." ("jpg" |
"jpeg"|
"gif" |
"png" |
"bmp" |
"ico" |
"emf" |
"wmf" |
"exif"|
"tif" |
"tiff");
folder<start> = ( size [ "_" size ] | "_" size ) [ format ]
There is a potential minimum size, maximum size and format.
Each size is an optional integer width, and/or an optional integer height (preceded by an "x")
The minimum size comes first, if indicated. The maximum size, if indicated comes next (preceded by a "_")
After that, if format conversion is required, put the extension, like ".jpg"
Examples (all preserve aspect ratio)
_640
(max width of 640)_640.jpg
(max width of 640, convert to jpg)320_640
(min width of 320, max of 640)320x200
(min size of 320x200)320x200_640x480.png
(min size of 320x200, max size of 640x480, convert to png)You can also have directory trees under these specially named folders, and all images underneath will be sized and formatted to the specification.
All the important bits are in Main.cs.
The main workhorse is the FileSystemWatcher which I've assigned to the selected folder in Folder.Text.
Whenever a file is created, basically we do a few things. First, we walk backward looking for a folder with the format as I specified above. It keeps searching ancestors until it finds one, or exits.
After that, we "crack" the file extension into an ImageFormat and if it returns MemoryBmp, we know it's not an image. I use that as a stand in fore "none" because it has no real disk format.
If it's got a valid image file extension, and we found an ancestor specification folder, then the magic begins.
We always preserve the aspect ratio so what we do is kind of weird. After loading the image and computing the ratio based on its Size, we proceed to "clamp" the new size (newSZ) to minimums and maximums as indicated.
Finally, if we had to change anything, we create a new bitmap from the current bitmap resized as indicated, saving it to either the original format, or a new format if specified. Finally, we delete the original copy of the file.
All of that happens in UpdateFile() which relies on the various _CrackXXXX() functions to parse values out of the strings.