Collection of draw extension methods for the Silverlight WriteableBitmap class.
Beispiel #1
0
        /// <summary>
        /// scrolls content of given rectangle
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="dx">if greater than 0, scrolls right, else scrolls left</param>
        /// <param name="rect"></param>
        public static unsafe void ScrollX(this WriteableBitmap bmp, int dx, IntRect rect, Color?background = null)
        {
            int bgcolor = WriteableBitmapExtensions.ConvertColor(background ?? Colors.White);

            using (var context = bmp.GetBitmapContext())
            {
                // Use refs for faster access (really important!) speeds up a lot!
                int w      = context.Width;
                int h      = context.Height;
                var pixels = context.Pixels;
                int xmin   = rect.Left;
                int ymin   = rect.Top;
                int xmax   = rect.Right;
                int ymax   = rect.Bottom;

                if (xmin < 0)
                {
                    xmin = 0;
                }
                if (ymin < 0)
                {
                    ymin = 0;
                }
                if (xmax >= w)
                {
                    xmax = w - 1;
                }
                if (ymax >= h)
                {
                    ymax = h - 1;
                }
                int xcnt = xmax - xmin + 1;
                int ycnt = ymax - ymin + 1;

                int srcx = xmin, dstx = xmin;
                if (dx < 0)
                {
                    xcnt += dx;
                    dstx  = xmin;
                    srcx  = xmin - dx;
                }
                if (dx > 0)
                {
                    xcnt -= dx;
                    srcx  = xmin;
                    dstx  = xmin + dx;
                }

                if (xcnt <= 0)
                {
                    return;
                }

                int *yptr = pixels + w * ymin;
                for (int y = ymin; y <= ymax; y++, yptr += w)
                {
                    NativeMethods.memcpy(yptr + dstx, yptr + srcx, xcnt * 4);
                }

                if (dx < 0)
                {
                    bmp.FillRectangle(xmax + dx + 1, ymin, xmax, ymax, bgcolor);
                }
                if (dx > 0)
                {
                    bmp.FillRectangle(xmin, ymin, xmin + dx - 1, ymax, bgcolor);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// scrolls content of given rectangle
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="dy">if greater than 0, scrolls down, else scrolls up</param>
        /// <param name="rect"></param>
        public static unsafe void ScrollY(this WriteableBitmap bmp, int dy, IntRect rect, Color?background = null)
        {
            int bgcolor = WriteableBitmapExtensions.ConvertColor(background ?? Colors.White);

            using (var context = bmp.GetBitmapContext())
            {
                // Use refs for faster access (really important!) speeds up a lot!
                int w      = context.Width;
                int h      = context.Height;
                var pixels = context.Pixels;
                int xmin   = rect.Left;
                int ymin   = rect.Top;
                int xmax   = rect.Right;
                int ymax   = rect.Bottom;

                if (xmin < 0)
                {
                    xmin = 0;
                }
                if (ymin < 0)
                {
                    ymin = 0;
                }
                if (xmax >= w)
                {
                    xmax = w - 1;
                }
                if (ymax >= h)
                {
                    ymax = h - 1;
                }
                int xcnt = xmax - xmin + 1;
                int ycnt = ymax - ymin + 1;
                if (xcnt <= 0)
                {
                    return;
                }

                if (dy > 0)
                {
                    for (int y = ymax; y >= ymin + dy; y--)
                    {
                        int ydstidex  = y;
                        int ysrcindex = y - dy;
                        if (ysrcindex < ymin || ysrcindex > ymax)
                        {
                            continue;
                        }

                        NativeMethods.memcpy(pixels + ydstidex * w + xmin, pixels + ysrcindex * w + xmin, xcnt * 4);
                    }
                }
                if (dy < 0)
                {
                    for (int y = ymin; y <= ymax - dy; y++)
                    {
                        int ysrcindex = y - dy;
                        int ydstidex  = y;
                        if (ysrcindex < ymin || ysrcindex > ymax)
                        {
                            continue;
                        }
                        NativeMethods.memcpy(pixels + ydstidex * w + xmin, pixels + ysrcindex * w + xmin, xcnt * 4);
                    }
                }

                if (dy < 0)
                {
                    bmp.FillRectangle(xmin, ymax + dy + 1, xmax, ymax, bgcolor);
                }
                if (dy > 0)
                {
                    bmp.FillRectangle(xmin, ymin, xmax, ymin + dy - 1, bgcolor);
                }
            }
        }
        public static ClearTypeLetterGlyph CreateGlyph(GlyphTypeface glyphTypeface, System.Drawing.Font font, double size, char ch, Color fontColor, Color bgColor)
        {
            if (ch == ' ')
            {
                return(CreateSpaceGlyph(glyphTypeface, size));
            }

            int width;
            int height;

            using (var bmp1 = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
            {
                using (var g = Graphics.FromImage(bmp1))
                {
                    //var sizef = g.MeasureString("" + ch, font, new PointF(0, 0), StringFormat.GenericTypographic);
                    var sizef = g.MeasureString("" + ch, font, new PointF(0, 0), StringFormat.GenericTypographic);
                    width  = (int)Math.Ceiling(sizef.Width);
                    height = (int)Math.Ceiling(sizef.Height);
                }
            }

            if (width == 0 || height == 0)
            {
                return(null);
            }

            var res = new List <Item>();

            using (var bmp = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
            {
                var fg2 = System.Drawing.Color.FromArgb(fontColor.A, fontColor.R, fontColor.G, fontColor.B);
                var bg2 = System.Drawing.Color.FromArgb(bgColor.A, bgColor.R, bgColor.G, bgColor.B);

                using (var g = System.Drawing.Graphics.FromImage(bmp))
                {
                    g.FillRectangle(new System.Drawing.SolidBrush(bg2), new Rectangle(0, 0, width, height));
                    g.DrawString("" + ch, font, new System.Drawing.SolidBrush(fg2), 0, 0, StringFormat.GenericTypographic);
                }

                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        var color = bmp.GetPixel(x, y);
                        if (color != bg2)
                        {
                            res.Add(new Item
                            {
                                X     = (short)x,
                                Y     = (short)y,
                                Color = WriteableBitmapExtensions.ConvertColor(Color.FromArgb(color.A, color.R, color.G, color.B)),
                            });
                        }
                    }
                }
            }

            //var res = new List<int>();

            //using (var bmp = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
            //{
            //    var fg2 = System.Drawing.Color.FromArgb(fontColor.A, fontColor.R, fontColor.G, fontColor.B);
            //    var bg2 = System.Drawing.Color.FromArgb(bgColor.A, bgColor.R, bgColor.G, bgColor.B);

            //    using (var g = System.Drawing.Graphics.FromImage(bmp))
            //    {
            //        g.FillRectangle(new System.Drawing.SolidBrush(bg2), new Rectangle(0, 0, width, height));
            //        g.DrawString("" + ch, font, new System.Drawing.SolidBrush(fg2), 0, 0, StringFormat.GenericTypographic);
            //    }

            //    int bgint = WriteableBitmapExtensions.ConvertColor(Color.FromArgb(bgColor.A, bgColor.R, bgColor.G, bgColor.B));
            //    for (int y = 0; y < height; y++)
            //    {
            //        var line = new List<int>();
            //        for (int x = 0; x < width; x++)
            //        {
            //            var color = bmp.GetPixel(x, y);
            //            line.Add(WriteableBitmapExtensions.ConvertColor(Color.FromArgb(color.A, color.R, color.G, color.B)));
            //        }
            //        if (line.All(x => x == bgint)) continue; // all pixels filled with BG color
            //        int minx = line.FindIndex(x => x != bgint);
            //        int maxx = line.FindLastIndex(x => x != bgint);
            //        res.Add(y);
            //        res.Add(minx);
            //        res.Add(maxx - minx + 1);
            //        for (int i = minx; i <= maxx; i++) res.Add(line[i]);
            //    }
            //}

            //res.Add(-1); // end mark

            return(new ClearTypeLetterGlyph
            {
                Width = width,
                Height = height,
                Ch = ch,
                //Instructions = res.ToArray(),
                Items = res.ToArray(),
            });
        }
 public static unsafe void Blit(this WriteableBitmap bmp, Rect destRect, WriteableBitmap source, Rect sourceRect, Color color, WriteableBitmapExtensions.BlendMode blendMode)
 {
     if ((int)color.A == 0)
         return;
     bool flag1 = source.Format == PixelFormats.Pbgra32 || source.Format == PixelFormats.Prgba64 || source.Format == PixelFormats.Prgba128Float;
     int num1 = (int)destRect.Width;
     int num2 = (int)destRect.Height;
     using (BitmapContext bitmapContext1 = WriteableBitmapContextExtensions.GetBitmapContext(source, ReadWriteMode.ReadOnly))
     {
         using (BitmapContext bitmapContext2 = WriteableBitmapContextExtensions.GetBitmapContext(bmp))
         {
             int width1 = bitmapContext1.Width;
             int width2 = bitmapContext2.Width;
             int height = bitmapContext2.Height;
             Rect rect = new Rect(0.0, 0.0, (double)width2, (double)height);
             rect.Intersect(destRect);
             if (rect.IsEmpty)
                 return;
             int* pixels1 = bitmapContext1.Pixels;
             int* pixels2 = bitmapContext2.Pixels;
             int length = bitmapContext1.Length;
             int num3 = (int)destRect.X;
             int num4 = (int)destRect.Y;
             int num5 = 0;
             int num6 = 0;
             int num7 = 0;
             int num8 = 0;
             int num9 = (int)color.A;
             int num10 = (int)color.R;
             int num11 = (int)color.G;
             int num12 = (int)color.B;
             bool flag2 = color != Colors.White;
             int num13 = (int)sourceRect.Width;
             double num14 = sourceRect.Width / destRect.Width;
             double num15 = sourceRect.Height / destRect.Height;
             int num16 = (int)sourceRect.X;
             int num17 = (int)sourceRect.Y;
             int num18 = -1;
             int num19 = -1;
             double num20 = (double)num17;
             int num21 = num4;
             for (int index1 = 0; index1 < num2; ++index1)
             {
                 if (num21 >= 0 && num21 < height)
                 {
                     double num22 = (double)num16;
                     int index2 = num3 + num21 * width2;
                     int num23 = num3;
                     int num24 = *pixels1;
                     if (blendMode == WriteableBitmapExtensions.BlendMode.None && !flag2)
                     {
                         int num25 = (int)num22 + (int)num20 * width1;
                         int num26 = num23 < 0 ? -num23 : 0;
                         int num27 = num23 + num26;
                         int num28 = width1 - num26;
                         int num29 = num27 + num28 < width2 ? num28 : width2 - num27;
                         if (num29 > num13)
                             num29 = num13;
                         if (num29 > num1)
                             num29 = num1;
                         BitmapContext.BlockCopy(bitmapContext1, (num25 + num26) * 4, bitmapContext2, (index2 + num26) * 4, num29 * 4);
                     }
                     else
                     {
                         for (int index3 = 0; index3 < num1; ++index3)
                         {
                             if (num23 >= 0 && num23 < width2)
                             {
                                 if ((int)num22 != num18 || (int)num20 != num19)
                                 {
                                     int index4 = (int)num22 + (int)num20 * width1;
                                     if (index4 >= 0 && index4 < length)
                                     {
                                         num24 = pixels1[index4];
                                         num8 = num24 >> 24 & (int)Byte.MaxValue;
                                         num5 = num24 >> 16 & (int)Byte.MaxValue;
                                         num6 = num24 >> 8 & (int)Byte.MaxValue;
                                         num7 = num24 & (int)Byte.MaxValue;
                                         if (flag2 && num8 != 0)
                                         {
                                             num8 = num8 * num9 * 32897 >> 23;
                                             num5 = (num5 * num10 * 32897 >> 23) * num9 * 32897 >> 23;
                                             num6 = (num6 * num11 * 32897 >> 23) * num9 * 32897 >> 23;
                                             num7 = (num7 * num12 * 32897 >> 23) * num9 * 32897 >> 23;
                                             num24 = num8 << 24 | num5 << 16 | num6 << 8 | num7;
                                         }
                                     }
                                     else
                                         num8 = 0;
                                 }
                                 if (blendMode == WriteableBitmapExtensions.BlendMode.None)
                                     pixels2[index2] = num24;
                                 else if (blendMode == WriteableBitmapExtensions.BlendMode.ColorKeying)
                                 {
                                     num5 = num24 >> 16 & (int)Byte.MaxValue;
                                     num6 = num24 >> 8 & (int)Byte.MaxValue;
                                     num7 = num24 & (int)Byte.MaxValue;
                                     if (num5 != (int)color.R || num6 != (int)color.G || num7 != (int)color.B)
                                         pixels2[index2] = num24;
                                 }
                                 else if (blendMode == WriteableBitmapExtensions.BlendMode.Mask)
                                 {
                                     int num25 = pixels2[index2];
                                     int num26 = num25 >> 24 & (int)Byte.MaxValue;
                                     int num27 = num25 >> 16 & (int)Byte.MaxValue;
                                     int num28 = num25 >> 8 & (int)Byte.MaxValue;
                                     int num29 = num25 & (int)Byte.MaxValue;
                                     int num30 = num26 * num8 * 32897 >> 23 << 24 | num27 * num8 * 32897 >> 23 << 16 | num28 * num8 * 32897 >> 23 << 8 | num29 * num8 * 32897 >> 23;
                                     pixels2[index2] = num30;
                                 }
                                 else if (num8 > 0)
                                 {
                                     int num25 = pixels2[index2];
                                     int num26 = num25 >> 24 & (int)Byte.MaxValue;
                                     if ((num8 == (int)Byte.MaxValue || num26 == 0) && (blendMode != WriteableBitmapExtensions.BlendMode.Additive && blendMode != WriteableBitmapExtensions.BlendMode.Subtractive) && blendMode != WriteableBitmapExtensions.BlendMode.Multiply)
                                     {
                                         pixels2[index2] = num24;
                                     }
                                     else
                                     {
                                         int num27 = num25 >> 16 & (int)Byte.MaxValue;
                                         int num28 = num25 >> 8 & (int)Byte.MaxValue;
                                         int num29 = num25 & (int)Byte.MaxValue;
                                         if (blendMode == WriteableBitmapExtensions.BlendMode.Alpha)
                                         {
                                             int num30 = (int)Byte.MaxValue - num8;
                                             num25 = !flag1 ? (num26 & (int)Byte.MaxValue) << 24 | (num5 * num8 + num30 * num27 >> 8 & (int)Byte.MaxValue) << 16 | (num6 * num8 + num30 * num28 >> 8 & (int)Byte.MaxValue) << 8 | num7 * num8 + num30 * num29 >> 8 & (int)Byte.MaxValue : (num26 & (int)Byte.MaxValue) << 24 | ((num5 << 8) + num30 * num27 >> 8 & (int)Byte.MaxValue) << 16 | ((num6 << 8) + num30 * num28 >> 8 & (int)Byte.MaxValue) << 8 | (num7 << 8) + num30 * num29 >> 8 & (int)Byte.MaxValue;
                                         }
                                         else if (blendMode == WriteableBitmapExtensions.BlendMode.Additive)
                                         {
                                             int num30 = (int)Byte.MaxValue <= num8 + num26 ? (int)Byte.MaxValue : num8 + num26;
                                             num25 = num30 << 24 | (num30 <= num5 + num27 ? num30 : num5 + num27) << 16 | (num30 <= num6 + num28 ? num30 : num6 + num28) << 8 | (num30 <= num7 + num29 ? num30 : num7 + num29);
                                         }
                                         else if (blendMode == WriteableBitmapExtensions.BlendMode.Subtractive)
                                             num25 = num26 << 24 | (num5 >= num27 ? 0 : num5 - num27) << 16 | (num6 >= num28 ? 0 : num6 - num28) << 8 | (num7 >= num29 ? 0 : num7 - num29);
                                         else if (blendMode == WriteableBitmapExtensions.BlendMode.Multiply)
                                         {
                                             int num30 = num8 * num26 + 128;
                                             int num31 = num5 * num27 + 128;
                                             int num32 = num6 * num28 + 128;
                                             int num33 = num7 * num29 + 128;
                                             int num34 = (num30 >> 8) + num30 >> 8;
                                             int num35 = (num31 >> 8) + num31 >> 8;
                                             int num36 = (num32 >> 8) + num32 >> 8;
                                             int num37 = (num33 >> 8) + num33 >> 8;
                                             num25 = num34 << 24 | (num34 <= num35 ? num34 : num35) << 16 | (num34 <= num36 ? num34 : num36) << 8 | (num34 <= num37 ? num34 : num37);
                                         }
                                         pixels2[index2] = num25;
                                     }
                                 }
                             }
                             ++num23;
                             ++index2;
                             num22 += num14;
                         }
                     }
                 }
                 num20 += num15;
                 ++num21;
             }
         }
     }
 }
        /// <summary>
        /// Rotates the bitmap in 90° steps clockwise and returns a new rotated WriteableBitmap.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="angle">The angle in degrees the bitmap should be rotated in 90° steps clockwise.</param>
        /// <returns>A new WriteableBitmap that is a rotated version of the input.</returns>
        public static WriteableBitmap Rotate(this WriteableBitmap bmp, int angle)
        {
            using (var context = bmp.GetBitmapContext(ReadWriteMode.ReadOnly))
            {
                // Use refs for faster access (really important!) speeds up a lot!
                var             w      = context.Width;
                var             h      = context.Height;
                var             p      = context.Pixels;
                var             i      = 0;
                WriteableBitmap result = null;
                angle %= 360;

                if (angle > 0 && angle <= 90)
                {
                    result = BitmapFactory.New(h, w);
                    using (var destContext = result.GetBitmapContext())
                    {
                        var rp = destContext.Pixels;
                        for (var x = 0; x < w; x++)
                        {
                            for (var y = h - 1; y >= 0; y--)
                            {
                                var srcInd = y * w + x;
                                rp[i] = p[srcInd];
                                i++;
                            }
                        }
                    }
                }
                else if (angle > 90 && angle <= 180)
                {
                    result = BitmapFactory.New(w, h);
                    using (var destContext = result.GetBitmapContext())
                    {
                        var rp = destContext.Pixels;
                        for (var y = h - 1; y >= 0; y--)
                        {
                            for (var x = w - 1; x >= 0; x--)
                            {
                                var srcInd = y * w + x;
                                rp[i] = p[srcInd];
                                i++;
                            }
                        }
                    }
                }
                else if (angle > 180 && angle <= 270)
                {
                    result = BitmapFactory.New(h, w);
                    using (var destContext = result.GetBitmapContext())
                    {
                        var rp = destContext.Pixels;
                        for (var x = w - 1; x >= 0; x--)
                        {
                            for (var y = 0; y < h; y++)
                            {
                                var srcInd = y * w + x;
                                rp[i] = p[srcInd];
                                i++;
                            }
                        }
                    }
                }
                else
                {
                    result = WriteableBitmapExtensions.Clone(bmp);
                }
                return(result);
            }
        }