public void FillGrid(Grid g, FillOptions options) { using (var bitmapWrapper = new BmpPixelSnoop(drawArea)) using (var textureWrapper = options.Texture != null ? new BmpPixelSnoop(options.Texture) : null) Parallel.ForEach(g.GetPolygons(), t => AlgorithmUtils.FillPolygon(t, options, bitmapWrapper, textureWrapper)); //g.GetPolygons().ForEach(t => AlgorithmUtils.FillPolygon(t, options, bitmapWrapper, textureWrapper)); }
/// <summary> /// Test that GetPixel() works the same way as Bitmap.GetPixel() /// </summary> /// <param name="bmp">The bitmap to test with</param> static void TestGetPixel(Bitmap bmp) { Console.WriteLine("Testing GetPixel()"); // Deep copy the bitmap var bmpClone = bmp.Clone() as Bitmap; // Now create a snoop over the clone and // iterate over both and compare each pixel // using (var snoop = new BmpPixelSnoop(bmpClone)) { for (int j = 0; j != bmp.Height; j++) { for (int i = 0; i != bmp.Width; i++) { // Normal Butmap.GetPixel() var p1 = bmp.GetPixel(i, j); // BmpPixelSnoop's GetPixel() var p2 = snoop.GetPixel(i, j); // Are they the same (they should be..) if (p1 != p2) { throw new Exception(string.Format("Pixel at ({0}, {1}) does not match!", i, j)); } } } } Console.WriteLine("GetPixel() OK"); }
private static Bitmap ReduceColorsWithoutCachedBitmap(Options options, ProgressBar progressBar) { Bitmap reducedImage = new Bitmap(options.OriginalImage); using (var reducedWrapper = new BmpPixelSnoop(reducedImage)) { var random = new Random(); bool isChange = true; int k = options.ColorsNumber; Color[] centroids = new Color[k]; (int R, int G, int B)[] sums = new (int R, int G, int B)[k];
public static Bitmap ReduceColors(Options options, ProgressBar progressBar) { var filter = GetFilter(options.EDDFiler); Bitmap reducedImage = new Bitmap(options.OriginalImage);//new Bitmap(originalImage.Width, originalImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); //using (BmpPixelSnoop originalWrapper = new BmpPixelSnoop(originalImage)) using (BmpPixelSnoop reducedWrapper = new BmpPixelSnoop(reducedImage)) { for (int i = 0; i < reducedImage.Width; i++) { for (int j = 0; j < reducedImage.Height; j++) { var originalImagePixel = reducedWrapper.GetPixel(i, j); var r = (int)Approximate(originalImagePixel.R, options.RNumber); var g = (int)Approximate(originalImagePixel.G, options.GNumber); var b = (int)Approximate(originalImagePixel.B, options.BNumber); reducedWrapper.SetPixel(i, j, Color.FromArgb(r, g, b)); double errorR = originalImagePixel.R - r; double errorG = originalImagePixel.G - g; double errorB = originalImagePixel.B - b; int f_x = filter.GetLength(0) / 2; int f_y = filter.GetLength(1) / 2; for (int ii = -f_x; ii <= f_x; ii++) { if (i + ii >= reducedImage.Width || i + ii < 0) { continue; } for (int jj = -f_y; jj <= f_y; jj++) { if (j + jj >= reducedImage.Height || j + jj < 0) { continue; } var colorToSet = reducedWrapper.GetPixel(i + ii, j + jj); colorToSet = Color.FromArgb( CutTo_0_255(colorToSet.R + (errorR * filter[f_x + ii, f_y + jj])), CutTo_0_255(colorToSet.G + (errorG * filter[f_x + ii, f_y + jj])), CutTo_0_255(colorToSet.B + (errorB * filter[f_x + ii, f_y + jj]))); reducedWrapper.SetPixel(i + ii, j + jj, colorToSet); } } } progressBar.Value = (int)((i * progressBar.Maximum) / (double)reducedImage.Width); } } progressBar.Value = progressBar.Maximum; return(reducedImage); }
/// <summary> /// Test that SetPixel() works the same way as Bitmap.SetPixel() /// </summary> /// <param name="bmp">The bitmap to test with</param> static void TestSetPixel(Bitmap bmp) { Console.WriteLine("Testing SetPixel()"); // Create an empty target bitmap // PixelFormat.Format32bppArgb is the default format var bmpTarget = new Bitmap(bmp.Width, bmp.Height); // We get each pixel from the input bitmap and // set to the corresponding pixel in the snooped bitmap. // Then we read back this pixel and check that it equals the // original pixel value. // using (var snoop = new BmpPixelSnoop(bmpTarget)) { for (int j = 0; j != bmp.Height; j++) { for (int i = 0; i != bmp.Width; i++) { // Get a pixel from the input bitmap var p1 = bmp.GetPixel(i, j); // Set it into the snooped bitmap snoop.SetPixel(i, j, p1); // Read it back from the snooped bitmap var p2 = snoop.GetPixel(i, j); // And compare with original. if (p1 != p2) { throw new Exception(string.Format("Pixel at ({0}, {1}) does not match!", i, j)); } } } } // Now test that the snooped bitmap has been released and // that we can call SetPixel() on it without an excpetion // being thrown... // try { bmpTarget.SetPixel(0, 0, System.Drawing.Color.Aqua); } catch { throw new Exception(string.Format("Could not write to bitmap, BitmapSnoop did not release it!")); } Console.WriteLine("SetPixel() OK"); }
private void openVectorTexture_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "image(.png,.jpg)|*.jpg;*.png"; if (dialog.ShowDialog() == DialogResult.OK) { var texture = new Bitmap(dialog.FileName); normalMap = new BmpPixelSnoop(texture.Clone(new Rectangle(0, 0, texture.Width, texture.Height), System.Drawing.Imaging.PixelFormat.Format32bppArgb)); } normal_map_loaded = true; drawing_panel.Invalidate(); }
public static Bitmap ReduceColors(Options options, ProgressBar progressBar) { Dictionary <(byte R, byte G, byte B), int> colorsPopularity = new Dictionary <(byte R, byte G, byte B), int>(); var reducedBitmap = new Bitmap(options.OriginalImage); using (var reducedWrapper = new BmpPixelSnoop(reducedBitmap)) { for (int i = 0; i < reducedBitmap.Width; i++) { for (int j = 0; j < reducedBitmap.Height; j++) { var c = reducedWrapper.GetPixel(i, j); if (!colorsPopularity.TryGetValue((c.R, c.G, c.B), out int cPopularity)) { colorsPopularity[(c.R, c.G, c.B)] = 1;
/// <summary> /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="options"></param> /// <returns></returns> /// <remarks>Only for triangles.</remarks> private static Color GetInterpolatedColorForPixel( double x1, double y1, double x2, double y2, double x3, double y3, double triangleDenominator, // cout once, use for each pixel Vector normalVector1, // cout once, use for each pixel Vector normalVector2, // cout once, use for each pixel Vector normalVector3, // cout once, use for each pixel Color objectColor1, // cout once, use for each pixel Color objectColor2, // cout once, use for each pixel Color objectColor3, // cout once, use for each pixel int x, int y, FillOptions options, BmpPixelSnoop textureWrapper) { // calculate barycentric coordinates double W1 = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / triangleDenominator; double W2 = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / triangleDenominator; double W3 = 1 - W1 - W2; Vector N = options.NormalVectorOption == NormalVectorOpt.FromTexture ? W1 * normalVector1 + W2 * normalVector2 + W3 * normalVector3 // inerpolated normal vector : DEFAULT_OPTIONS.defaultNormalVector; Vector V = new Vector(0, 0, 1); var LightPoint = options.LightPoint; var L = (options.LightVectorOption == LightVectorOpt.FromPointOnSpiral && LightPoint != null) ? new Vector(LightPoint.X - x, (-1) * (LightPoint.Y - y), LightPoint.Z - 0).GetNormalised() : DEFAULT_OPTIONS.defaultLightVector; Vector R = 2 * Vector.DotProduct(N, L) * N - L; Color Il = options.LightColor; Color Io = (options.ObjectColorOption == ObjectColorOpt.Constant || options.Texture == null) ? (Color)options.ObjectColor : Color.FromArgb( round_To_0_255((int)(W1 * objectColor1.R + W2 * objectColor2.R + W3 * objectColor3.R)), round_To_0_255((int)(W1 * objectColor1.G + W2 * objectColor2.G + W3 * objectColor3.G)), round_To_0_255((int)(W1 * objectColor1.B + W2 * objectColor2.B + W3 * objectColor3.B))); // interpolated object color double kd = options.LambertModelFactor; double ks = options.ReflectionFactor; int m = options.ReflectionLevel; return(Color.FromArgb(calculatePart(Il.R, Io.R, kd, ks, N, L, V, R, m), calculatePart(Il.G, Io.G, kd, ks, N, L, V, R, m), calculatePart(Il.B, Io.B, kd, ks, N, L, V, R, m))); }
/// <summary> /// Test how fast SetPixel() works compared to Bitmap.SetPixel() /// </summary> /// <param name="bmp">The bitmap to test with</param> static void TestSetPixelSpeed(Bitmap bmp) { Console.WriteLine("Testing SetPixel() Speed"); // Deep copy the bitmap var bmpClone = bmp.Clone() as Bitmap; var stopwatch = new Stopwatch(); stopwatch.Start(); // Loop through the bitmap and set each pixel's value // to something interesting.. for (int j = 0; j != bmpClone.Height; j++) { for (int i = 0; i != bmpClone.Width; i++) { var col = Color.FromArgb(i % 255, j % 255, (i + j) % 255, (i * j) % 255); bmpClone.SetPixel(i, j, col); } } var time = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); stopwatch.Start(); // Now do the same on the snooped bitmap.. using (var snoop = new BmpPixelSnoop(bmpClone)) { for (int j = 1; j != snoop.Height; j++) { for (int i = 0; i != snoop.Width; i++) { var col = Color.FromArgb(i % 255, j % 255, (i * j) % 255, (i + j) % 255); snoop.SetPixel(i, j, col); } } } var snoopTime = stopwatch.ElapsedMilliseconds; Console.WriteLine(string.Format("Bitmap.SetPixel() took {0}ms, BmpPixelSnoop.SetPixel() took {1}ms", time, snoopTime)); }
private void drawing_panel_Paint(object sender, PaintEventArgs e) { //foreach (var tri in triangles_net) Bitmap tmp = new Bitmap(drawing_panel.Width, drawing_panel.Height); tmpPicture = new BmpPixelSnoop(tmp); Parallel.ForEach(triangles_net, (Polygon tri) => // foreach (var tri in triangles_net) { if (!moving) { if (aproximate.Checked) { FillFigureAprox(tri, Ks, Kd, M); } else if (hybrid.Checked) { FillFigureHybrid(tri, Ks, Kd, M); } else { FillFigure(tri, Ks, Kd, M); } } }); tmpPicture.Dispose(); e.Graphics.DrawImage(tmp, 0, 0); tmp.Dispose(); foreach (var tri in triangles_net) { foreach (var edge in tri.edges) { DrawLine(edge, e.Graphics); } } //foreach (var point in tri.vertices) //{ // DrawVertice(point.Get(), e.Graphics); //} }
private static Vector getNormalVectorFromTexture(int x, int y, FillOptions options, BmpPixelSnoop textureWrapper) { if (textureWrapper == null) { return(DEFAULT_OPTIONS.defaultNormalVector); } var vector = textureWrapper.GetPixel(x - (int)(options.GridLeft), y - (int)(options.GridTop)); return(new Vector(scaleToNormalVector(vector.R), scaleToNormalVector(vector.G), scale_Form_0_255_To_0_1(vector.B)).GetNormalised()); double scaleToNormalVector(int c) { var ret = ((double)c / 255) * 2 - 1; if (ret > 1) { return(1); } if (ret < -1) { return(-1); } return(ret); } }
public static void FillPolygon(Polygon polygon, FillOptions options, BmpPixelSnoop bitmapWrapper, BmpPixelSnoop textureWrapper) { #region prepare data for interpolation if needed double x1 = 1, y1 = 1; double x2 = 1, y2 = 1; double x3 = 1, y3 = 1; double triangleDenominator = 1; Vector normalVector1 = null; Vector normalVector2 = null; Vector normalVector3 = null; Color objectColor1 = Color.FromArgb(1, 1, 1); Color objectColor2 = Color.FromArgb(1, 1, 1); Color objectColor3 = Color.FromArgb(1, 1, 1); if (options.FillColorPrecisionOption == FillColorPrecisionOpt.Interpolated) { // assume polygon is a traingle if (polygon.Vertices.Count != 3) { throw new ArgumentException("Interpolated Presices is possible only for triangles!"); } x1 = polygon.Vertices[0].X; y1 = polygon.Vertices[0].Y; x2 = polygon.Vertices[1].X; y2 = polygon.Vertices[1].Y; x3 = polygon.Vertices[2].X; y3 = polygon.Vertices[2].Y; triangleDenominator = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3); if (triangleDenominator == 0) { triangleDenominator = 1; } normalVector1 = getNormalVectorFromTexture((int)x1, (int)y1, options, textureWrapper); normalVector2 = getNormalVectorFromTexture((int)x2, (int)y2, options, textureWrapper); normalVector3 = getNormalVectorFromTexture((int)x3, (int)y3, options, textureWrapper); objectColor1 = (options.ObjectColorOption == ObjectColorOpt.Constant || options.Texture == null) ? (Color)options.ObjectColor : textureWrapper.GetPixel((int)(x1 - options.GridLeft), (int)(y1 - options.GridTop)); objectColor2 = (options.ObjectColorOption == ObjectColorOpt.Constant || options.Texture == null) ? (Color)options.ObjectColor : textureWrapper.GetPixel((int)(x2 - options.GridLeft), (int)(y2 - options.GridTop)); objectColor3 = (options.ObjectColorOption == ObjectColorOpt.Constant || options.Texture == null) ? (Color)options.ObjectColor : textureWrapper.GetPixel((int)(x3 - options.GridLeft), (int)(y3 - options.GridTop)); } #endregion var sortedVertices = polygon.Vertices.ConvertAll(v => v); sortedVertices.Sort((a, b) => { if (a.Y < b.Y) { return(-1); } if (a.Y == b.Y) { return(0); } return(1); }); var ind = sortedVertices.ConvertAll(v => polygon.Vertices.IndexOf(v)); var P = polygon.Vertices; double ymin = P[ind[0]].Y; double ymax = P[ind[ind.Count - 1]].Y; int k = 0; // current vertex index; List <AETItem> AET = new List <AETItem>(); // for each scanline for (double y = ymin + 1; y <= ymax + 1; y++) { while (k < ind.Count && y - 1 == P[ind[k]].Y) { // previous vertex int pVertInd = ind[k] - 1 >= 0 ? ind[k] - 1 : P.Count - 1; if (P[pVertInd].Y >= P[ind[k]].Y) { // add to AET double dx = (double)(P[pVertInd].X - P[ind[k]].X); double dy = (double)(P[pVertInd].Y - P[ind[k]].Y); if (dy != 0) { AET.Add(new AETItem(P[pVertInd], P[ind[k]], P[ind[k]].X, dx / dy)); } } else { // remove from AET AET.RemoveAll(i => i.start == P[pVertInd] && i.end == P[ind[k]]); } // next vertex int nVertInd = ind[k] + 1 < P.Count ? ind[k] + 1 : 0; if (P[nVertInd].Y >= P[ind[k]].Y) { // add to AET double dx = (double)(P[ind[k]].X - P[nVertInd].X); double dy = (double)(P[ind[k]].Y - P[nVertInd].Y); if (dy != 0) { AET.Add(new AETItem(P[ind[k]], P[nVertInd], P[ind[k]].X, dx / dy)); } } else { // remove from AET AET.RemoveAll(i => i.start == P[ind[k]] && i.end == P[nVertInd]); } k++; } // sort by x AET.Sort((a, b) => { if (a.x < b.x) { return(-1); } if (a.x == b.x) { return(0); } return(1); }); // set pixels for (int i = 0; i < AET.Count - 1; i += 2) { for (double x = AET[i].x; x <= AET[i + 1].x; x++) { bitmapWrapper.SetPixel((int)x, (int)y - 1, options.FillColorPrecisionOption == FillColorPrecisionOpt.Precise ? GetPreciseColorForPixel((int)x, (int)y - 1, options, textureWrapper) : GetInterpolatedColorForPixel( (int)x1, (int)y1, (int)x2, (int)y2, (int)x3, (int)y3, triangleDenominator, normalVector1, normalVector2, normalVector3, objectColor1, objectColor2, objectColor3, (int)x, (int)y - 1, options, textureWrapper)); } } // update x AET.ForEach(v => v.x += v.reciprocalM); } }
private static Color GetPreciseColorForPixel(int x, int y, FillOptions options, BmpPixelSnoop textureWrapper) { Vector N = options.NormalVectorOption == NormalVectorOpt.FromTexture ? getNormalVectorFromTexture(x, y, options, textureWrapper) : DEFAULT_OPTIONS.defaultNormalVector; Vector V = new Vector(0, 0, 1); var LightPoint = options.LightPoint; var L = (options.LightVectorOption == LightVectorOpt.FromPointOnSpiral && LightPoint != null) ? new Vector(LightPoint.X - x, (-1) * (LightPoint.Y - y), LightPoint.Z - 0).GetNormalised() : DEFAULT_OPTIONS.defaultLightVector; Vector R = 2 * Vector.DotProduct(N, L) * N - L; Color Il = options.LightColor; Color Io = (options.ObjectColorOption == ObjectColorOpt.Constant || options.Texture == null) ? (Color)options.ObjectColor : textureWrapper.GetPixel(x - (int)(options.GridLeft), y - (int)(options.GridTop)); double kd = options.LambertModelFactor; double ks = options.ReflectionFactor; int m = options.ReflectionLevel; return(Color.FromArgb(calculatePart(Il.R, Io.R, kd, ks, N, L, V, R, m), calculatePart(Il.G, Io.G, kd, ks, N, L, V, R, m), calculatePart(Il.B, Io.B, kd, ks, N, L, V, R, m))); }
private void ProcessBitmap() { int usedColors = 0; int totalColors = 0; if (texinfo is PvrTextureInfo) { radioButtonRGB5A3.Enabled = radioButtonIntensity8A.Enabled = false; } using (var snoop_u = new BmpPixelSnoop(new Bitmap(bitmap))) { for (int p = 0; p < bitmap.Palette.Entries.Length; p++) { totalColors += 1; bool match = false; for (int h = 0; h < bitmap.Height; h++) { for (int w = 0; w < bitmap.Width; w++) { if (snoop_u.GetPixel(w, h) == bitmap.Palette.Entries[p]) { match = true; } } } if (match) { usedColors += 1; } } } if (usedColors <= 16) { radioButtonIndex4.Checked = true; radioButtonIndex4.Enabled = true; } else if (usedColors <= 256) { radioButtonIndex8.Checked = true; radioButtonIndex4.Enabled = false; } else { radioButtonIndex4.Enabled = radioButtonIndex8.Enabled = false; radioButtonNonIndexed.Checked = true; } int tlevel = TextureFunctions.GetAlphaLevelFromBitmap(bitmap); string transparency = ""; switch (tlevel) { case 0: radioButtonRGB565.Checked = true; transparency = "no transparency"; break; case 1: transparency = "1-bit transparency"; if (SACompatible || !gamecube) { radioButtonARGB1555.Checked = true; } else { radioButtonRGB5A3.Checked = true; } break; case 2: transparency = "partial transparency"; if (SACompatible || !gamecube) { radioButtonARGB4444.Checked = true; } else { radioButtonRGB5A3.Checked = true; } break; } labelPaletteInfo.Text = "Palette: " + totalColors.ToString() + " colors (" + usedColors.ToString() + " colors used) , " + transparency; groupBoxMask.Enabled = groupBoxPalette.Enabled = buttonAuto.Enabled = buttonOK.Enabled = true; if (!gamecube) { radioButtonIntensity8A.Enabled = radioButtonRGB5A3.Enabled = false; } else { radioButtonIntensity8A.Enabled = radioButtonRGB5A3.Enabled = true; } }
/// <summary> /// Test how fast GetPixel() works compared to Bitmap.GetPixel() /// </summary> /// <param name="bmp">The bitmap to test with</param> static void TestGetPixelSpeed(Bitmap bmp) { Console.WriteLine("Testing GetPixel() Speed"); // Deep copy the bitmap var bmpClone = bmp.Clone() as Bitmap; // Calculate a simple sum over all of the pixels // in the original bitmap. long sum = 0; var stopwatch = new Stopwatch(); stopwatch.Start(); for (int j = 0; j != bmpClone.Height; j++) { for (int i = 0; i != bmpClone.Width; i++) { var col = bmpClone.GetPixel(i, j); sum += col.R + col.G + col.B; } } var time = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); stopwatch.Start(); long snoopSum = 0; // Calculate a simple sum over all of the pixels // in the snooped bitmap. using (var snoop = new BmpPixelSnoop(bmpClone)) { for (int j = 0; j != snoop.Height; j++) { for (int i = 0; i != snoop.Width; i++) { var col = snoop.GetPixel(i, j); snoopSum += col.R + col.G + col.B; } } } var snoopTime = stopwatch.ElapsedMilliseconds; // Just make sure our sums match if (sum != snoopSum) { throw new Exception("Pixel sums don't match!"); } Console.WriteLine(string.Format("Bitmap.GetPixel() took {0}ms, BmpPixelSnoop.GetPixel() took {1}ms", time, snoopTime)); }
public override Bitmap GenerateImage(int width, int height, int level) { double A = d_m[0, 0], B = d_m[1, 0], C = d_m[2, 0], D = d_m[3, 0], E = d_m[0, 1], F = d_m[1, 1], G = d_m[1, 2], H = d_m[1, 3], I = d_m[2, 0], J = d_m[2, 1], K = d_m[2, 2], L = d_m[2, 3], M = d_m[3, 0], N = d_m[3, 1], P = d_m[3, 2], Q = d_m[3, 3]; double a = K; width = (int)((double)width / (level * level)); height = (int)((double)height / (level * level)); Bitmap resultImage = new Bitmap(width, height); BmpPixelSnoop snoop = new BmpPixelSnoop(resultImage); { Color lastColor; int x_max = width % 2 == 0 ? width / 2 : width / 2 + 1; int y_max = height % 2 == 0 ? height / 2 : height / 2 + 1; for (int x_r = -width / 2; x_r < x_max; x_r++) { int x = x_r * level * level; for (int y_r = -height / 2; y_r < y_max; y_r++) { int y = y_r * level * level; double b = x * I + y * J + x * C + y * G + P + L; double c = x * x * A + x * y * E + x * M + x * y * B + y * y * F + y * N + x * D + y * H + Q; double delta = b * b - 4 * a * c; if (delta < 0) { lastColor = Color.DarkGray; } else { double z; if (delta == 0) { z = -b / 2 * a; } else { double z1 = (-b - Math.Sqrt(delta)) / (2 * a); double z2 = (-b + Math.Sqrt(delta)) / (2 * a); if (observator_position[2] - z1 < observator_position[2] - z2) { z = z1; } else { z = z2; } } Vector <double> normal = Vector <double> .Build.DenseOfArray( new double[] { 2 * x * A + y * E + z * I + M + y * B + z * C + D, x *E + x * B + 2 * y * F + z * J + N + z * G + H, x *I + y * J + x * C + y * G + 2 * z * K + P + L }).Normalize(2); Vector <double> to_observer = (observator_position - Vector <double> .Build.DenseOfArray(new double[] { x, y, z })).Normalize(2); double color = to_observer.DotProduct(normal); color = Math.Pow(color, m_col); if (color < 0) { color = 0; } lastColor = Color.FromArgb((byte)(Color.Yellow.R * color), (byte)(Color.Yellow.G * color), (byte)(Color.Yellow.B * color)); } snoop.SetPixel(x_r + width / 2, y_r + height / 2, lastColor); } } } return(resultImage); }