public override int Compare(RGB x, RGB y) { Color xColor = x.ToColor(); Color yColor = y.ToColor(); int compare = ((xColor.GetHue() + shift % 360).CompareTo((yColor.GetHue() + shift) % 360)); if (compare == 0) compare = xColor.GetBrightness().CompareTo(yColor.GetBrightness()); if (compare == 0) compare = base.Compare(x, y); return compare; }
/// <summary> /// Places the given color on the image /// </summary> public void Place(RGB color, int startX, int startY, ref ImageData imageData) { // find the next coordinates Pixel p; if (Queue.Count == 0) p = imageData.Image[startY * imageData.Width + startX]; else p = placeImpl(color); Debug.Assert(p.Empty); p.Empty = false; p.Color = color; // adjust the queue changeQueue(p); }
protected override Pixel placeImpl(RGB color) { // find the best pixel with parallel processing Pixel[] q = queue.Pixels; var best = Partitioner.Create(0, queue.UsedUntil, Math.Max(256, queue.UsedUntil / AlgorithmBase.threads)) .AsParallel().Min(range => { int bestdiff = int.MaxValue; Pixel bestpixel = null; for (int i = range.Item1; i < range.Item2; i++) { Pixel pixel = q[i]; if (pixel != null) { AvgInfo avg = queue.Data[pixel.QueueIndex]; int cr = (int)color.R; int cg = (int)color.G; int cb = (int)color.B; int rd = cr * cr * avg.NeighborCount + (avg.Rsq - 2 * cr * avg.R); int gd = cg * cg * avg.NeighborCount + (avg.Gsq - 2 * cg * avg.G); int bd = cb * cb * avg.NeighborCount + (avg.Bsq - 2 * cb * avg.B); int diff = rd + gd + bd; // we have to use the same comparison as PixelWithValue if (diff < bestdiff || (diff == bestdiff && pixel.Weight < bestpixel.Weight)) { bestdiff = diff; bestpixel = pixel; } } } return new PixelWithValue { Pixel = bestpixel , Value = bestdiff }; }).Pixel; // found the pixel, return it queue.Remove(best); return best; }
protected override Pixel placeImpl(RGB color) { // find the best with paralell processing var q = queue.Pixels; var best = Partitioner.Create(0, queue.UsedUntil, Math.Max(256, queue.UsedUntil / AlgorithmBase.threads)) .AsParallel().Min(range => { var bestdiff = int.MaxValue; Pixel bestpixel = null; for (var i = range.Item1; i < range.Item2; i++) { var qp = q[i]; if (qp != null) { var rd = (int)qp.Color.R - color.R; var gd = (int)qp.Color.G - color.G; var bd = (int)qp.Color.B - color.B; var diff = rd * rd + gd * gd + bd * bd; if (diff < bestdiff || (diff == bestdiff && qp.Weight < bestpixel.Weight)) { bestdiff = diff; bestpixel = qp; } } } return new PixelWithValue { Pixel = bestpixel, Value = bestdiff }; }).Pixel; // select a deterministically random, empty neighbor int shift = best.Weight % best.Neighbors.Length; for (int i = 0; i < best.Neighbors.Length; i++) { Pixel bestn = best.Neighbors[(i + shift) % best.Neighbors.Length]; if (bestn.Empty) return bestn; } throw new NotReachedException(); }
protected override Pixel placeImpl(RGB color) { // find the best pixel with parallel processing Pixel[] q = queue.Pixels; var best = Partitioner.Create(0, queue.UsedUntil, Math.Max(256, queue.UsedUntil / AlgorithmBase.threads)) .AsParallel().Min(range => { int bestdiff = int.MaxValue; Pixel bestpixel = null; for (int i = range.Item1; i < range.Item2; i++) { Pixel qp = q[i]; if (qp != null) { RGB avg = queue.Data[qp.QueueIndex]; int rd = (int)avg.R - color.R; int gd = (int)avg.G - color.G; int bd = (int)avg.B - color.B; int diff = rd * rd + gd * gd + bd * bd; // we have to use the same comparison as PixelWithValue if (diff < bestdiff || (diff == bestdiff && qp.Weight < bestpixel.Weight)) { bestdiff = diff; bestpixel = qp; } } } return new PixelWithValue { Pixel = bestpixel , Value = bestdiff }; }).Pixel; // found the pizel, return it queue.Remove(best); return best; }
protected override void changeQueue(Pixel pixel) { // recalculate the neighbors Pixel[] pixelNeighbors = pixel.Neighbors; for (int i = 0, l = pixelNeighbors.Length; i < l; i++) { Pixel nPixel = pixelNeighbors[i]; if (nPixel.Empty) { int r = 0, g = 0, b = 0, n = 0; Pixel[] nPixelNeighbors = nPixel.Neighbors; for (int j = 0, jl = nPixelNeighbors.Length; j < jl; j++) { Pixel nNeighborPixel = nPixelNeighbors[j]; if (!nNeighborPixel.Empty) { r += nNeighborPixel.Color.R; g += nNeighborPixel.Color.G; b += nNeighborPixel.Color.B; n++; } } RGB avg = new RGB { R = (byte)(r / n) , G = (byte)(g / n) , B = (byte)(b / n) }; if (nPixel.QueueIndex == -1) queue.Add(nPixel); queue.Data[nPixel.QueueIndex] = avg; } } }
/// <summary> /// Handles implementation specific pixel placement. /// </summary> protected abstract Pixel placeImpl(RGB color);