<?xml version='1.0' encoding='UTF-8'?>

<?xml-stylesheet href="./_c74_tut.xsl" type="text/xsl"?>
<chapter name="Tutorial 3: Math Operations on a Matrix">
<setdocpatch name="03jMathOperations" patch="03jMathOperations.maxpat"/>

<previous name="jitterchapter02">Create a Matrix</previous>
<next name="jitterchapter04">Controlling Movie Playback</next>
<parent name="jitindex">Jitter Tutorials</parent>



<h1>Tutorial 3: Math Operations on a Matrix</h1>
<p>This tutorial shows how you can perform simple mathematical operations on the data stored in a Jitter matrix. We'll show you how to use the <o>jit.op</o> object to perform arithmetic scaling of matrix cells, or of individual planes within those cells.</p>

<p>The tutorial patch is split into three simple examples of mathematical operations you can perform with the <o>jit.op</o> object. The <o>jit.op</o> object performs mathematical operations on entire matrices of data at a time rather than individual numbers.</p>
<illustration><img src="images/jitterchapter03a.png"/>Adding a constant value to all cells in a matrix.</illustration>

<p>The first example shows a <o>jit.matrix</o> object hooked up to a <o>jit.op</o> whose output is viewable by a <o>jit.pwindow</o> object. Every time you change the <o>number</o> box hooked up to the right inlet of the <o>jit.op</o> object a <m>bang</m> will put out a new matrix from the <o>jit.matrix</o> object. As you can see from its arguments, the <o>jit.matrix</o> object is generating a 4x3 matrix of single-plane <i>char</i> data (i.e. data in the range 0-255). The <o>jit.pwindow</o> object will visualize this matrix for you as a greyscale image. Dragging the <o>number</o> box will change the level of grey shown in the <o>jit.pwindow</o> from black (<m>0</m>) to white (<m>255</m>).</p>
<p>It's important to realize that the <o>jit.matrix</o> object is putting out a Jitter matrix that has all its cells set to 0. If you were to connect the <o>jit.matrix</o> and <o>jit.pwindow</o> objects together and bypass the <b>jit.op</b>, you would see a black image, no matter how many times you send a <m>bang</m> message to the <o>jit.matrix</o> object. The <o>jit.op</o> object is <i>adding</i> a value (as defined by the <o>number</o> box) to all the cells in the Jitter matrix sent between the <o>jit.matrix</o> and the <o>jit.op</o> objects. </p>

<h2>Operation @-Sign</h2>
<p>We said above that the <o>jit.op</o> object <i>adds</i> a value to all the cells in its input matrix. The <o>jit.op</o> object adds a value (rather than, say, dividing or multiplying) because of the argument to its <m>op</m> attribute (written <m>@op</m> in the object). The argument following <m>@op</m> is a symbol (or a list of symbols, as we'll see in a moment) that defines what math the <o>jit.op</o> performs on its input matrix. In this case, we can see that the <m>op</m> attribute is set to the value of <m>+</m>, which means that it performs simple addition on any matrix that arrives in its left inlet. The integer value in the right inlet is added to all the cells in the matrix. This value is referred to as a <i>scalar</i>, because it adds the same value to the entire matrix (in <i>Tutorial 9</i> we show how <o>jit.op</o> can do math using two Jitter matrices as well).</p>

<div>
<techdetail><b>Important note:</b> Changing the scalar value in the right inlet of the <o>jit.op</o> object does not output a new matrix. If you were to disconnect the patch cord between the <o>number</o> box and the <o>button</o> object, the <o>jit.pwindow</o> object would stop showing you anything new. The reason for this is that as with most Max objects, most Jitter objects only output data when something comes into their leftmost inlet. In the case above, each time you change the <b>number box</b>, the <o>jit.op</o> object stores the new scalar value. As soon as that happens, the <o>button</o> object sends a <m>bang</m> to the <o>jit.matrix</o> object, causing it to send a new Jitter matrix (with all its values set to 0) into the left inlet of the <o>jit.op</o> object, triggering an output matrix which you can see. If you put a break-watchpoint on the patchcord above the button and then step through the message order with the <b>Step</b> command (shift-cmd-T), you will see how this plays out. (See <link name="basicchapter05" type="tutorial" module="max">Max Tutorial 5: Message Order and Debugging</link> for details about how to trace Max messages with the watchpoints feature.)</techdetail>
</div>

<p>The scalar value can also be supplied as a constant by using the <m>val</m> attribute of <b>jit.op</b>. For example, if we always wanted to add <m>134</m> to all the cells of an incoming Jitter matrix, we could use this object and dispense with the <o>number</o> box:</p>

<illustration><img src="images/jitterchapter03b.png"/>Setting a scalar as an attribute.</illustration>
<p>Similarly, if we wanted to change the mathematical operation performed by any given <o>jit.op</o> object, we could send the message <m>op</m> followed by the relevant mathematical symbol into the object's left inlet.</p>

<h2>Math Operations on Multiple Planes of Data</h2>
<p>The second example shows a more complicated instance of using <o>jit.op</o> to add values to an incoming matrix.</p>

<illustration><img src="images/jitterchapter03c.png"/>Using separate scalars for each plane of a matrix</illustration>

<p>This patch is similar to the first one, with the important difference that we are now working with a 4-plane matrix. This is shown by the first argument to the <o>jit.matrix</o> object that generates the matrix we're using. The <o>jit.pwindow</o> now shows things in color, interpreting the four planes of Jitter matrix data as separate color channels of alpha, red, green, and blue. Our <o>jit.op</o> object in this example has a list of four symbols for its <m>op</m> attribute: each symbol sets the mathematical operation for one plane of the incoming matrix. In this patch we're going to pass the first (alpha) plane through unchanged, and add numbers to each of the other planes. (You can mix and match operators like this to your heart's content.)</p>
<p>The <b>pak</b> object feeding the right inlet of our <o>jit.op</o> object takes four integers and packs them into a list. The only difference between <o>pak</o> and the Max <o>pack</o> object is that <o>pak</o> will output a new list when <i>any</i> number is changed (unlike the <o>pack</o> object, which needs a new number or a <m>bang</m> in the left inlet to output a new list). The four numbers in the list generated by <o>pak</o> determine the scalars for each plane of the matrix coming into the <o>jit.op</o> object. In the example above, plane 0 will have nothing added to it (the first argument of the op attribute is pass). Planes 1, 2, and 3, will have 161, 26, and 254 added to them, respectively. Our <o>jit.pwindow</o> object will interpret the cells of the output matrix as lovely shades of magenta (even though we see only one color, there are in fact 12 different cells in the matrix, all set to the same values).</p>
<b> </b>
<div>
<techdetail><b>Important Note:</b> If we decided to use only one value for the <m>op</m> attribute of the <o>jit.op</o> object above (and only used one number as a scalar), <o>jit.op</o> would use that mathematical operator and scalar value for <i>all</i> planes of the incoming matrix.</techdetail>
</div>
<h2>Modifying the Colors in an Image</h2>

<p>The third example shows a use of <o>jit.op</o> on a matrix that already has relevant data stored in it:</p>
<illustration><img src="images/jitterchapter03d.png"/>Multiplying individual planes with scalars</illustration>

<bullet>Click the <o>message</o> box <m>importmovie</m> <m>colorbars.pict</m>. The <m>importmovie</m> message to <o>jit.matrix</o> loads a single frame of an image from a picture or movie file into the Jitter matrix stored by the object. It will scale the picture on the disk to the dimensions of its own matrix (in this case, 320 by 240).</bullet>
<p>Clicking the <o>button</o> object shows you image calibration colorbars in the <o>jit.pwindow</o> on the right of the patch. In this case, our <o>jit.op</o> object has its arithmetic operators set to <m>pass</m> for the alpha plane and  <m>*</m> (multiply) for the other planes. Since we're working with a 4-plane image, we set each of the scalars using a list of 4 floating-point numbers. Values of 1. in planes 1 through 3 will show you the image as it appears originally:</p>

<illustration><img src="images/jitterchapter03e.png"/>All scalars at 1.</illustration>

<p>If you set the scalars to 1., 0., and 0., you should see the following image:</p>

<illustration><img src="images/jitterchapter03f.png"/>The mean reds.</illustration>

<p>All of the planes (except plane 1) of the matrix containing the colorbars have been multiplied by 0. This will eliminate the alpha, green, and blue planes of the matrix, leaving only the red (plane 1) behind.</p>
<p>Setting intermediate values (such as 0., 0., 1. and 0.5) as the scalars for <o>jit.op</o> will give you an image where the colorbars look different:</p>

<illustration><img src="images/jitterchapter03g.png"/>Pretty, isn't it?</illustration>

<p>In this case, the alpha channel is ignored and the red channel is zeroed. The blue plane's values are all half of what they were. The green channel (plane 2) is left untouched. </p>
<div>
<techdetail><b>Important Note:</b> Some mathematical scalars in <o>jit.op</o> are expressed as floating-point numbers, and some are expressed as integers. This depends on the relevant operator (defined by the <m>op</m> attribute), as well as the <m>type</m> of the input matrix. Since all the examples in this tutorial use <i>char</i> matrices, it makes sense to use integers when adding to them (any floating-point numbers will be truncated, as the matrix data needs to remain as integers in the range 0-255). If we were using a <m>float32</m> matrix as our input, it would make perfect sense to add floating-point numbers to it. Similarly, it's reasonable to multiply a <i>char</i> matrix by a floating-point scalar (240 * 0.5 = 120, an integer). However, since the matrix output by <o>jit.op</o> will still be a char matrix (see note below), you will still only get values in the range of 0-255.</techdetail>
</div>
<p>If you experiment with the scalar values you will see that you can easily make some of the colorbars disappear or merge with neighboring bars. This is because the colorbars are all set to standard color values with similar ranges. If you show only one channel at a time (by setting all planes but one to 0), four of the seven bars along the top will show color.</p>
<p>We have demonstrated the <m>+</m> and <m>*</m> operators in this tutorial, but in fact the <o>jit.op</o> object can perform a great many other math operations. For a complete list of the possible operators, see the reference page, or double-click on the <link name="patcher" type="refpage">p</link> <m>op_list</m> subpatch in the <o>jit.op</o> help file.</p>
<h2>Sizing it Up</h2>
<p>When you create a <o>jit.pwindow</o> object, it will appear in the Max Console as 80 pixels wide by 60 pixels tall. You can change its size using its <i>grow box</i>, just like many of the user interface objects in Max. If you want to change its size precisely, you can do so using its Inspector or by sending it the <m>size</m> message followed by a width and height, in pixels:</p>

<illustration><img src="images/jitterchapter03h.png"/>Changing the size of a jit.pwindow</illustration>

<p>If you send a <o>jit.pwindow</o> object of a certain size (in pixels) a matrix with a different size (in cells), the <o>jit.pwindow</o> object will scale the incoming matrix to show you the entire matrix. If you send a very small matrix to a very large <o>jit.pwindow</o>, you will see <i>pixelation</i> (rectangular regions in the image where the color stays exactly the same). If you send a small <o>jit.pwindow</o> a large matrix, varying degrees of detail may be lost in what you see. </p>
<div>
<techdetail><b>Important Note:</b> in the example above, our <o>jit.matrix</o> holding the colorbars had a size (specified by its <m>dim</m> list) of 320 by 240 cells, a <m>planecount</m> of 4, and a type of <m>char</m>. The <o>jit.op</o> object (and most Jitter objects you will encounter) recognizes that information and <i>adapts</i> to perform its calculation on the entire matrix and output a matrix of the same specifications. If we were to change the <o>jit.matrix</o> object to some different size, the <o>jit.op</o> object would instantly recognize the change and re-adapt. The <o>jit.pwindow</o> object also adapts to the incoming matrix, but in a slightly different way. If the incoming matrix is smaller than its own dimensions, it uses duplicate data to fill all of its pixels. (This results in the pixelation effect described in the previous paragraph.) If the incoming matrix is larger than its own dimensions, it will be obliged to ignore some of the data, and will only display what it can. So, even though the <o>jit.pwindow</o> objects in the Tutorial patch never match the size (in cells) of their matrix input, they do their best to adapt to the size of the <o>jit.op</o> object's matrix. The <o>jit.pwindow</o> in the last example shows you as much as it can of the entire matrix output by the <o>jit.op</o> object, but it has to ignore every other row and column in order to fit the 320x240 matrix it receives into its own 160x120 display area.</techdetail>
</div>

<h2>Summary</h2>
<p>The <o>jit.op</o> object lets you perform mathematical operations on all the data in a Jitter matrix at once. You can perform calculations on the matrix cells in their entirety or on each plane separately. The mathematical operation that <o>jit.op</o> will perform is determined by its <m>op</m> attribute, which can be typed in as an <m>@op</m> <m>[operator]</m> attribute argument or provided by an <m>op [operator]</m> message in the left inlet. For multiple-plane matrices (such as color pictures and video), you can specify the operation for each plane by providing a list of operators (e.g<m>. op pass * * *</m>), and you can provide different scalar values for each plane. In <i>Tutorial 9</i> you will see how you can use a second Jitter matrix to act in place of a simple scalar.</p>
<p>You can set the size of a <o>jit.pwindow</o> object with a <m>size [width] [height]</m> message. The <o>jit.pwindow</o> will do its best to adapt to the size of any matrix it receives. It will duplicate data if the incoming matrix is smaller than its dimensions, and it will ignore some data if the incoming matrix is larger than its own dimensions. Most Jitter objects do their best to adapt to the dimensions, type, and planecount of the matrix they receive. In the case of <o>jit.op</o>, it does not have specified dimensions of its own, so it adapts to characteristics of the incoming matrix.</p>
	<seealsolist>
		<seealso display="Video and Graphics Tutorial 5: Jitter Matrix Exploration Part 1" module="Video and Graphics" name="jitterchapter00g_Jitter Matrix 1" type="tutorial" />
		<seealso name="jit.matrix">The Jitter Matrix!</seealso>
		<seealso name="jit.op">Apply binary or unary operators</seealso>
		<seealso name="pak">Format items into a list and automatically trigger output.</seealso>
	</seealsolist>

</chapter>
