Online Book Reader

Home Category

Beautiful Code [27]

By Root 5008 0
of the filter array, so now is a convenient time to put a reference to that array on the evaluation stack:

generator.Emit(OpCodes.Ldarg_0);

The Ldarg instruction refers to the arguments to the generated method, and the src array will be the first argument associated with an index of 0.

Next, we will specify several labels. Notice that these three labels are defined so that Intermediate Language instructions can refer to them, but they're not marked yet because they will be inserted at a later point in the Intermediate Language instruction stream:

Label labelLessThanZero = generator.DefineLabel();

Label labelGreaterThan = generator.DefineLabel();

Label labelLoopBottom = generator.DefineLabel();

For each element of the filter, the src array must be accessed with the iDst index plus an offset value that has already been calculated by C# code. The following code puts iDst on the stack, followed by the actual offset value, adds the two together (which effectively pops the two operands from the stack and pushes the sum on the stack), and makes two duplicates of the sum:

generator.Emit(OpCodes.Ldloc_0); // dst index on stack

generator.Emit(OpCodes.Ldc_I4, offset); // offset on stack

generator.Emit(OpCodes.Add); // Add the two

generator.Emit(OpCodes.Dup); // Duplicate twice

generator.Emit(OpCodes.Dup);

The resultant index (which was called iSrc in FilterMethodCS) might be outside the bounds of the array. The following code loads an integer 0 on the stack and branches if iSrc is less than 0, effectively popping both operands from the stack. This is a partial equivalent of the if statement conditional in line 19 of Example 8-2:

generator.Emit(OpCodes.Ldc_I4_0);

generator.Emit(OpCodes.Blt_S, labelLessThanZero);

Blt stands for branch if less than and S indicates a short branch (one in which the target is fewer than 256 op code bytes away).

A second check determines whether iSrc is greater than the byte size of the bitmap. Notice that the literal cBytes value is pushed on the stack for this comparison. This is the remainder of the if conditional in line 19 of Example 8-2:

generator.Emit(OpCodes.Ldc_I4, cBytes);

generator.Emit(OpCodes.Bge_S, labelGreaterThan);

If iSrc is good, the source array can be accessed. The Ldelem op code assumes that the array itself and an index to the array are already on the stack. Those two values are effectively popped and replaced with the array element at that index. The U1 part of this op code specifies that the array element is an unsigned one-byte value:

generator.Emit(OpCodes.Ldelem_U1);

generator.Emit(OpCodes.Conv_R8);

The Conv_R8 op code converts the value on the stack to an eight-byte floating-point value and replaces it on the stack.

At this point, the byte at iSrc is on the stack and has been converted to a floating point. It is ready to be multiplied by a filter element. Because the value of the filter element is known at the time the method is being generated, C# code skips the multiplication if the filter element is 1 (no multiplication is required if the filter element is 1):

if (filter[iFilter] == 1)

{

// src element is on stack, so do nothing

}

If the filter element is –1, the source byte can simply be negated, perhaps saving a little processing time over the multiplication:

else if (filter[iFilter] == -1)

{

generator.Emit(OpCodes.Neg);

}

Otherwise, the byte is multiplied by the filter element:

else

{

generator.Emit(OpCodes.Ldc_R8, filter[iFilter]);

generator.Emit(OpCodes.Mul);

}

You might recall that pixelsAccum was defined as a local variable with an index of 1. The following code puts pixelsAccum on the stack, adds to it the source byte value multiplied by the filter element, and stores the result back in pixelsAccum:

generator.Emit(OpCodes.Ldloc_1);

generator.Emit(OpCodes.Add);

generator.Emit(OpCodes.Stloc_1);

Similarly, filterAccum (which has a local variable index of 2) must accumulate the values of the filter elements:

generator.Emit(OpCodes.Ldc_R8, filter[iFilter]);

Return Main Page Previous Page Next Page

®Online Book Reader