Hello FME'ers
I'm writing this question-of-the-week for a number of reasons. It's something that is regularly asked (because perhaps it's not totally understood), it came up in a support question this week, and I've actually been working on a similar task myself this week.
The question is all about creating a transparent area around clipped raster data.
Question of the WeekThis week's question came from a case in our support queue:
Q) After clipping a raster feature to an ellipse shape, the surrounding cells have a value of 140. Why is that and how can I remove this?
A) A raster feature (file) can only be rectangular, so when you clip it to a non-rectangular shape, then the "outside" area must be represented in some way. This is done by "nodata" and so you can control what you see by controlling the raster nodata value. But in some cases, a transparency (alpha band) is better.
Â
Let's see why...
My Profile Picture ScenarioAs I mentioned, I was working on something similar this week too. I was taking user profile pictures for the community and working on a way to automatically add a circular border to them, like so:
The orange border signifies that I work at Safe.
But the important part for us is that if I start out with a square picture, then I need to clip it to a circle. That's what this part of my workspace does:
It creates an ellipse with the same radius as the rectangle and then clips out the outside of the ellipse. I would usually take the Inside data, although here I'm taking the outside port, for unrelated reasons.
Anyway, the important question is what value the clipped cells get? Right now, the Clipper will set them to nodata, but what is that and why does the user get a value of 140?
What is Nodata?The key part here is understanding what is meant by "nodata".
Nodata is not a unique non-value, but instead is a marker that denotes value n represents nothing.
In attribute data, an attribute can have a value (like 1, 2, 3, 4, 5, 6, etc) OR it can be Null. In raster data, a cell can have a value that is null. It's like saying "attribute value 5 represents null".
I don't have to have a nodata value, but if I do, then cells with that value are treated as nulls.
What does the Clipper do?As I mentioned, the Clipper sets the cells outside the clip boundary as nodata. If the user who asked about this is getting the value 140 for those cells, then it must be that 140 is the nodata value!
So the simple solution is to add a RasterBandNodataRemover transformer to the workspace:
Now the output of that will not be nodata, and it won't have the value 140.
Clipping Without NodataBut whether we clip with nodata or without, those cells still exist, and can't be completely empty. They must have a value of some sort and, by default, that value is 0 (zero):
That's OK, but in a colour image, zero means black, and we don't necessarily want a black border. At this point most user's thought is: what if instead of removing the nodata, I set it to 255? Then those cells would be white!
This is true. However, there are two drawbacks to this:
- I'm assuming that the background where I use the image will be white to match. It might not be.
- Other cells that are white will also get tagged as nodata.
The second issue there is really where nodata can be a problem, particularly for image data. I can set nodata to 255 so that cells around the outside are white. However, other cells that are white also become 'no data". Sadly, much of my hair is turning white, and while I'd like to think its values are around 200 instead of 255, some of my hair would become nodata.
So, what else can we do?
Clipping With TransparencyThe solution is to make use of raster transparency. Basically, a raster like this has three bands: red, green, and blue, so each cell has a red, green, and blue value that creates the overall colour.
We need to add a fourth band - an alpha band - to specify how transparent the data should be. We would set transparency to 0 (zero) on the outer area, but 255 on the main picture.
OK, how do we do this? We could use a RasterInterpretationCoercer to add this extra band, and at the same time convert nodata values to transparent. But then we have the same problem. If I make white cells around the border transparent, then I also make the white cells in the actual image transparent.
My hair would literally disappear - and I have little enough as it is!
So what I do is this...
Use a Mask!What I must do is simply mask out the part of the image I want to be transparent. In this case, it's the same shape as the clip boundary!
To explain, I take the ellipse that I created and - in a separate stream - rasterize it. I need to apply a colour, but it doesn't matter what colour. The important part is that the cells inside the ellipse get an alpha value of 255, but cells outside get an alpha of 0:
Then I select the RGB bands and remove them with the RasterBandRemover. This gives me a raster feature with a single alpha band:
In effect, it's a mask that I can apply by adding it to the main raster image. I do that with a RasterBandCombiner.
Now I have the output I want. A circular image that's opaque, surrounded by a completely transparent border - without flagging any of the image cells as being nodata or transparent.
SummaryI'm always unsure with raster data, perhaps because I still don't know if I fully understand it. But to me, if you want to clip a raster feature, and want the clipped pixels to be transparent, the best way to do it is to take the Clipper feature and turn it into an alpha mask.
Then that mask can be applied to the result of the Clipper without affecting any other part of the data.
If you want to examine my workspace, you can
Other Notable QuestionsHere are some other questions that I spotted this week...
- Can I license a transformer that I upload to the FME Hub?
- Yes, @jstanger, you can, using a non-copyleft open source license such as MIT, BSD, Apache, or CC-BY. However, you should not use a GPL or copyleft license. I don't know why, but that's what our in-house lawyer told me, so I'm not inclined to argue ;-)
- How can I find the next date that isn't a working day?
- So asks @ledger and @jdh responds that you can simply take the day of the week number and add 1 to it (if it's Sunday to Thursday), add 2 if it's Saturday, or add 3 if it's Friday.
- This reminds me of the WorkingDaysCalculator that I uploaded to the FME Hub, and I might actually update it to include this excellent idea for a new capability.
- Why is Google restricting access to my Gmail account through FME?
- It looks like Google is getting stricter about accessing services through third party products or APIs. @hollyatsafe comes to the rescue with a workaround until we can get FME cleared to access email, but other users mention that it might be time to get a proper email setup, and not rely on Gmail.
- How do I "rate" data that enters into a workspace?
- @freddy17 wants to know how to create statistics on data entering a workspace. Is there a better way than conditional attributes? Or could it be organized better using custom transformers or collapsed bookmarks to make the workspace tidier? If you have any suggestions, it seems an interesting question.