private static ConvertDelegate GenerateConvertMethod(BufferDescriptor inputBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var vColor = new PixelDescriptor();

            var vInStep  = Expression.Variable(typeof(int), "inStep");
            var vOutStep = Expression.Variable(typeof(int), "outStep");
            var vLength  = Expression.Variable(typeof(int), "length");

            var vInputBuffer  = Expression.Parameter(typeof(byte[]), "inputBuffer");
            var vClutBuffer   = Expression.Parameter(typeof(byte[]), "clutBuffer");
            var vOutputBuffer = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");

            var vInPos  = Expression.Variable(typeof(int), "inPos");
            var vOutPos = Expression.Variable(typeof(int), "outPos");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new [] { vColor.RedChannel, vColor.GreenChannel, vColor.BlueChannel, vColor.AlphaChannel, vInStep, vOutStep, vLength, vInPos, vOutPos, tmp },

                Expression.Assign(vInStep, Expression.Constant(inputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vInputBuffer, "Length")),

                Expression.Assign(vInPos, Expression.Constant(0)),
                Expression.Assign(vOutPos, Expression.Constant(0)),
                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vInPos, vLength),
                                          Expression.Block(
                                              GenerateFrom(inputBufferDescriptor, vInputBuffer, vClutBuffer, vInPos, vColor, tmp),
                                              GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, vColor),

                                              Expression.AddAssign(vInPos, vInStep),
                                              Expression.AddAssign(vOutPos, vOutStep)
                                              ),
                                          Expression.Break(outOfLoop)
                                          ),
                    outOfLoop
                    )
                );

            return(Expression.Lambda <ConvertDelegate>(block, vInputBuffer, vClutBuffer, vOutputBuffer).Compile());
        }
        private static BlendDelegate GenerateBlendMethod(BufferDescriptor backgroudBufferDescriptor, BufferDescriptor foregroundBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var outputPixel            = new PixelDescriptor();
            var inputBackgroundPixel   = new PixelDescriptor();
            var inputForegroundPixel   = new PixelDescriptor();
            var contantBackgroundPixel = new PixelDescriptor();

            var vBackPos   = Expression.Variable(typeof(int), "backPos");
            var vFrontPos  = Expression.Variable(typeof(int), "frontPos");
            var vOutPos    = Expression.Variable(typeof(int), "outPos");
            var vBackStep  = Expression.Variable(typeof(int), "backStep");
            var vFrontStep = Expression.Variable(typeof(int), "frontStep");
            var vOutStep   = Expression.Variable(typeof(int), "outStep");
            var vLength    = Expression.Variable(typeof(int), "length");

            var vBackBuffer                 = Expression.Parameter(typeof(byte[]), "backBuffer");
            var vBackClutBuffer             = Expression.Parameter(typeof(byte[]), "backClutBuffer");
            var vFrontBuffer                = Expression.Parameter(typeof(byte[]), "fronBuffer");
            var vFrontClutBuffer            = Expression.Parameter(typeof(byte[]), "frontClutBuffer");
            var vOutputBuffer               = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");
            var vBackgroundColor            = Expression.Parameter(typeof(Pixel), "backgroundColor");
            var vBackBufferAlphaMultiplier  = Expression.Parameter(typeof(byte), "backBufferAlphaMultiplier");
            var vFrontBufferAlphaMultiplier = Expression.Parameter(typeof(byte), "frontBufferAlphaMultiplier");

            var vBackAlphaBlended            = Expression.Variable(typeof(uint), "backAlphaBlended");
            var vBackgroundColorAlphaBlended = Expression.Variable(typeof(uint), "backgroundColorAlphaBlended");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new[] { outputPixel.RedChannel, outputPixel.GreenChannel, outputPixel.BlueChannel, outputPixel.AlphaChannel,
                        inputForegroundPixel.RedChannel, inputForegroundPixel.GreenChannel, inputForegroundPixel.BlueChannel, inputForegroundPixel.AlphaChannel,
                        inputBackgroundPixel.RedChannel, inputBackgroundPixel.GreenChannel, inputBackgroundPixel.BlueChannel, inputBackgroundPixel.AlphaChannel,
                        vBackStep, vFrontStep, vOutStep, vLength, vBackPos, vFrontPos, vOutPos,
                        contantBackgroundPixel.RedChannel, contantBackgroundPixel.GreenChannel, contantBackgroundPixel.BlueChannel, contantBackgroundPixel.AlphaChannel,
                        vBackAlphaBlended, vBackgroundColorAlphaBlended,
                        tmp },

                Expression.Assign(vBackStep, Expression.Constant(backgroudBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vFrontStep, Expression.Constant(foregroundBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vBackBuffer, "Length")),

                Expression.Assign(vBackPos, Expression.Constant(0x00)),
                Expression.Assign(vFrontPos, Expression.Constant(0x00)),
                Expression.Assign(vOutPos, Expression.Constant(0x00)),

                Expression.Assign(contantBackgroundPixel.AlphaChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Alpha"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.RedChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Red"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.GreenChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Green"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.BlueChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Blue"), typeof(uint))),

                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vBackPos, vLength),
                                          Expression.Block(

                                              GenerateFrom(backgroudBufferDescriptor, vBackBuffer, vBackClutBuffer, vBackPos, inputBackgroundPixel, tmp),
                                              GenerateFrom(foregroundBufferDescriptor, vFrontBuffer, vFrontClutBuffer, vFrontPos, inputForegroundPixel, tmp),

                                              Expression.Assign(inputBackgroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputBackgroundPixel.AlphaChannel, Expression.Convert(vBackBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),
                                              Expression.Assign(inputForegroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputForegroundPixel.AlphaChannel, Expression.Convert(vFrontBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),

                                              Expression.Block(
                                                  // (b_alpha * (0xFF - f_alpha)) / 0xFF
                                                  Expression.Assign(
                                                      vBackAlphaBlended,
                                                      Expression.Divide(
                                                          Expression.Multiply(
                                                              inputBackgroundPixel.AlphaChannel,
                                                              Expression.Subtract(
                                                                  Expression.Constant((uint)0xFF),
                                                                  inputForegroundPixel.AlphaChannel)),
                                                          Expression.Constant((uint)0xFF))),

                                                  // (c_alpha * (0xFF - (f_alpha + b_alpha * (0xFF - f_alpha)))) / 0xFF
                                                  Expression.Assign(
                                                      vBackgroundColorAlphaBlended,
                                                      Expression.Divide(
                                                          Expression.Multiply(
                                                              contantBackgroundPixel.AlphaChannel,
                                                              Expression.Subtract(
                                                                  Expression.Constant((uint)0xFF),
                                                                  Expression.Add(
                                                                      inputForegroundPixel.AlphaChannel,
                                                                      vBackAlphaBlended))),
                                                          Expression.Constant((uint)0xFF))),

                                                  Expression.Assign(
                                                      outputPixel.AlphaChannel,
                                                      Expression.Add(
                                                          inputForegroundPixel.AlphaChannel,
                                                          Expression.Add(
                                                              vBackAlphaBlended,
                                                              vBackgroundColorAlphaBlended))),

                                                  Expression.IfThenElse(
                                                      Expression.Equal(outputPixel.AlphaChannel, Expression.Constant((uint)0)),
                                                      Expression.Block(
                                                          Expression.Assign(outputPixel.RedChannel, contantBackgroundPixel.RedChannel),
                                                          Expression.Assign(outputPixel.GreenChannel, contantBackgroundPixel.GreenChannel),
                                                          Expression.Assign(outputPixel.BlueChannel, contantBackgroundPixel.BlueChannel),
                                                          Expression.Assign(outputPixel.AlphaChannel, contantBackgroundPixel.AlphaChannel)),
                                                      Expression.Block(
                                                          Expression.Assign(
                                                              outputPixel.RedChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.RedChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.RedChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.RedChannel)),
                                                                  outputPixel.AlphaChannel)),
                                                          Expression.Assign(
                                                              outputPixel.GreenChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.GreenChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.GreenChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.GreenChannel)),
                                                                  outputPixel.AlphaChannel)),
                                                          Expression.Assign(
                                                              outputPixel.BlueChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.BlueChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.BlueChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.BlueChannel)),
                                                                  outputPixel.AlphaChannel))))
                                                  ),

                                              GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, outputPixel),

                                              Expression.AddAssign(vBackPos, vBackStep),
                                              Expression.AddAssign(vFrontPos, vFrontStep),
                                              Expression.AddAssign(vOutPos, vOutStep)
                                              ),
                                          Expression.Break(outOfLoop)
                                          ),
                    outOfLoop
                    )
                );

            return(Expression.Lambda <BlendDelegate>(block, vBackBuffer, vBackClutBuffer, vFrontBuffer, vFrontClutBuffer, vOutputBuffer, vBackgroundColor, vBackBufferAlphaMultiplier, vFrontBufferAlphaMultiplier).Compile());
        }
        /// <summary>
        /// Generates expression converting and storing one pixel in output format to output buffer (ordering bytes accordingly to endianess) at given position using channels values provided by red/green/blue/alpha variables.
        /// </summary>
        /// <returns>Generated expression.</returns>
        /// <param name="outputBufferDescriptor">Object containing information about output buffer: color format and endianness.</param>
        /// <param name="outBuffer">Output buffer.</param>
        /// <param name="outPosition">Position of pixel in output buffer.</param>
        /// <param name="color">Object with variables from which value of color channels should be read.</param>
        private static Expression GenerateTo(BufferDescriptor outputBufferDescriptor, ParameterExpression outBuffer, ParameterExpression outPosition, PixelDescriptor color)
        {
            byte currentBit  = 0;
            byte currentByte = 0;
            var  expressions = new List <Expression>();

            Expression currentExpression = null;

            foreach (var colorDescriptor in outputBufferDescriptor.ColorFormat.GetColorsLengths())
            {
                Expression colorExpression = null;

                switch (colorDescriptor.Key)
                {
                case ColorType.A:
                    colorExpression = color.AlphaChannel;
                    break;

                case ColorType.B:
                    colorExpression = color.BlueChannel;
                    break;

                case ColorType.G:
                    colorExpression = color.GreenChannel;
                    break;

                case ColorType.R:
                    colorExpression = color.RedChannel;
                    break;

                case ColorType.X:
                    colorExpression = Expression.Constant((uint)0xFF);
                    break;

                case ColorType.L:
                    throw new ArgumentException("Luminance channel is not allowed in target color format");
                }

                foreach (var transformation in ByteSqueezeAndMove(colorDescriptor.Value, currentBit))
                {
                    Expression currentExpressionFragment = colorExpression;

                    if (transformation.MaskBits != 0xFF)
                    {
                        currentExpressionFragment = Expression.And(currentExpressionFragment, Expression.Constant((uint)transformation.MaskBits));
                    }

                    if (transformation.ShiftBits > 0)
                    {
                        currentExpressionFragment = Expression.RightShift(currentExpressionFragment, Expression.Constant((int)transformation.ShiftBits));
                    }
                    else if (transformation.ShiftBits < 0)
                    {
                        currentExpressionFragment = Expression.And(
                            Expression.LeftShift(currentExpressionFragment, Expression.Constant((int)(-transformation.ShiftBits))),
                            Expression.Constant((uint)0xFF));
                    }

                    currentExpression = (currentExpression == null) ? currentExpressionFragment : Expression.Or(currentExpression, currentExpressionFragment);

                    currentBit += transformation.UsedBits;
                    while (currentBit >= 8)
                    {
                        expressions.Add(
                            Expression.Assign(
                                Expression.ArrayAccess(outBuffer,
                                                       Expression.Add(
                                                           outPosition,
                                                           Expression.Constant((outputBufferDescriptor.DataEndianness == Endianess.BigEndian) ? (int)currentByte : (outputBufferDescriptor.ColorFormat.GetColorDepth() - currentByte - 1)))),
                                Expression.Convert(currentExpression, typeof(byte))));

                        currentExpression = null;
                        currentBit       -= 8;
                        currentByte++;
                    }
                }
            }

            return(Expression.Block(expressions));
        }
        /// <summary>
        /// Generates expression reading one pixel encoded in given format from input buffer (with bytes ordered accordingly to endianess) at given position
        /// and storing each channel in separate variable expression.
        /// </summary>
        /// <returns>Generated expression.</returns>
        /// <param name="inputBufferDescriptor">Object containing information about input buffer: color format and endianness.</param>
        /// <param name="inBuffer">Input buffer.</param>
        /// <param name="clutBuffer">Color look-up table buffer.</param>
        /// <param name="inPosition">Position of pixel in buffer.</param>
        /// <param name="color">Variable where values of color channels should be stored.</param>
        private static Expression GenerateFrom(BufferDescriptor inputBufferDescriptor, ParameterExpression inBuffer, ParameterExpression clutBuffer, Expression inPosition, PixelDescriptor color, Expression tmp)
        {
            byte currentBit  = 0;
            byte currentByte = 0;
            bool isAlphaSet  = false;

            var expressions = new List <Expression>();
            var inputBytes  = new ParameterExpression[inputBufferDescriptor.ColorFormat.GetColorDepth()];

            for (int i = 0; i < inputBytes.Length; i++)
            {
                inputBytes[i] = Expression.Variable(typeof(uint));

                expressions.Add(
                    Expression.Assign(
                        inputBytes[i],
                        Expression.Convert(
                            Expression.ArrayIndex(
                                inBuffer,
                                Expression.Add(
                                    inPosition,
                                    Expression.Constant((inputBufferDescriptor.DataEndianness == Endianess.BigEndian) ? i : inputBytes.Length - i - 1))),
                            typeof(uint))));
            }

            foreach (var colorDescriptor in inputBufferDescriptor.ColorFormat.GetColorsLengths())
            {
                Expression colorExpression = null;

                foreach (var transformation in ByteInflate(colorDescriptor.Value, currentBit))
                {
                    Expression currentExpressionFragment = inputBytes[currentByte];

                    if (transformation.MaskBits != 0xFF)
                    {
                        currentExpressionFragment = Expression.And(currentExpressionFragment, Expression.Constant((uint)transformation.MaskBits));
                    }

                    if (transformation.ShiftBits > 0)
                    {
                        currentExpressionFragment = Expression.RightShift(currentExpressionFragment, Expression.Constant((int)transformation.ShiftBits));
                    }
                    else if (transformation.ShiftBits < 0)
                    {
                        currentExpressionFragment = Expression.And(
                            Expression.LeftShift(currentExpressionFragment, Expression.Constant((int)(-transformation.ShiftBits))),
                            Expression.Constant((uint)0xFF));
                    }

                    currentBit += transformation.UsedBits;
                    if (currentBit >= 8)
                    {
                        currentBit -= 8;
                        currentByte++;
                    }

                    colorExpression = (colorExpression == null) ? currentExpressionFragment : Expression.Or(colorExpression, currentExpressionFragment);
                }

                if (colorDescriptor.Key == ColorType.X)
                {
                    continue;
                }

                // luminance - indirect color indexing using CLUT
                if (colorDescriptor.Key == ColorType.L)
                {
                    if (!inputBufferDescriptor.ClutColorFormat.HasValue)
                    {
                        throw new ArgumentException("CLUT mode required but not set");
                    }

                    var clutWidth  = Expression.Constant((uint)inputBufferDescriptor.ClutColorFormat.Value.GetColorDepth());
                    var clutOffset = Expression.Multiply(colorExpression, clutWidth);

                    expressions.Add(Expression.Assign(tmp, color.AlphaChannel));

                    // todo: indirect parameters should not be needed here, but we  m u s t  pass something
                    expressions.Add(
                        GenerateFrom(new BufferDescriptor
                    {
                        ColorFormat    = inputBufferDescriptor.ClutColorFormat.Value,
                        DataEndianness = inputBufferDescriptor.DataEndianness
                    }, clutBuffer, clutBuffer, Expression.Convert(clutOffset, typeof(int)), color, tmp));

                    expressions.Add(Expression.Assign(color.AlphaChannel, tmp));
                }
                else
                {
                    Expression currentColor = null;
                    switch (colorDescriptor.Key)
                    {
                    case ColorType.A:
                        currentColor = color.AlphaChannel;
                        isAlphaSet   = true;
                        break;

                    case ColorType.B:
                        currentColor = color.BlueChannel;
                        break;

                    case ColorType.G:
                        currentColor = color.GreenChannel;
                        break;

                    case ColorType.R:
                        currentColor = color.RedChannel;
                        break;
                    }

                    expressions.Add(Expression.Assign(currentColor, colorExpression));

                    // filling lsb '0'-bits with copy of msb pattern
                    var numberOfBits = colorDescriptor.Value;
                    var zeroBits     = 8 - numberOfBits;
                    while (zeroBits > 0)
                    {
                        expressions.Add(Expression.OrAssign(
                                            currentColor,
                                            Expression.RightShift(
                                                currentColor,
                                                Expression.Constant((int)numberOfBits))));
                        zeroBits -= numberOfBits;
                    }
                }
            }

            if (!isAlphaSet)
            {
                expressions.Add(Expression.Assign(color.AlphaChannel, Expression.Constant((uint)0xFF)));
            }
            return(Expression.Block(inputBytes, expressions));
        }
        private static BlendDelegate GenerateBlendMethod(BufferDescriptor backgroudBufferDescriptor, BufferDescriptor foregroundBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var outputPixel            = new PixelDescriptor();
            var inputBackgroundPixel   = new PixelDescriptor();
            var inputForegroundPixel   = new PixelDescriptor();
            var contantBackgroundPixel = new PixelDescriptor();

            var vBackPos   = Expression.Variable(typeof(int), "backPos");
            var vFrontPos  = Expression.Variable(typeof(int), "frontPos");
            var vOutPos    = Expression.Variable(typeof(int), "outPos");
            var vBackStep  = Expression.Variable(typeof(int), "backStep");
            var vFrontStep = Expression.Variable(typeof(int), "frontStep");
            var vOutStep   = Expression.Variable(typeof(int), "outStep");
            var vLength    = Expression.Variable(typeof(int), "length");

            var vBackBuffer                 = Expression.Parameter(typeof(byte[]), "backBuffer");
            var vBackClutBuffer             = Expression.Parameter(typeof(byte[]), "backClutBuffer");
            var vFrontBuffer                = Expression.Parameter(typeof(byte[]), "frontBuffer");
            var vFrontClutBuffer            = Expression.Parameter(typeof(byte[]), "frontClutBuffer");
            var vOutputBuffer               = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");
            var vBackgroundColor            = Expression.Parameter(typeof(Pixel), "backgroundColor");
            var vBackBufferAlphaMultiplier  = Expression.Parameter(typeof(byte), "backBufferAlphaMultiplier");
            var vFrontBufferAlphaMultiplier = Expression.Parameter(typeof(byte), "frontBufferAlphaMultiplier");

            var vBackgroundBlendingMode = Expression.Parameter(typeof(PixelBlendingMode), "backgroundBlendingMode");
            var vForegroundBlendingMode = Expression.Parameter(typeof(PixelBlendingMode), "foregroundBlendingMode");

            var vBackAlphaBlended            = Expression.Variable(typeof(uint), "backAlphaBlended");
            var vBackgroundColorAlphaBlended = Expression.Variable(typeof(uint), "backgroundColorAlphaBlended");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new[] { outputPixel.RedChannel, outputPixel.GreenChannel, outputPixel.BlueChannel, outputPixel.AlphaChannel,
                        inputForegroundPixel.RedChannel, inputForegroundPixel.GreenChannel, inputForegroundPixel.BlueChannel, inputForegroundPixel.AlphaChannel,
                        inputBackgroundPixel.RedChannel, inputBackgroundPixel.GreenChannel, inputBackgroundPixel.BlueChannel, inputBackgroundPixel.AlphaChannel,
                        vBackStep, vFrontStep, vOutStep, vLength, vBackPos, vFrontPos, vOutPos,
                        contantBackgroundPixel.RedChannel, contantBackgroundPixel.GreenChannel, contantBackgroundPixel.BlueChannel, contantBackgroundPixel.AlphaChannel,
                        vBackAlphaBlended, vBackgroundColorAlphaBlended,
                        tmp },

                Expression.Assign(vBackStep, Expression.Constant(backgroudBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vFrontStep, Expression.Constant(foregroundBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vBackBuffer, "Length")),

                Expression.Assign(vBackPos, Expression.Constant(0x00)),
                Expression.Assign(vFrontPos, Expression.Constant(0x00)),
                Expression.Assign(vOutPos, Expression.Constant(0x00)),

                Expression.Assign(contantBackgroundPixel.AlphaChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Alpha"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.RedChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Red"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.GreenChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Green"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.BlueChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Blue"), typeof(uint))),

                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vBackPos, vLength),
                                          Expression.Block(

                                              GenerateFrom(backgroudBufferDescriptor, vBackBuffer, vBackClutBuffer, vBackPos, inputBackgroundPixel, tmp),
                                              GenerateFrom(foregroundBufferDescriptor, vFrontBuffer, vFrontClutBuffer, vFrontPos, inputForegroundPixel, tmp),

                                              Expression.Switch(typeof(void), vBackgroundBlendingMode, null, null, new SwitchCase[]
            {
                // Multiply: input BG Pixel Alpha *= bg alpha
                Expression.SwitchCase(
                    Expression.Assign(inputBackgroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputBackgroundPixel.AlphaChannel, Expression.Convert(vBackBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),
                    Expression.Constant(PixelBlendingMode.Multiply)
                    ),

                // Replace: input BG Pixel Alpha = bg alpha
                Expression.SwitchCase(
                    Expression.Assign(inputBackgroundPixel.AlphaChannel, Expression.Convert(vBackBufferAlphaMultiplier, typeof(uint))),
                    Expression.Constant(PixelBlendingMode.Replace)
                    )
            }),

                                              Expression.Switch(typeof(void), vForegroundBlendingMode, null, null, new SwitchCase[]
            {
                // Multiply: input FG Pixel Alpha *= fg alpha
                Expression.SwitchCase(
                    Expression.Assign(inputForegroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputForegroundPixel.AlphaChannel, Expression.Convert(vFrontBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),
                    Expression.Constant(PixelBlendingMode.Multiply)
                    ),

                // Replace: input FG Pixel Alpha = fg alpha
                Expression.SwitchCase(
                    Expression.Assign(inputForegroundPixel.AlphaChannel, Expression.Convert(vFrontBufferAlphaMultiplier, typeof(uint))),
                    Expression.Constant(PixelBlendingMode.Replace)
                    )
            }),

                                              Expression.Block(
                                                  // (b_alpha * (0xFF - f_alpha)) / 0xFF
                                                  Expression.Assign(
                                                      vBackAlphaBlended,
                                                      Expression.Divide(
                                                          Expression.Multiply(
                                                              inputBackgroundPixel.AlphaChannel,
                                                              Expression.Subtract(
                                                                  Expression.Constant((uint)0xFF),
                                                                  inputForegroundPixel.AlphaChannel)),
                                                          Expression.Constant((uint)0xFF))),

                                                  // (c_alpha * (0xFF - (f_alpha + b_alpha * (0xFF - f_alpha)))) / 0xFF
                                                  Expression.Assign(
                                                      vBackgroundColorAlphaBlended,
                                                      Expression.Divide(
                                                          Expression.Multiply(
                                                              contantBackgroundPixel.AlphaChannel,
                                                              Expression.Subtract(
                                                                  Expression.Constant((uint)0xFF),
                                                                  Expression.Add(
                                                                      inputForegroundPixel.AlphaChannel,
                                                                      vBackAlphaBlended))),
                                                          Expression.Constant((uint)0xFF))),

                                                  Expression.Assign(
                                                      outputPixel.AlphaChannel,
                                                      Expression.Add(
                                                          inputForegroundPixel.AlphaChannel,
                                                          Expression.Add(
                                                              vBackAlphaBlended,
                                                              vBackgroundColorAlphaBlended))),

                                                  Expression.IfThenElse(
                                                      // If output pixel is 100% transparent
                                                      Expression.Equal(outputPixel.AlphaChannel, Expression.Constant((uint)0)),
                                                      // ... then the outputpixel should actually be equal to the underlying background pixel
                                                      Expression.Block(
                                                          Expression.Assign(outputPixel.RedChannel, contantBackgroundPixel.RedChannel),
                                                          Expression.Assign(outputPixel.GreenChannel, contantBackgroundPixel.GreenChannel),
                                                          Expression.Assign(outputPixel.BlueChannel, contantBackgroundPixel.BlueChannel),
                                                          Expression.Assign(outputPixel.AlphaChannel, contantBackgroundPixel.AlphaChannel)),
                                                      // ... else, apply alpha to all color channels
                                                      Expression.Block(
                                                          Expression.Assign(
                                                              outputPixel.RedChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.RedChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.RedChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.RedChannel)),
                                                                  outputPixel.AlphaChannel)),
                                                          Expression.Assign(
                                                              outputPixel.GreenChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.GreenChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.GreenChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.GreenChannel)),
                                                                  outputPixel.AlphaChannel)),
                                                          Expression.Assign(
                                                              outputPixel.BlueChannel,
                                                              Expression.Divide(
                                                                  Expression.Add(
                                                                      Expression.Add(
                                                                          Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.BlueChannel),
                                                                          Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.BlueChannel)),
                                                                      Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.BlueChannel)),
                                                                  outputPixel.AlphaChannel))))
                                                  ),

                                              GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, outputPixel),

                                              Expression.AddAssign(vBackPos, vBackStep),
                                              Expression.AddAssign(vFrontPos, vFrontStep),
                                              Expression.AddAssign(vOutPos, vOutStep)
                                              ),
                                          Expression.Break(outOfLoop)
                                          ),
                    outOfLoop
                    )
                );

            return(Expression.Lambda <BlendDelegate>(block, vBackBuffer, vBackClutBuffer, vFrontBuffer, vFrontClutBuffer, vOutputBuffer, vBackgroundColor, vBackBufferAlphaMultiplier, vBackgroundBlendingMode, vFrontBufferAlphaMultiplier, vForegroundBlendingMode).Compile());
        }
        private static ConvertDelegate GenerateConvertMethod(BufferDescriptor inputBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var vColor = new PixelDescriptor();

            var vInStep  = Expression.Variable(typeof(int), "inStep");
            var vOutStep = Expression.Variable(typeof(int), "outStep");
            var vLength  = Expression.Variable(typeof(int), "length");

            var vInputBuffer      = Expression.Parameter(typeof(byte[]), "inputBuffer");
            var vClutBuffer       = Expression.Parameter(typeof(byte[]), "clutBuffer");
            var vAlpha            = Expression.Parameter(typeof(byte), "alpha");
            var vAlphaReplaceMode = Expression.Parameter(typeof(PixelBlendingMode), "alphaReplaceMode");
            var vOutputBuffer     = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");

            var vInPos  = Expression.Variable(typeof(int), "inPos");
            var vOutPos = Expression.Variable(typeof(int), "outPos");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new [] { vColor.RedChannel, vColor.GreenChannel, vColor.BlueChannel, vColor.AlphaChannel, vInStep, vOutStep, vLength, vInPos, vOutPos, tmp },

                Expression.Assign(vInStep, Expression.Constant(inputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vInputBuffer, "Length")),

                Expression.Assign(vInPos, Expression.Constant(0)),
                Expression.Assign(vOutPos, Expression.Constant(0)),
                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vInPos, vLength),
                                          Expression.Block(
                                              GenerateFrom(inputBufferDescriptor, vInputBuffer, vClutBuffer, vInPos, vColor, tmp),

                                              // handle the case where alpha needs to be changed
                                              Expression.Switch(typeof(void), vAlphaReplaceMode, null, null, new SwitchCase[]
            {
                // Multiply
                Expression.SwitchCase(
                    Expression.Assign(vColor.AlphaChannel, Expression.Divide(Expression.Multiply(vColor.AlphaChannel, Expression.Convert(vAlpha, typeof(uint))), Expression.Constant((uint)0xFF))),
                    Expression.Constant(PixelBlendingMode.Multiply)
                    ),

                // Replace
                Expression.SwitchCase(
                    Expression.Assign(vColor.AlphaChannel, Expression.Convert(vAlpha, typeof(uint))),
                    Expression.Constant(PixelBlendingMode.Replace)
                    )
            }),

                                              GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, vColor),

                                              Expression.AddAssign(vInPos, vInStep),
                                              Expression.AddAssign(vOutPos, vOutStep)
                                              ),
                                          Expression.Break(outOfLoop)
                                          ),
                    outOfLoop
                    )
                );

            return(Expression.Lambda <ConvertDelegate>(block, vInputBuffer, vClutBuffer, vAlpha, vAlphaReplaceMode, vOutputBuffer).Compile());
        }
Exemplo n.º 7
0
        private static BlendDelegate GenerateBlendMethod(BufferDescriptor backgroudBufferDescriptor, BufferDescriptor foregroundBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var outputPixel = new PixelDescriptor();
            var inputBackgroundPixel = new PixelDescriptor();
            var inputForegroundPixel = new PixelDescriptor();
            var contantBackgroundPixel = new PixelDescriptor();

            var vBackPos = Expression.Variable(typeof(int), "backPos");
            var vFrontPos = Expression.Variable(typeof(int), "frontPos");
            var vOutPos = Expression.Variable(typeof(int), "outPos");
            var vBackStep = Expression.Variable(typeof(int), "backStep");
            var vFrontStep = Expression.Variable(typeof(int), "frontStep");
            var vOutStep = Expression.Variable(typeof(int), "outStep");
            var vLength = Expression.Variable(typeof(int),  "length");

            var vBackBuffer = Expression.Parameter(typeof(byte[]), "backBuffer");
            var vBackClutBuffer = Expression.Parameter(typeof(byte[]), "backClutBuffer");
            var vFrontBuffer = Expression.Parameter(typeof(byte[]), "fronBuffer");
            var vFrontClutBuffer = Expression.Parameter(typeof(byte[]), "frontClutBuffer");
            var vOutputBuffer = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");
            var vBackgroundColor = Expression.Parameter(typeof(Pixel), "backgroundColor");
            var vBackBufferAlphaMultiplier = Expression.Parameter(typeof(byte), "backBufferAlphaMultiplier");
            var vFrontBufferAlphaMultiplier = Expression.Parameter(typeof(byte), "frontBufferAlphaMultiplier");

            var vBackAlphaBlended = Expression.Variable(typeof(uint), "backAlphaBlended");
            var vBackgroundColorAlphaBlended = Expression.Variable(typeof(uint), "backgroundColorAlphaBlended");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new[] {  outputPixel.RedChannel, outputPixel.GreenChannel, outputPixel.BlueChannel, outputPixel.AlphaChannel,
                         inputForegroundPixel.RedChannel, inputForegroundPixel.GreenChannel, inputForegroundPixel.BlueChannel, inputForegroundPixel.AlphaChannel,
                         inputBackgroundPixel.RedChannel, inputBackgroundPixel.GreenChannel, inputBackgroundPixel.BlueChannel, inputBackgroundPixel.AlphaChannel,
                         vBackStep, vFrontStep, vOutStep, vLength, vBackPos, vFrontPos, vOutPos,
                         contantBackgroundPixel.RedChannel, contantBackgroundPixel.GreenChannel, contantBackgroundPixel.BlueChannel, contantBackgroundPixel.AlphaChannel,
                         vBackAlphaBlended, vBackgroundColorAlphaBlended,
                                    tmp
                },

                Expression.Assign(vBackStep, Expression.Constant(backgroudBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vFrontStep, Expression.Constant(foregroundBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vBackBuffer, "Length")),

                Expression.Assign(vBackPos, Expression.Constant(0x00)),
                Expression.Assign(vFrontPos, Expression.Constant(0x00)),
                Expression.Assign(vOutPos, Expression.Constant(0x00)),

                Expression.Assign(contantBackgroundPixel.AlphaChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Alpha"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.RedChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Red"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.GreenChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Green"), typeof(uint))),
                Expression.Assign(contantBackgroundPixel.BlueChannel, Expression.Convert(Expression.Property(vBackgroundColor, "Blue"), typeof(uint))),

                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vBackPos, vLength),
                        Expression.Block(

                            GenerateFrom(backgroudBufferDescriptor, vBackBuffer, vBackClutBuffer, vBackPos, inputBackgroundPixel, tmp),
                            GenerateFrom(foregroundBufferDescriptor, vFrontBuffer, vFrontClutBuffer, vFrontPos, inputForegroundPixel, tmp),

                            Expression.Assign(inputBackgroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputBackgroundPixel.AlphaChannel, Expression.Convert(vBackBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),
                            Expression.Assign(inputForegroundPixel.AlphaChannel, Expression.Divide(Expression.Multiply(inputForegroundPixel.AlphaChannel, Expression.Convert(vFrontBufferAlphaMultiplier, typeof(uint))), Expression.Constant((uint)0xFF))),

                            Expression.Block(
                                // (b_alpha * (0xFF - f_alpha)) / 0xFF
                                Expression.Assign(
                                    vBackAlphaBlended,
                                    Expression.Divide(
                                        Expression.Multiply(
                                            inputBackgroundPixel.AlphaChannel,
                                            Expression.Subtract(
                                                Expression.Constant((uint)0xFF),
                                                inputForegroundPixel.AlphaChannel)),
                                        Expression.Constant((uint)0xFF))),

                                // (c_alpha * (0xFF - (f_alpha + b_alpha * (0xFF - f_alpha)))) / 0xFF
                                Expression.Assign(
                                        vBackgroundColorAlphaBlended,
                                        Expression.Divide(
                                            Expression.Multiply(
                                                contantBackgroundPixel.AlphaChannel,
                                                Expression.Subtract(
                                                    Expression.Constant((uint)0xFF),
                                                    Expression.Add(
                                                        inputForegroundPixel.AlphaChannel,
                                                        vBackAlphaBlended))),
                                             Expression.Constant((uint)0xFF))),
                                                  
                                Expression.Assign(
                                    outputPixel.AlphaChannel, 
                                    Expression.Add(
                                        inputForegroundPixel.AlphaChannel,
                                        Expression.Add(
                                            vBackAlphaBlended,
                                            vBackgroundColorAlphaBlended))),

                                Expression.IfThenElse(
                                    Expression.Equal(outputPixel.AlphaChannel, Expression.Constant((uint)0)),
                                    Expression.Block(
                                        Expression.Assign(outputPixel.RedChannel, contantBackgroundPixel.RedChannel),
                                        Expression.Assign(outputPixel.GreenChannel, contantBackgroundPixel.GreenChannel),
                                        Expression.Assign(outputPixel.BlueChannel, contantBackgroundPixel.BlueChannel),
                                        Expression.Assign(outputPixel.AlphaChannel, contantBackgroundPixel.AlphaChannel)),
                                    Expression.Block( 
                                        Expression.Assign(
                                            outputPixel.RedChannel, 
                                            Expression.Divide(
                                                Expression.Add(
                                                    Expression.Add(
                                                        Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.RedChannel),
                                                        Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.RedChannel)),
                                                    Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.RedChannel)),
                                                outputPixel.AlphaChannel)),
                                        Expression.Assign(
                                            outputPixel.GreenChannel, 
                                            Expression.Divide(
                                                Expression.Add(
                                                    Expression.Add(
                                                        Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.GreenChannel),
                                                        Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.GreenChannel)),
                                                    Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.GreenChannel)),
                                                outputPixel.AlphaChannel)),
                                        Expression.Assign(
                                            outputPixel.BlueChannel, 
                                            Expression.Divide(
                                                Expression.Add(
                                                    Expression.Add(
                                                        Expression.Multiply(vBackgroundColorAlphaBlended, contantBackgroundPixel.BlueChannel),
                                                        Expression.Multiply(vBackAlphaBlended, inputBackgroundPixel.BlueChannel)),
                                                    Expression.Multiply(inputForegroundPixel.AlphaChannel, inputForegroundPixel.BlueChannel)),
                                                outputPixel.AlphaChannel))))
                            ),

                            GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, outputPixel),

                            Expression.AddAssign(vBackPos, vBackStep),
                            Expression.AddAssign(vFrontPos, vFrontStep),
                            Expression.AddAssign(vOutPos, vOutStep)
                        ),
                        Expression.Break(outOfLoop)
                    ),
                    outOfLoop
                )
            );

            return Expression.Lambda<BlendDelegate>(block, vBackBuffer, vBackClutBuffer, vFrontBuffer, vFrontClutBuffer, vOutputBuffer, vBackgroundColor, vBackBufferAlphaMultiplier, vFrontBufferAlphaMultiplier).Compile();
        }
Exemplo n.º 8
0
        /// <summary>
        /// Generates expression converting and storing one pixel in output format to output buffer (ordering bytes accordingly to endianess) at given position using channels values provided by red/green/blue/alpha variables.
        /// </summary>
        /// <returns>Generated expression.</returns>
        /// <param name="outputBufferDescriptor">Object containing information about output buffer: color format and endianness.</param>
        /// <param name="outBuffer">Output buffer.</param>
        /// <param name="outPosition">Position of pixel in output buffer.</param>
        /// <param name="color">Object with variables from which value of color channels should be read.</param>
        private static Expression GenerateTo(BufferDescriptor outputBufferDescriptor, ParameterExpression outBuffer, ParameterExpression outPosition, PixelDescriptor color)
        {
            byte currentBit = 0;
            byte currentByte = 0;
            var expressions = new List<Expression>();
            
            Expression currentExpression = null;
            
            foreach(var colorDescriptor in outputBufferDescriptor.ColorFormat.GetColorsLengths())
            {
                Expression colorExpression = null; 
                
                switch(colorDescriptor.Key)
                {
                case ColorType.A:
                    colorExpression = color.AlphaChannel;
                    break;
                case ColorType.B:
                    colorExpression = color.BlueChannel;
                    break;
                case ColorType.G:
                    colorExpression = color.GreenChannel;
                    break;
                case ColorType.R:
                    colorExpression = color.RedChannel;
                    break;
                case ColorType.X:
                    colorExpression = Expression.Constant((uint)0xFF);
                    break;
                case ColorType.L:
                    throw new ArgumentException("Luminance channel is not allowed in target color format");
                }

                foreach(var transformation in ByteSqueezeAndMove(colorDescriptor.Value, currentBit))
                {
                    Expression currentExpressionFragment = colorExpression;
                
                    if(transformation.MaskBits != 0xFF)
                    {
                        currentExpressionFragment = Expression.And(currentExpressionFragment, Expression.Constant((uint)transformation.MaskBits));
                    }

                    if(transformation.ShiftBits > 0)
                    {
                        currentExpressionFragment = Expression.RightShift(currentExpressionFragment, Expression.Constant((int)transformation.ShiftBits));
                    }
                    else if(transformation.ShiftBits < 0)
                    {
                        currentExpressionFragment = Expression.And(
                            Expression.LeftShift(currentExpressionFragment, Expression.Constant((int)(-transformation.ShiftBits))),
                            Expression.Constant((uint)0xFF));
                                
                    }
                    
                    currentExpression = (currentExpression == null) ? currentExpressionFragment : Expression.Or(currentExpression, currentExpressionFragment);

                    currentBit += transformation.UsedBits;
                    while(currentBit >= 8)
                    {
                        expressions.Add(
                            Expression.Assign(
                                Expression.ArrayAccess(outBuffer, 
                                    Expression.Add(
                                        outPosition, 
                                        Expression.Constant((outputBufferDescriptor.DataEndianness == Endianess.BigEndian) ? (int) currentByte : (outputBufferDescriptor.ColorFormat.GetColorDepth() - currentByte - 1)))),
                                Expression.Convert(currentExpression, typeof(byte))));

                        currentExpression = null;
                        currentBit -= 8;
                        currentByte++;
                    }
                }
            }

            return Expression.Block(expressions);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Generates expression reading one pixel encoded in given format from input buffer (with bytes ordered accordingly to endianess) at given position 
        /// and storing each channel in separate variable expression.
        /// </summary>
        /// <returns>Generated expression.</returns>
        /// <param name="inputBufferDescriptor">Object containing information about input buffer: color format and endianness.</param>
        /// <param name="inBuffer">Input buffer.</param>
        /// <param name="clutBuffer">Color look-up table buffer.</param>
        /// <param name="inPosition">Position of pixel in buffer.</param>
        /// <param name="color">Variable where values of color channels should be stored.</param>
        private static Expression GenerateFrom(BufferDescriptor inputBufferDescriptor, ParameterExpression inBuffer, ParameterExpression clutBuffer, Expression inPosition, PixelDescriptor color, Expression tmp)
        {
            byte currentBit = 0;
            byte currentByte = 0;
            bool isAlphaSet = false;
            
            var expressions = new List<Expression>();
            var inputBytes = new ParameterExpression[inputBufferDescriptor.ColorFormat.GetColorDepth()];
            for(int i = 0; i < inputBytes.Length; i++)
            {
                inputBytes[i] = Expression.Variable(typeof(uint));
                
                expressions.Add(
                    Expression.Assign(
                        inputBytes[i], 
                        Expression.Convert(
                            Expression.ArrayIndex(
                                inBuffer,
                                Expression.Add(
                                    inPosition, 
                                    Expression.Constant((inputBufferDescriptor.DataEndianness == Endianess.BigEndian) ? i : inputBytes.Length - i - 1))),
                            typeof(uint))));
            }

            foreach(var colorDescriptor in inputBufferDescriptor.ColorFormat.GetColorsLengths())
            {
                Expression colorExpression = null; 
                
                foreach(var transformation in ByteInflate(colorDescriptor.Value, currentBit))
                {
                    Expression currentExpressionFragment = inputBytes[currentByte];
                    
                    if(transformation.MaskBits != 0xFF)
                    {
                        currentExpressionFragment = Expression.And(currentExpressionFragment, Expression.Constant((uint)transformation.MaskBits));
                    }
                    
                    if(transformation.ShiftBits > 0)
                    {
                        currentExpressionFragment = Expression.RightShift(currentExpressionFragment, Expression.Constant((int)transformation.ShiftBits));
                    }
                    else if(transformation.ShiftBits < 0)
                    {
                        currentExpressionFragment = Expression.And(
                            Expression.LeftShift(currentExpressionFragment, Expression.Constant((int)(-transformation.ShiftBits))),
                            Expression.Constant((uint)0xFF));
                    }
                    
                    currentBit += transformation.UsedBits;
                    if(currentBit >= 8)
                    {
                        currentBit -= 8;
                        currentByte++;
                    }
                    
                    colorExpression = (colorExpression == null) ? currentExpressionFragment : Expression.Or(colorExpression, currentExpressionFragment);
                }

                if(colorDescriptor.Key == ColorType.X)
                {
                    continue;
                }

                // luminance - indirect color indexing using CLUT
                if(colorDescriptor.Key == ColorType.L)
                {
                    if(!inputBufferDescriptor.ClutColorFormat.HasValue)
                    {
                        throw new ArgumentException("CLUT mode required but not set");
                    }

                    var clutWidth = Expression.Constant((uint)inputBufferDescriptor.ClutColorFormat.Value.GetColorDepth());
                    var clutOffset = Expression.Multiply(colorExpression, clutWidth);

                    expressions.Add(Expression.Assign(tmp, color.AlphaChannel));

                    // todo: indirect parameters should not be needed here, but we  m u s t  pass something
                    expressions.Add(
                        GenerateFrom(new BufferDescriptor
                    { 
                        ColorFormat = inputBufferDescriptor.ClutColorFormat.Value, 
                        DataEndianness = inputBufferDescriptor.DataEndianness 
                    }, clutBuffer, clutBuffer, Expression.Convert(clutOffset, typeof(int)), color, tmp));

                    expressions.Add(Expression.Assign(color.AlphaChannel, tmp));
                }
                else
                {
                    Expression currentColor = null;
                    switch(colorDescriptor.Key)
                    {
                    case ColorType.A:
                        currentColor = color.AlphaChannel;
                        isAlphaSet = true;
                        break;
                    case ColorType.B:
                        currentColor = color.BlueChannel;
                        break;
                    case ColorType.G:
                        currentColor = color.GreenChannel;
                        break;
                    case ColorType.R:
                        currentColor = color.RedChannel;
                        break;
                    }

                    expressions.Add(Expression.Assign(currentColor, colorExpression));
                                
                    // filling lsb '0'-bits with copy of msb pattern
                    var numberOfBits = colorDescriptor.Value;
                    var zeroBits = 8 - numberOfBits;
                    while(zeroBits > 0)
                    {
                        expressions.Add(Expression.OrAssign(
                            currentColor, 
                            Expression.RightShift(
                                currentColor, 
                                Expression.Constant((int)numberOfBits))));
                        zeroBits -= numberOfBits;
                    }
                }
            }

            if(!isAlphaSet)
            {
                expressions.Add(Expression.Assign(color.AlphaChannel, Expression.Constant((uint)0xFF)));
            }
            return Expression.Block(inputBytes, expressions);
        }
Exemplo n.º 10
0
        private static ConvertDelegate GenerateConvertMethod(BufferDescriptor inputBufferDescriptor, BufferDescriptor outputBufferDescriptor)
        {
            var vColor = new PixelDescriptor();

            var vInStep = Expression.Variable(typeof(int),  "inStep");
            var vOutStep = Expression.Variable(typeof(int), "outStep");
            var vLength = Expression.Variable(typeof(int),  "length");

            var vInputBuffer = Expression.Parameter(typeof(byte[]), "inputBuffer");
            var vClutBuffer = Expression.Parameter(typeof(byte[]), "clutBuffer");
            var vOutputBuffer = Expression.Parameter(typeof(byte[]).MakeByRefType(), "outputBuffer");

            var vInPos = Expression.Variable(typeof(int), "inPos");
            var vOutPos = Expression.Variable(typeof(int), "outPos");

            var tmp = Expression.Variable(typeof(uint));

            var outOfLoop = Expression.Label();

            var block = Expression.Block(
                new [] { vColor.RedChannel, vColor.GreenChannel, vColor.BlueChannel, vColor.AlphaChannel, vInStep, vOutStep, vLength, vInPos, vOutPos, tmp },

                Expression.Assign(vInStep, Expression.Constant(inputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vOutStep, Expression.Constant(outputBufferDescriptor.ColorFormat.GetColorDepth())),
                Expression.Assign(vLength, Expression.Property(vInputBuffer, "Length")),

                Expression.Assign(vInPos, Expression.Constant(0)),
                Expression.Assign(vOutPos, Expression.Constant(0)),
                Expression.Loop(
                    Expression.IfThenElse(Expression.LessThan(vInPos, vLength),
                        Expression.Block(
                            GenerateFrom(inputBufferDescriptor, vInputBuffer, vClutBuffer, vInPos, vColor, tmp),
                            GenerateTo(outputBufferDescriptor, vOutputBuffer, vOutPos, vColor),

                            Expression.AddAssign(vInPos, vInStep),
                            Expression.AddAssign(vOutPos, vOutStep)
                        ),
                        Expression.Break(outOfLoop)
                    ),
                    outOfLoop
                )
            );

            return Expression.Lambda<ConvertDelegate>(block, vInputBuffer, vClutBuffer, vOutputBuffer).Compile();
        }