To Everything - turn, turn, turn
Written by @marcemarc on Monday, 01 May 2017
uSpinMeRightRoundBabyRightRoundLikeARecordBabyRightRoundRoundRound or
uSpinMeRightRound for short… is a package that adds the functionality to rotate the orientation of an image once it has been uploaded into the Umbraco Media Section.
You can see a video here that shows it in action:
Why the plugin?
You’ve probably not noticed that a 'rotate option' is actually missing from the back office of Umbraco, this is because uploaded images are ‘auto-rotated’ to be the right way up, based on their exif data etc I think, and using Image Processors AutoRotate functionality... so why would an editor ever need to rotate an image in the back office?
Well if you are bulk uploading images it seems like sometimes the auto-rotate doesn’t kick in and also if you are uploading scanned images from a flatbed scanner like in the olden days then there isn’t the orientation data to auto-rotate by, or perhaps if you are like me and could never fathom how to put the document around the right way, (same with manually doing double-sided printing).
Anyway if you are cohabiting that Venn diagram overlap of niche circumstances then it’s super helpful to have a rotate option in the back office, and it saves you from downloading, spinning it around in some other image manipulator and having to re-upload the corrected version.
How do I work it?
Choose 'rotate' from the action menu
See preview of options for rotating the selected image in 90-degree turns
Select rotation option and click rotate…
(you can replace the crow spinning image at /app_plugins/tooorangey.uSpinMeRightRound/spinner.png)
Correctly orientated image.
And that is it. (although there is an option to create a new media item for the rotated image if you so desire)
How does it work?
This is, of course, standing on the giant shoulders of James M South and Image processor that ships with Umbraco now. Image Processor has a 'rotate' option built-in (a wrapper around System.Drawing) that is of course super-easy to use. However in generating the preview images of how the image will look in the various rotated states, I hit a problem in that I wanted to just add ?rotate= on the querystring, but the rotate processor is turned off by default (for good reason) in Umbraco and I didn't want to enable it for all 360 degrees for all images on the front end of people's websites just to do the previews for these three rotated positions in the plugin.
So I created a new Image Graphics Processor called ‘pirouette’ that will only accept a number of quarter-turns, 1, 2 or 3.. (I'm aware that pirouette means one full turn doh!)
Again, nods to Mr M South as this is just as simple as creating a class that implements his IGraphicsProcessor interface.
public class Pirouette : IWebGraphicsProcessor { /// The regular expression to search strings for. /// </summary> private static readonly Regex QueryRegex = new Regex(@"pirouette=[1|2|3]", RegexOptions.Compiled); //etc
and add details of the processor to the processing.config file:
<plugin name="Pirouette" type="tooorangey.uSpinMeRightRound.Processors.Pirouette, tooorangey.uSpinMeRightRound" enabled="true" />
(It’s only since Umbraco 7.5 that the additional Image Processor configs have been shipped, so if you want to use this package pre-Umbraco 7.5 you’ll need to install the Image Processor config NuGet package – here…..)
Rotating the image
The actual rotating and resaving of the image back into Umbraco is done via a back office only UmbracoAuthorizedApiController, when you select the number of turns in the UI this instruction is sent to the Api, and we use Image Processors' ImageFactory class to perform the rotation. There is a save method that enables you to save the new transformed image into a memory stream, which is just what Umbraco's media file service likes to get hold of to add images to wherever it is Umbraco is configured to store them. So I have a feeling this will work in the cloud…
var imageToRotate = imageFactory.Load(fullPath); var ms = new MemoryStream(); imageToRotate.Rotate(turns * 90).Save(ms);
But the tricky part here was trying to avoid file locks, eg what if the image you are trying to rotate is being displayed by IIS on site and locked - I think I've worked around this by always renaming the file with –rotatedX on the end of the filename, where X is the number of turns, this avoids the locks, and sort of also means if I’m doing something really bad here I haven’t mucked up the original image!
(If your having one of those days, perhaps your Umbraco site is powering an art gallery of conceptional art and it’s not clear which way around the picture should be anyway, and you keep rotating and rotating the image around in circles, then if the rotation for that number of turns already exists on disc, uSpinMeRightRound will use that instead for the media item.)
I’ve just realised in typing this that there is probably an edge case here if you have the text '–rotated1(2or3)' naturally somewhere in the name of your image file – well I’m sure it will be fine…
Finally, there is an option to create a new media item inside Umbraco with the rotated image keeping the original in place – the trick here is to make Umbraco think that the memory stream is an uploaded file by implementing a wrapper class that inherits from UploadedFile base class.
public class MemoryStreamPostedFile : HttpPostedFileBase { public MemoryStreamPostedFile(MemoryStream ms, string fileName) { this.ContentLength = (int)ms.Length; this.FileName = fileName; this.InputStream = ms; } //
and well
Anyway, it’s a first-release, there are improvements to be made (image selecting UI and making text translatable, but let's see if it’s of any use to anyone first).
uSpinMeRightRound is on github
Umbraco package is here
Nuget: Install-Package tooorangey.uSpinMeRightRound
Thanks to James M South for Image Processor and very helpful suggestions.