Exemple #1
0
        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;
        }
Exemple #2
0
        /// <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;
                }
            }
        }
Exemple #7
0
 /// <summary>
 /// Handles implementation specific pixel placement.
 /// </summary>
 protected abstract Pixel placeImpl(RGB color);