/// <summary> /// Creates a new WriteableBitmap which is contrast adjusted version of this one and returns it. /// </summary> /// <param name="bmp">The WriteableBitmap.</param> /// <param name="level">Level of contrast as double. [-255.0, 255.0] </param> /// <returns>The new WriteableBitmap.</returns> public static BitmapBuffer AdjustContrast(this BitmapBuffer bmp, double level) { int factor = (int)((259.0 * (level + 255.0)) / (255.0 * (259.0 - level)) * 255.0); using (BitmapContext context = bmp.GetBitmapContext(ReadWriteMode.ReadOnly)) { int nWidth = context.Width; int nHeight = context.Height; unsafe { NativeInt32Arr px1 = context.Pixels; int * px = px1._inf32Buffer; BitmapBuffer result = BitmapBufferFactory.New(nWidth, nHeight); using (BitmapContext dest = result.GetBitmapContext()) { NativeInt32Arr rp1 = dest.Pixels; int * rp = rp1._inf32Buffer; int len = context.Length; for (int i = 0; i < len; i++) { // Extract int c = px[i]; int a = (c >> 24) & 0xff; int r = (c >> 16) & 0xff; int g = (c >> 8) & 0xff; int b = (c) & 0xff; // Adjust contrast based on computed factor //TODO: create lookup table for this r = ((factor * (r - 128)) >> 8) + 128; g = ((factor * (g - 128)) >> 8) + 128; b = ((factor * (b - 128)) >> 8) + 128; // Clamp r = r < 0 ? 0 : r > 255 ? 255 : r; g = g < 0 ? 0 : g > 255 ? 255 : g; b = b < 0 ? 0 : b > 255 ? 255 : b; // Set rp[i] = (a << 24) | (r << 16) | (g << 8) | b; } } return(result); } } }
/// <summary> /// Creates a new WriteableBitmap which is the grayscaled version of this one and returns it. The gray values are equal to the brightness values. /// </summary> /// <param name="bmp">The WriteableBitmap.</param> /// <returns>The new gray WriteableBitmap.</returns> public static BitmapBuffer Gray(this BitmapBuffer bmp) { using (BitmapContext context = bmp.GetBitmapContext(ReadWriteMode.ReadOnly)) { int nWidth = context.Width; int nHeight = context.Height; unsafe { BitmapBuffer result = BitmapBufferFactory.New(nWidth, nHeight); using (BitmapContext dest = result.GetBitmapContext()) { NativeInt32Arr px1 = context.Pixels; NativeInt32Arr rp1 = dest.Pixels; int len = context.Length; int * px = px1._inf32Buffer; int * rp = rp1._inf32Buffer; for (int i = 0; i < len; i++) { // Extract int c = px[i]; int a = (c >> 24) & 0xff; int r = (c >> 16) & 0xff; int g = (c >> 8) & 0xff; int b = (c) & 0xff; // Convert to gray with constant factors 0.2126, 0.7152, 0.0722 r = g = b = ((r * 6966 + g * 23436 + b * 2366) >> 15); // Set rp[i] = (a << 24) | (r << 16) | (g << 8) | b; } } return(result); } } }
private static void AAWidthLine(int width, int height, BitmapContext context, float x1, float y1, float x2, float y2, float lineWidth, Int32 color, RectD?clipRect = null) { // Perform cohen-sutherland clipping if either point is out of the viewport if (!CohenSutherlandLineClip(clipRect ?? new RectD(0, 0, width, height), ref x1, ref y1, ref x2, ref y2)) { return; } if (lineWidth <= 0) { return; } unsafe { NativeInt32Arr buffer1 = context.Pixels; int * buffer = buffer1._inf32Buffer; if (y1 > y2) { Swap(ref x1, ref x2); Swap(ref y1, ref y2); } if (x1 == x2) { x1 -= (int)lineWidth / 2; x2 += (int)lineWidth / 2; if (x1 < 0) { x1 = 0; } if (x2 < 0) { return; } if (x1 >= width) { return; } if (x2 >= width) { x2 = width - 1; } if (y1 >= height || y2 < 0) { return; } if (y1 < 0) { y1 = 0; } if (y2 >= height) { y2 = height - 1; } for (int x = (int)x1; x <= x2; x++) { for (int y = (int)y1; y <= y2; y++) { byte a = (byte)((color & 0xff000000) >> 24); byte r = (byte)((color & 0x00ff0000) >> 16); byte g = (byte)((color & 0x0000ff00) >> 8); byte b = (byte)((color & 0x000000ff) >> 0); byte rs, gs, bs; byte rd, gd, bd; int d; rs = r; gs = g; bs = b; d = buffer[y * width + x]; rd = (byte)((d & 0x00ff0000) >> 16); gd = (byte)((d & 0x0000ff00) >> 8); bd = (byte)((d & 0x000000ff) >> 0); rd = (byte)((rs * a + rd * (0xff - a)) >> 8); gd = (byte)((gs * a + gd * (0xff - a)) >> 8); bd = (byte)((bs * a + bd * (0xff - a)) >> 8); buffer[y * width + x] = (0xff << 24) | (rd << 16) | (gd << 8) | (bd << 0); } } return; } if (y1 == y2) { if (x1 > x2) { Swap(ref x1, ref x2); } y1 -= (int)lineWidth / 2; y2 += (int)lineWidth / 2; if (y1 < 0) { y1 = 0; } if (y2 < 0) { return; } if (y1 >= height) { return; } if (y2 >= height) { y2 = height - 1; } if (x1 >= width || y2 < 0) { return; } if (x1 < 0) { x1 = 0; } if (x2 >= width) { x2 = width - 1; } for (int x = (int)x1; x <= x2; x++) { for (int y = (int)y1; y <= y2; y++) { byte a = (byte)((color & 0xff000000) >> 24); byte r = (byte)((color & 0x00ff0000) >> 16); byte g = (byte)((color & 0x0000ff00) >> 8); byte b = (byte)((color & 0x000000ff) >> 0); Byte rs, gs, bs; Byte rd, gd, bd; Int32 d; rs = r; gs = g; bs = b; d = buffer[y * width + x]; rd = (byte)((d & 0x00ff0000) >> 16); gd = (byte)((d & 0x0000ff00) >> 8); bd = (byte)((d & 0x000000ff) >> 0); rd = (byte)((rs * a + rd * (0xff - a)) >> 8); gd = (byte)((gs * a + gd * (0xff - a)) >> 8); bd = (byte)((bs * a + bd * (0xff - a)) >> 8); buffer[y * width + x] = (0xff << 24) | (rd << 16) | (gd << 8) | (bd << 0); } } return; } y1 += 1; y2 += 1; float slope = (y2 - y1) / (x2 - x1); float islope = (x2 - x1) / (y2 - y1); float m = slope; float w = lineWidth; float dx = x2 - x1; float dy = y2 - y1; float xtot = (float)(w * dy / Math.Sqrt(dx * dx + dy * dy)); float ytot = (float)(w * dx / Math.Sqrt(dx * dx + dy * dy)); float sm = dx * dy / (dx * dx + dy * dy); // Center it. x1 += xtot / 2; y1 -= ytot / 2; x2 += xtot / 2; y2 -= ytot / 2; // // float sx = -xtot; float sy = +ytot; int ix1 = (int)x1; int iy1 = (int)y1; int ix2 = (int)x2; int iy2 = (int)y2; int ix3 = (int)(x1 + sx); int iy3 = (int)(y1 + sy); int ix4 = (int)(x2 + sx); int iy4 = (int)(y2 + sy); if (lineWidth == 2) { if (Math.Abs(dy) < Math.Abs(dx)) { if (x1 < x2) { iy3 = iy1 + 2; iy4 = iy2 + 2; } else { iy1 = iy3 + 2; iy2 = iy4 + 2; } } else { ix1 = ix3 + 2; ix2 = ix4 + 2; } } int starty = Math.Min(Math.Min(iy1, iy2), Math.Min(iy3, iy4)); int endy = Math.Max(Math.Max(iy1, iy2), Math.Max(iy3, iy4)); if (starty < 0) { starty = -1; } if (endy >= height) { endy = height + 1; } for (int y = starty + 1; y < endy - 1; y++) { leftEdgeX[y] = -1 << 16; rightEdgeX[y] = 1 << 16 - 1; } AALineQ1(width, height, context, ix1, iy1, ix2, iy2, color, sy > 0, false); AALineQ1(width, height, context, ix3, iy3, ix4, iy4, color, sy < 0, true); if (lineWidth > 1) { AALineQ1(width, height, context, ix1, iy1, ix3, iy3, color, true, sy > 0); AALineQ1(width, height, context, ix2, iy2, ix4, iy4, color, false, sy < 0); } if (x1 < x2) { if (iy2 >= 0 && iy2 < height) { rightEdgeX[iy2] = Math.Min(ix2, rightEdgeX[iy2]); } if (iy3 >= 0 && iy3 < height) { leftEdgeX[iy3] = Math.Max(ix3, leftEdgeX[iy3]); } } else { if (iy1 >= 0 && iy1 < height) { rightEdgeX[iy1] = Math.Min(ix1, rightEdgeX[iy1]); } if (iy4 >= 0 && iy4 < height) { leftEdgeX[iy4] = Math.Max(ix4, leftEdgeX[iy4]); } } //return; for (int y = starty + 1; y < endy - 1; y++) { leftEdgeX[y] = Math.Max(leftEdgeX[y], 0); rightEdgeX[y] = Math.Min(rightEdgeX[y], width - 1); for (int x = leftEdgeX[y]; x <= rightEdgeX[y]; x++) { byte a = (byte)((color & 0xff000000) >> 24); byte r = (byte)((color & 0x00ff0000) >> 16); byte g = (byte)((color & 0x0000ff00) >> 8); byte b = (byte)((color & 0x000000ff) >> 0); Byte rs, gs, bs; Byte rd, gd, bd; Int32 d; rs = r; gs = g; bs = b; d = buffer[y * width + x]; rd = (byte)((d & 0x00ff0000) >> 16); gd = (byte)((d & 0x0000ff00) >> 8); bd = (byte)((d & 0x000000ff) >> 0); rd = (byte)((rs * a + rd * (0xff - a)) >> 8); gd = (byte)((gs * a + gd * (0xff - a)) >> 8); bd = (byte)((bs * a + bd * (0xff - a)) >> 8); buffer[y * width + x] = (0xff << 24) | (rd << 16) | (gd << 8) | (bd << 0); } } } }