Tutorial 3.1

This tutorial shows a small example of color-correcting in Shake, and using the Pixel Analyzer to help you*. It also relies on Z compositing, so it shows you how you can manipulate Z channels. The first step will be the Z composite, and then the color-correction. At the end, we add in some fog to point out the importance of color-correcting un-premultiplied elements.

*Because of new functionality in Shake 2.2, the use of the Pixel Analyzer in this tutorial is obsolete. You can instead use the new Color Pickers to color correct your element. However, we have retained the section on the Pixel Analyzer as it is still a helpful tool.

The Composite

Most composite nodes are dependent on the RGB and Alpha channels to calculate the final composite. For Z compositing, we use a fifth channel, the Z channel, that orders pixels according to a certain depth from the pixel plane. Generally, these Z channels are generated with a 3D renderer. Z channels are simple to generate, since every pixel has a certain distance from the camera. When mixing two Z channel images, (usually) the image with the lower Z value at that pixel is taken. Z channels are sometimes rendered into the same file as the RGBA, or may be saved out into a separate file and later copied in during the composite with a Copy node using z as your channel . We are using the latter technique, because we have saved the RGB and Alpha images as jpg format images to cut down on size, and because it is the more complicated situation. If it was easy, I wouldn't bother explaining it.

RGB: dir.jpg (from 3D render) RGB: nyc.jpg (from scan)
Z: dir_z.iff (from 3D render) Z: nyc_grey.jpg (hand-painted)
Alpha: dir_a.jpg (from 3D render) Final Composite

Why did I use a ZCompose? With about 100 ships in the air, I would have to have re-created my cityscape in 3D and created a 3D mask in my render. If my camera was moving, this would have been the most practical solution in the long run. However, since the background plate is static, it seemed more practical to fake the Z with a hand-painted mask. By using Z, we get the dirigibles going both in front and behind the buildings, as in this close-up:

 

So, now to set up the Z composite. The first thing to do is to read in the images. You can do this one of two ways:

  • Open up Shake, and create a FileIn, looking for all of the images in doc/pix/nyc. Shift+click on the following images, and hit OK:

    dir.jpg, dir_a.jpg, dir_z.iff
    , nyc.jpg and nyc_grey.jpg.

    Because you used Shift+click, all 5 are read in as separate FileIns.

  • The second, alternate way to do it, is to use the command shell to open up Shake. Go to doc/pix/nyc, and then type

    shake *.jpg *.iff -gui

    This uses the UNIX wildcard (*) to pick all files ending in ".jpg" and ".iff", and loads them into the gui with -gui. Don't load everything in the directory, since there are example scripts in here as well. If you didn't append -gui, you would be looking at the five images on the monitor, using Shake as a viewer.

Go in and rename each node if necessary according to its file name. You should now have a tree that looks like this, more or less:

Preparing the Z Channel for the Dirigible

If you look at each image, you will see that dir_z is black. That is because the Z information is not visible in the Viewer. You can, however, see that there is a Z channel in the image by observing the Viewer title bar - it should have a Z on it to indicate the presence of a Z channel. Normally, values go from 0 to 1. The Z values can be any number. My dirigible values happen to range from about 0 to 255, meaning, try to have good lines of communication with the 3D Department, which also happens to be me at Nothing Real. If you want to see what the Z channel looks like, you can temporarily attach a Key - DepthKey node to the Z image, and then look at the alpha channel in the Viewer. Move the hiVal slider from 75 up to 250 with the virtual sliders (Ctrl+drag horizontally in the numeric text field).

You should now have an image with black foreground dirigibles and fading off to white in the background. Does this seem like a pain right now? You bet! This Z viewing functionality will be in the Viewer later on.




Don't do this part...
As a curious side note, you could put a
Mult after a Reorder of zzza, and place 1/255 in the red, green, and blue channels of the Mult, but you will basically get black, because 8 bits and 16 bits per channel get clipped at 0 and 1. This means every value above 1 gets clipped to 1, which is then multiplied by .0039, making the image black. You would have to insert a Bytes command before the Reorder, and boost your bytes to 4 (32 bits per channel). 4 bytes allows you to retain values below 0 and above 1. Your tree would look like this sample. This paragraph is really just one big long-winded digression...


ANYWAY... We now copy the Z channel into the RGB image of the dirigibles with the Layer -Copy command. Enter z as the channel you want to copy. Make sure the node dir_rgb is the first input to the Copy command. This means you are copying the z channel from dir_z into dir_rgb. You should see a Z on the Viewer title bar.

Since we read in a jpg as our source image, dir_rgb has no alpha mask, which is why I included dir_a in the project as well. Normally, the alpha mask would be embedded in the same file, unless it was a Cineon image. This next step copies the luminance of dir_a into the alpha channel of dir_rgb.

 




Clicking on dir_a, you can see it is a BW (black-and-white, or one-channel) image without an alpha channel. We could use Reorder (rgbr) to place the red channel into the alpha, and then copy that over with Copy (a), which is similar to what we did above. However, we have saved you a step by creating the Layer - SwitchMatte function, which is essentially a macro of Reorder and Copy. This function allows you to copy any channel from a second image into the first image's alpha plane. If you want to copy any channel in one image to any other arbitrary channel in a second image, use a Reorder and then a Copy.

For the parameters, I use r as the source channel. One could argue that r isn't really a valid channel in a black-and-white image, but it is, however, the first channel, making it eligible here. We also turn matteMult off, since the 3D render already multiplied the RGB channels by the alpha channel. I simply stripped out the mask to create smaller files for a smaller e-mail burden. My little part to help humanity. If we had left matteMult on, the RGB channels would have been multiplied twice by the alpha channel - once by the 3D render, once by Shake.

This would be bad.

 


Preparing the Z Channel for the City

Now we prepare the Z channel for the New York City image. Since this was a scan, I didn't have either an alpha channel or a Z channel. Instead, I hand-painted one with not-very-scientific precision. Whereas the dirigible element had a specific Z channel with ranges from 0 to (about) 200 already prepared that had to be copied in, in this case we will be copying in a normal black-and-white image as the simulated Z channel. The only difference is that the values of this channel, since it is 8-bit, will range from 0 to 1.

To copy the channel, I first attach a Reorder and an Invert node. The Reorder parameter is rgbar, which places the red channel into the Z position. I use the Invert to invert the Z channel. If you look at the sample images at the top of this tutorial, you will see that dirigible Z image fades to white, and the city Z image fades to black. I therefore have to flip one of them. I can't flip the dirigible image because its Z range goes beyond 1, and Invert will only properly invert the Z channel if it is normalized (i.e., between 0 and 1). Therefore, I place it here on the city image. I finally use Copy to copy the Z channel from nyc_z to nyc_rgb. Keep in mind that nyc_rgb is the first image in the Copy command. Again, don't forget to place the Z in the Copy command.

Once again, there is absolutely no visual indication that you have succeeded except the Z in the Viewer title bar unless you attach a temporary DepthKey and look at the new alpha channel.

 





As a final step, I want to add an alpha channel to the nyc_rgb image. I click on nyc_rgb, and insert a Color - SetAlpha. That sets the alpha to 1.

 

Doing the ZCompose

Our Z channels are in place. We can do the ZCompose. This function takes two images, and takes the rgba pixels by comparing which image has the lower Z value. Therefore, order does not matter when doing a ZCompose. OK, after all of that buildup, you are going to be disappointed to see that the composite is only of the city - no airships in sight. Great. What a fine tutorial. If you will recall, the dirigible Z values range from 0 to about 200. The NYC range is from 0 to 1. That pretty much guarantees that the nyc image is always going to be in the foreground, since 1 is less than 200. What we have to do is multiply the the Z value to make it fit the same range as the dirigibles. You are really going to like this, by the way.

 

Click on Copy1, and insert a Color - Mult after it. While looking at ZCompose1, move the depth slider of the Mult up to around 200. It looks really snazzy when you use the virtual slider (Ctrl+drag in the depth text field). You should see all of the dirigibles gradually pop into view. I set my value around 204.

I have stored the script so far as zcomp.shk in the pix/nyc directory.

 

Using the Pixel Analyzer to do a Color Correction

You may have noticed that, gee, the blimps are black and white in the middle of a fine smoggy red sunset. To help blend them in, insert a Color - Compress function between SwitchMatte1 and ZCompose1, so it will affect only the blimps. This squeezes the blacks and whites into an orange range. Use the Color Picker buttons in the Compress node to select high and lo colors from the screen. Just push the appropriate button, and select from the new color you want from the screen. For example, click on the High Color color picker button and select a highlight. The brightest spot on the background is a glint of the sun on the Chrysler building. Then do the Low Color and pick a shaded area.

The following information is obsolete for the purposes of this demo, but the Pixel Analyzer is still a useful tool, so we have kept the information here for your reference. Jump to the end of this section to continue with the tutorial.

 



To help us find the correct color values, I will use the Pixel Analyzer, located on a tab in the same space as the Node Workspace. Just click on it to jump to the Pixel Analyzer.

I first want to choose my highlights. The brightest spot on the background is a glint of the sun on the Chrysler building. I want to get the values of that highlight. If you just drag across the image, the values will show up in the Analyzer. Click on the Min, Max, Average, or Current buttons to get that value.

Notice as you go over different shaded pixels how these boxes update.

  • If you switch Mode from Pixel to Image, it will return the Min, Max and Average values of the entire image. Switching back to Pixel will bring you back on a per-pixel basis.
  • You can change the numeric values from 0 - 1 to 0 - 255, 0 - 1023, etc. You can also toggle on Hexadecimal values as well, which will of course give combinations of letters and numbers.
  • By default, the Min, Max, and Average calculations are based on the luminance, as indicated on the Min/Max Basis buttons. You may be concerned with a separate channel, like red, in which case you would get a different result. For example, if the basis was r (red), a pure bright green pixel will be considered darker than a dark red pixel, since it has no red component. Therefore, if you are interested in the Min, Max or Average red value, toggle over to r in Min/Max Basis.
  • By toggling Accumulate, the Average button will accumulate values as you drag. To reset this accumulation, hit Reset.

Since I am picking the highlights, I drag the cursor over the highlights (remember you can zoom in by pointing the cursor to a spot in the Viewer, and then pressing -/+ by the Backspace key). I then click on Max, and enter the R, G, B values into Compress1's rHi, gHi, and bHi.

I now want to set the lows. To do this, I turn on the Accumulate button, and drag on the dark side of the foreground buildings. I've turned on Accumulate because the scan pattern has introduced a lot of noise. This way, I can get the accumulated average of the pixel values. Once I have these low values, I click on Min, and enter the R,G,B values into Compress1's rLo, gLo, and bLo.



If you look closely, you will see a ringing around the edges of the airships. This is a great example of what can happen if you color-correct an element that is already pre-multiplied by its mask. There is a simple workaround. We insert a Color - MDiv before the Compress, and then insert a MMult after the Compress. This means we are doing a color-correction on non-pre-multiplied element, which is theoretically the proper way of doing things.

Bad Color Correction on pre-multiplied element Good Color Correction on un-pre-multiplied element

If you wanted to do further color-corrections, you would do it in between MDiv2 and MMult1.

 

Reducing the Scan Pattern on the Background.

A final touch is to help reduce the nasty pattern on the background from the scan. This isn't perfect, but we can reduce a great deal of it with the Median filter. This is a good filter for getting rid of single pixel irregularities and holes, or, scan patterns.

No Median filter With Median filter

The script has been saved as cc.shk in pix/nyc.

 

Adding Fog to the Dirigibles

Without Fog With Fog

In this last step, we add some depth cueing by mixing in some of the background color according to the depth, simulating a fog. Insert a Layer - KeyMix after the Compress, making sure it is before the MMult. Mix into that an Image - Ramp, and a DepthKey coming out of the dirigible's Z image, dir_z. To create the ramp, I use the Pixel Analyzer to sample dark and light areas of the nyc_rgb image, and enter those as my ramp values. In the KeyMix, I make sure I am using the alpha channel of DepthKey1 by entering a as the channel. Finally, I adjust the depth parameters in DepthKey1, setting hiVal to around 208 - you could, of course, use the one you created earlier.

This script is saved as fog.shk.

Mix this... and this... with this.