/// <summary> /// CDF-based sampling. /// </summary> /// <param name="random">[0,1] uniform random value.</param> /// <param name="rnd">Optional random generator instance. If provided, internal randomization is possible.</param> public virtual void GetSample(out double x, out double y, double random, RandomJames rnd = null) { if (cdf == null) { CollectCdf(); } // CDF-based importance sampling: int ia = 0; int ib = cdfRes - 1; double a = 0.0; double b = 1.0; do { int ip = (ia + ib) >> 1; double p = cdf[ip]; if (p < random) { ia = ip; a = p; } else { ib = ip; b = p; } }while (ia + 1 < ib); int ix = ia / resolution; int iy = ia % resolution; x = (ix + (rnd == null ? 0.5 : rnd.UniformNumber())) * pixel; y = (iy + (rnd == null ? 0.5 : rnd.UniformNumber())) * pixel; }
/// <summary> /// Renders the single pixel of an image. /// </summary> /// <param name="x">Horizontal coordinate.</param> /// <param name="y">Vertical coordinate.</param> /// <param name="color">Computed pixel color.</param> /// <param name="rnd">Shared random generator.</param> public override void RenderPixel(int x, int y, double[] color, RandomJames rnd) { Debug.Assert(color != null); Debug.Assert(rnd != null); int bands = color.Length; int b; Array.Clear(color, 0, bands); double[] tmp = new double[bands]; int i, j, ord; double step = 1.0 / superXY; double amplitude = Jittering * step; double origin = 0.5 * (step - amplitude); double x0, y0; for (j = ord = 0, y0 = y + origin; j++ < superXY; y0 += step) { for (i = 0, x0 = x + origin; i++ < superXY; x0 += step) { ImageFunction.GetSample(x0 + amplitude * rnd.UniformNumber(), y0 + amplitude * rnd.UniformNumber(), ord++, Supersampling, rnd, tmp); for (b = 0; b < bands; b++) { color[b] += tmp[b]; } } } double mul = step / superXY; if (Gamma > 0.001) { // gamma-encoding and clamping double g = 1.0 / Gamma; for (b = 0; b < bands; b++) { color[b] = Arith.Clamp(Math.Pow(color[b] * mul, g), 0.0, 1.0); } } else // no gamma, no clamping (for HDRI) { for (b = 0; b < bands; b++) { color[b] *= mul; } } }
/// <summary> /// Allocate large enough colormap.. /// </summary> public static void AssertColors(int num) { int i; if (debugColors == null || debugColors.Count < num) { debugColors = new List <Color>(num); RandomJames rnd = new RandomJames(); for (i = 0; i < num; i++) { int R = rnd.RandomInteger(0, 255); int G = rnd.RandomInteger(0, 255); int B = rnd.RandomInteger(0, 255); if (R >= 128 && G >= 128 && B >= 128) { if (rnd.UniformNumber() > 0.5) { R -= 128; } else { G -= 128; } } debugColors.Add(Color.FromArgb(R, G, B)); } } }
/// <summary> /// CDF-based sampling. /// </summary> /// <param name="x">Output horizontal coordinate from the [0.0,width) range.</param> /// <param name="y">Output vertical coordinate from the [0.0,height) range.</param> /// <param name="random">[0,1] uniform random value.</param> /// <param name="rnd">Optional random generator instance. If provided, internal randomization is possible.</param> public void GetSample(out double x, out double y, double random, RandomJames rnd = null) { if (cdf == null) { PrepareCdf(); } // CDF-based importance sampling: int ia = 0; int ib = width * height; double a = 0.0; double b = 1.0; do { int ip = (ia + ib) >> 1; double p = cdf[ip]; if (p < random) { ia = ip; a = p; } else { ib = ip; b = p; } }while (ia + 1 < ib); y = ia / width; x = ia % width; if (rnd != null) { x += rnd.UniformNumber(); y += rnd.UniformNumber(); } else { x += 0.5; y += 0.5; } }
public void generateSample(int r, int t) { if (t > 1) { if (r == rank && t == total) { return; } int uCell, vCell; if (t != total || r < rank) // [re-]initialization { total = t; uCell = rnd.PermutationFirst(total, ref permU); vCell = rnd.PermutationFirst(total, ref permV); } else { uCell = Math.Max(rnd.PermutationNext(ref permU), 0); vCell = Math.Max(rnd.PermutationNext(ref permV), 0); } rank = r; // point sample will be placed into [ uCell, vCell ] cell: u = (uCell + rnd.UniformNumber()) / total; v = (vCell + rnd.UniformNumber()) / total; } else { u = rnd.UniformNumber(); v = rnd.UniformNumber(); } // TODO: do something like: sample = source.position + u * source.width + v * source.height; }
int ActivateParticles(int nMax) { int nCount = Math.Min(nMax, particles.Count - activeParticles); if (nCount < 1) { return(0); } TotalSpawned += nCount; int nCountToDo = nCount; double fJitterRange = 0.1 / nCountToDo; foreach (var par in particles) { if (nCountToDo <= 0) { break; } else if (!par.active) { par.active = true; par.x = xMin + 0.0001; //par.y = yMin + 0.1 * rnd.UniformNumber() + 0.45; par.y = 0.45 + fJitterRange * (rnd.UniformNumber() + nCountToDo - 1.0); par.fx = 0.0; par.fy = 0.0; par.m = ParticleMass; par.vx = 0.0; par.vy = 0.0; nCountToDo--; } } activeParticles += nCount; return(nCount); }
/// <summary> /// Converts the given image into B/W (1bpp) output suitable for high-resolution printer. /// </summary> /// <param name="input">Input image.</param> /// <param name="output">Output (1bpp) image.</param> /// <param name="oWidth">Default output image width in pixels.</param> /// <param name="oHeight">Default output image height in pixels.</param> /// <param name="param">Set of optional text parameters.</param> /// <returns>Number of dots printed.</returns> public static long TransformImage(Bitmap input, out Bitmap output, int oWidth, int oHeight, string param) { // !!!{{ TODO: write your own image dithering code here int iWidth = input.Width; int iHeight = input.Height; long dots = 0L; // custom parameters from the text-field: double randomness = 0.0; double dot = 0.0; double gamma = 0.0; bool sampling = false; Dictionary <string, string> p = Util.ParseKeyValueList(param); if (p.Count > 0) { double scale = 0.0; // scale=<float-number> if (Util.TryParse(p, "scale", ref scale) && scale > 0.01) { oWidth = (int)(iWidth * scale); oHeight = (int)(iHeight * scale); } // rnd=<float-number> if (Util.TryParse(p, "rnd", ref randomness)) { randomness = Arith.Clamp(randomness, 0.0, 1.0); } // dot=<float-number> if (Util.TryParse(p, "dot", ref dot)) { dot = Math.Max(dot, 0.0); } // gamma=<float-number> if (Util.TryParse(p, "gamma", ref gamma)) { gamma = Math.Max(gamma, 0.0); } // sampling=<bool> Util.TryParse(p, "sampling", ref sampling); } // create output 1bpp Bitmap output = new Bitmap(oWidth, oHeight, PixelFormat.Format1bppIndexed); float dx = (iWidth - 1.0f) / (oWidth - 1.0f); float dy = (iHeight - 1.0f) / (oHeight - 1.0f); // set the B/W palette (0 .. black, 1 .. white): ColorPalette pal = output.Palette; pal.Entries[0] = Color.Black; pal.Entries[1] = Color.White; output.Palette = pal; int x, y; float fx, fy; RandomJames rnd = new RandomJames(); // convert pixel data (fast memory-mapped code): PixelFormat iFormat = input.PixelFormat; if (!PixelFormat.Format24bppRgb.Equals(iFormat) && !PixelFormat.Format32bppArgb.Equals(iFormat) && !PixelFormat.Format32bppPArgb.Equals(iFormat) && !PixelFormat.Format32bppRgb.Equals(iFormat)) { iFormat = PixelFormat.Format24bppRgb; } BitmapData dataOut = output.LockBits(new Rectangle(0, 0, oWidth, oHeight), ImageLockMode.WriteOnly, output.PixelFormat); unsafe { byte *optr; // A. placing reasonable number of random dots on the paper if (sampling) { dot = Math.Max(dot, 1.0); // clear output image: optr = (byte *)dataOut.Scan0; for (x = 0; x++ < oHeight * dataOut.Stride;) { *optr++ = 255; } // create grayscale image able to sample points from itself: FloatImage fi = new FloatImage(input); fi = fi.GrayImage(true, gamma); fi.PrepareCdf(); // sample 'dots' random dots: dots = (long)(1.2 * oWidth * oHeight / (dot * dot)); double xx, yy; for (long i = 0; i++ < dots;) { fi.GetSample(out xx, out yy, rnd.UniformNumber(), rnd); xx = oWidth * (xx / iWidth); yy = oHeight * (yy / iHeight); Dot1bpp((int)xx, (int)yy, dot, dataOut); } } else { BitmapData dataIn = input.LockBits(new Rectangle(0, 0, iWidth, iHeight), ImageLockMode.ReadOnly, iFormat); // B. random screen using dots bigger than 1px if (dot > 0.0) { // clear output image: optr = (byte *)dataOut.Scan0; for (x = 0; x++ < oHeight * dataOut.Stride;) { *optr++ = 255; } int dI = Image.GetPixelFormatSize(iFormat) / 8; for (y = 0, fy = 0.0f; y < oHeight; y++, fy += dy) { if (!Form1.cont) { break; } for (x = 0, fx = 0.0f; x < oWidth; x++, fx += dx) { float gray = GetGray(fx, fy, dataIn, dI); if (gamma > 0.0) { gray = (float)Math.Pow(gray, gamma); } float threshold = (float)(0.5 - randomness * (rnd.UniformNumber() - 0.5)); if (gray < threshold) { dots++; Dot1bpp(x, y, dot, dataOut); } } } } else // C. random screen using individual pixels { int buffer; int dI = Image.GetPixelFormatSize(iFormat) / 8; for (y = 0, fy = 0.0f; y < oHeight; y++, fy += dy) { if (!Form1.cont) { break; } optr = (byte *)dataOut.Scan0 + y * dataOut.Stride; buffer = 0; for (x = 0, fx = 0.0f; x < oWidth; fx += dx) { float gray = GetGray(fx, fy, dataIn, dI); if (gamma > 0.0) { gray = (float)Math.Pow(gray, gamma); } float threshold = (float)(0.5 - randomness * (rnd.UniformNumber() - 0.5)); buffer += buffer; if (gray >= threshold) { buffer++; } else { dots++; } if ((++x & 7) == 0) { *optr++ = (byte)buffer; buffer = 0; } } // finish the last byte of the scanline: if ((x & 7) != 0) { while ((x++ & 7) != 0) { buffer += buffer; } *optr = (byte)buffer; } } } input.UnlockBits(dataIn); } output.UnlockBits(dataOut); } return(dots); // !!!}} }