/// <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); } } }
/// <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); } }