コード例 #1
0
 /// <summary>
 /// http://en.wikipedia.org/wiki/Alpha_compositing
 /// </summary>
 /// <param name="destination_rect"></param>
 /// <param name="source"></param>
 /// <param name="source_rect"></param>
 /// <param name="blendMode"></param>
 public void Blit(
     Rectangle destination_rect,
     IPixelCanvas source,
     Rectangle source_rect,
     BlendMode blendMode)
 {
     Blit(destination_rect, source, source_rect, 255, 255, 255, 255, blendMode);
 }
コード例 #2
0
 /// <summary>
 /// http://en.wikipedia.org/wiki/Alpha_compositing
 /// </summary>
 /// <param name="destination_rect"></param>
 /// <param name="source"></param>
 /// <param name="source_rect"></param>
 /// <param name="blendMode"></param>
 public void Blit(
     System.Drawing.Rectangle destination_rect,
     IPixelCanvas source,
     System.Drawing.Rectangle source_rect,
     BlendMode blendMode
     )
 {
     Blit(destination_rect, source, source_rect, 255, 255, 255, 255, blendMode);
 }
コード例 #3
0
        public void DrawLineDDA(Rectangle bounds, int x1, int y1, int x2, int y2, IPixelCanvas pen, BlendMode blendMode = BlendMode.Copy)
        {
            var x1_d = (double)x1;
            var y1_d = (double)y1;
            var x2_d = (double)x2;
            var y2_d = (double)y2;

            if (!TryCohenSutherlandClip(bounds, ref x1_d, ref y1_d, ref x2_d, ref y2_d))
                return;

            DrawLineDDA((int)x1_d, (int)y1_d, (int)x2_d, (int)y2_d, pen, blendMode);
        }
コード例 #4
0
        /// <summary>
        /// http://en.wikipedia.org/wiki/Alpha_compositing
        /// </summary>
        /// <param name="destination_rect"></param>
        /// <param name="source"></param>
        /// <param name="source_rect"></param>
        /// <param name="alpha"></param>
        /// <param name="red"></param>
        /// <param name="green"></param>
        /// <param name="blue"></param>
        /// <param name="blendMode"></param>
        public void Blit(
            System.Drawing.Rectangle destination_rect,
            IPixelCanvas source,
            System.Drawing.Rectangle source_rect,
            byte alpha,
            byte red,
            byte green,
            byte blue,
            BlendMode blendMode)
        {

            // http://keithp.com/~keithp/porterduff/p253-porter.pdf
            // http://en.wikipedia.org/wiki/Alpha_compositing

            // tint with transparent color, nothing to do here, since this would make every source pixel transparent
            if (alpha == 0)
                return;

            if (!IntersectsWith(destination_rect))
                return;

            // tinted if color is not opaque white
            var is_tinted = alpha != 255 || red != 255 || green != 255 || blue != 255;

            var source_width = source.Width;
            var source_pixels = source;
            var source_length = source.Length;

            int source_rectangle_x = source_rect.X;
            int source_rectangle_y = source_rect.Y;

            var destination_width = Width;
            var destination_height = Height;
            var destination_pixels = this;
            var destination_length = Length;

            int destination_rectangle_x = destination_rect.X;
            int destination_rectangle_y = destination_rect.Y;
            int destination_rect_width = destination_rect.Width;
            int destination_rect_height = destination_rect.Height;

            int sourceIdx = -1;
            int idx;
            double ii;
            double jj;

            int source_pixel = 0;
            int source_alpha = 0;
            int source_red = 0;
            int source_green = 0;
            int source_blue = 0;

            int destination_alpha;
            int destination_red;
            int destination_green;
            int destination_blue;
            
            var source_rectangle_width = source_rect.Width;

            var sdx = source_rect.Width / destination_rect.Width;
            var sdy = source_rect.Height / destination_rect.Height;

            int lastii = -1;
            int lastjj = -1;

            jj = source_rectangle_y;


            int current_x;
            int current_y = destination_rectangle_y;

            // each row in destination rectangle
            for (int destination_rect_row = 0; destination_rect_row < destination_rect_height; destination_rect_row++)
            {
                // check if current y is within destination rectangle bounds (todo: >= 0? should it be destination_rect_y ?)
                if (current_y >= 0 && current_y < destination_height)
                {
                    ii = source_rectangle_x;
                    idx = destination_rectangle_x + current_y * destination_width;

                    // start from left most column in destination rectangle
                    current_x = destination_rectangle_x;

                    // each column in destination rectangle
                    for (int destination_rect_col = 0; destination_rect_col < destination_rect_width; destination_rect_col++)
                    {
                        // todo: >= 0?
                        if (current_x >= 0 && current_x < destination_width)
                        {
                            if ((int)ii != lastii || (int)jj != lastjj)
                            {
                                sourceIdx = (int)ii + (int)jj * source_width;

                                if (sourceIdx >= 0 && sourceIdx < source_length)
                                {
                                    // retrieve current source pixel and it's channels values
                                    source_pixel = source_pixels[sourceIdx];

                                    if (blendMode == BlendMode.Copy)
                                    {
                                        destination_pixels[idx] = source_pixel;

                                        current_x++;
                                        idx++;
                                        ii += sdx;

                                        continue;
                                    }

                                    if (source_pixel != 0)
                                    {
                                        source_alpha = ((source_pixel >> 24) & 0xff);
                                        source_red = ((source_pixel >> 16) & 0xff);
                                        source_green = ((source_pixel >> 8) & 0xff);
                                        source_blue = ((source_pixel) & 0xff);

                                        // tint the pixel if needed
                                        if (is_tinted && source_alpha != 0)
                                        {
                                            source_alpha = (((source_alpha * alpha) * 0x8081) >> 23);
                                            source_red = ((((((source_red * red) * 0x8081) >> 23) * alpha) * 0x8081) >> 23);
                                            source_green = ((((((source_green * green) * 0x8081) >> 23) * alpha) * 0x8081) >> 23);
                                            source_blue = ((((((source_blue * blue) * 0x8081) >> 23) * alpha) * 0x8081) >> 23);

                                            source_pixel = (source_alpha << 24) | (source_red << 16) | (source_green << 8) | source_blue;
                                        }
                                    }
                                    else
                                    {
                                        source_alpha = 0;
                                    }
                                }
                                else
                                {
                                    source_alpha = 0;
                                }
                            }

                            if (source_alpha == 0)
                            {
                                current_x++;
                                idx++;
                                ii += sdx;

                                continue;
                            }
                            else
                            {
                                // get destination pixel
                                int destPixel = destination_pixels[idx];

                                destination_alpha = ((destPixel >> 24) & 0xff);

                                // destination is transparent or source is opaque,
                                // just replace destination pixel with source pixel
                                if (blendMode == BlendMode.Alpha && (source_alpha == 255 || destination_alpha == 0))
                                {
                                    destination_pixels[idx] = source_pixel;

                                    current_x++;
                                    idx++;
                                    ii += sdx;

                                    continue;
                                }

                                // get destination pixel rgb values
                                destination_red = ((destPixel >> 16) & 0xff);
                                destination_green = ((destPixel >> 8) & 0xff);
                                destination_blue = ((destPixel) & 0xff);

                                if (blendMode == BlendMode.Alpha)
                                {
                                    var isa = 255 - source_alpha;

                                    destPixel = ((destination_alpha & 0xff) << 24) |
                                                (((((source_red << 8) + isa * destination_red) >> 8) & 0xff) << 16) |
                                                (((((source_green << 8) + isa * destination_green) >> 8) & 0xff) << 8) |
                                                 ((((source_blue << 8) + isa * destination_blue) >> 8) & 0xff);
                                }
                                else
                                    throw new NotSupportedException();

                                destination_pixels[idx] = destPixel;
                            }
                        }

                        current_x++;
                        idx++;
                        ii += sdx;
                    }
                }
                jj += sdy;
                current_y++;
            }
        }
コード例 #5
0
 public void Blit(IPixelCanvas source, BlendMode blendMode)
 {
     Blit(this.Bounds, source, source.Bounds, blendMode);
 }
コード例 #6
0
 public void DrawLine(int x1, int y1, int x2, int y2, IPixelCanvas pen, BlendMode blendMode = BlendMode.Copy)
 {
     DrawLineDDA(x1, y1, x2, y2, pen);
 }
コード例 #7
0
        public void DrawLineDDA(int x1, int y1, int x2, int y2, IPixelCanvas pen, BlendMode blendMode = BlendMode.Copy)
        {
            if (pen.Bounds.IsEmpty)
                return;

            var pen_centre_x = pen.Width / 2;
            var pen_centre_y = pen.Height / 2;

            // http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

            // cartesian slope-intercept http://en.wikipedia.org/wiki/Linear_equation#Slope.E2.80.93intercept_form
            // y = mx + b
            // m - slope of the line
            // b - y intercept (y coordinate of location where the line crosses the y axis)

            // write above equation as function of both x and y
            // slope is the "rise over run" or dx / dy
            //
            // y = mx + b
            // y = dy/dx * x + b
            // dx * y = dy * x + dx * b
            // 0 = dy*x - dx*y + dx*b
            // f(x,y) = 0 = Ax + By + C
            //  where
            //  A = dy
            //  B = -dx
            //  C = dx*b

            var dx = x2 - x1;
            var dy = y2 - y1;


            //# calculate number of steps as greather of max(abs(dx), abs(dy))
            // use maximum possible number of steps for better accuracy
            // do not user Math class here for quicker execution
            var dx_abs = dx;
            if (dx_abs < 0)
                dx_abs = -dx;

            var dy_abs = dy;
            if (dy_abs < 0)
                dy_abs = -dy;

            // calculate x and y steps

            var x_step = 0.0f;
            var y_step = 0.0f;

            var steps = dx_abs;
            if (dx_abs < dy_abs)
                steps = dy_abs;

            x_step = dx / (float)steps;
            y_step = dy / (float)steps;

            if (steps == 0)
                return;

            // line start point
            var x = (float)x1;
            var y = (float)y1;

            //var dash_style = new bool[] { true, false, false };
            //var dash_i = 0;

            for (int i = 0; i <= steps; i++)
            {
                if (y < _height && y >= 0 && x < _width && x >= 0)
                {
                    //if (dash_style[dash_i])
                    {
                        // blit pen at the centre
                        var dest_rect = new Rectangle(x - pen_centre_x, y - pen_centre_y, pen.Width, pen.Height);
                        Blit(dest_rect, pen, pen.Bounds, blendMode);
                    }

                    //dash_i = (dash_i + 1) % dash_style.Length;
                }

                x += x_step;
                y += y_step;
            }
        }
コード例 #8
0
 public static IPixelCanvas Blit(IPixelCanvas first, IPixelCanvas second, BlendMode blendMode)
 {
     var pc = new PixelArrayCanvas(first.Width, first.Height);
     pc.Blit(second, blendMode);
     return pc;
 }
コード例 #9
0
 public void Draw(IPixelCanvas pc, DrawingContext cx, CancellationToken ct)
 {
     DrawAction(pc, cx, ct);
 }
コード例 #10
0
 public void Draw(IPixelCanvas pc, CancellationToken ct)
 {
     DrawAction(pc, ct);
 }