예제 #1
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);
        }
예제 #2
0
파일: Program.cs 프로젝트: n-j-m/pixelate
        static void Main(string[] args)
        {
            Console.WriteLine("RGB image generator\n");

            if (!parseArgs(args))
            {
                printArgsHelp();
                Console.WriteLine("Press ENTER to exit.");
                Console.ReadLine();
                return;
            }

            System.Diagnostics.Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal;

            DateTime start = DateTime.Now;

            Console.WriteLine("Running the precalculations and eating up your memory.");

            // create every color once, and randomize their order
            List<RGB> colors = new List<RGB>(Width * Height);
            for (int r = 0; r < NumColors; r++)
                for (int g = 0; g < NumColors; g++)
                    for (int b = 0; b < NumColors; b++)
                        colors.Add(new RGB
                        {
                            R = (byte)(r * 255 / (NumColors - 1)),
                            G = (byte)(g * 255 / (NumColors - 1)),
                            B = (byte)(b * 255 / (NumColors - 1))
                        });

            colors.Sort(Sorter);
            Debug.Assert(colors.Count == Width * Height);

            Pixel[] img = new Pixel[Width * Height];
            ImageData imageData = new ImageData
            {
                Image = img,
                Height = Height,
                Width = Width
            };

            HashSet<int> weights = new HashSet<int>();
            Debug.Assert(NeighX.Length == NeighY.Length);
            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    int weight;
                    do
                    {
                        weight = RndGen.Next();
                    } while (!weights.Add(weight));

                    imageData.Image[y * Width + x] = new Pixel
                    {
                        X = x,
                        Y = y,

                        Empty = true,
                        QueueIndex = -1,
                        Weight = weight
                    };
                }
            }

            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    imageData.Image[y * Width + x].Neighbors = Enumerable.Range(0, NeighX.Length).Select(n =>
                    {
                        int y2 = y + NeighY[n];
                        if (y2 < 0 || y2 == Height)
                            return null;

                        int x2 = x + NeighX[n];
                        if (x2 < 0 || x2 == Width)
                            return null;

                        return img[y2 * Width + x2];
                    }).Where(p => p != null).ToArray();
                }
            }

            Dictionary<long, int> checkpoints = Enumerable.Range(1, NumFrames).ToDictionary(i => (long)i * colors.Count / NumFrames - 1, i => i - 1);

            Thread pngThread = null;

            // loop through all colors that we want to place
            for (int i = 0, l = colors.Count; i < l; i++)
            {
                // give progress report
                if (i % 1024 == 0)
                {
                    Algorithm.Queue.Compress();
                    Console.WriteLine("{0:P}, queue is size {1}", (double)i / Width / Height, Algorithm.Queue.Count);
                }

                // run the algorithm
                Algorithm.Place(colors[i], StartX, StartY, ref imageData);

                // save a checkpoint, if needed
                int chkidx;
                if (checkpoints.TryGetValue(i, out chkidx))
                {
                    // create an image
                    Bitmap image = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
                    BitmapData idata = image.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);

                    byte[] ibytes = new byte[idata.Stride * idata.Height];
                    int stride = idata.Stride;

                    for (int y = 0; y < Height; y++)
                    {
                        for (int x = 0; x < Width; x++)
                        {
                            RGB color = img[y * Width + x].Color;
                            ibytes[y * stride + x * 3 + 2] = color.R;
                            ibytes[y * stride + x * 3 + 1] = color.G;
                            ibytes[y * stride + x * 3 + 0] = color.B;
                        }
                    }

                    Marshal.Copy(ibytes, 0, idata.Scan0, ibytes.Length);
                    image.UnlockBits(idata);

                    // use one thread for png compression
                    if (pngThread != null)
                        pngThread.Join();
                    pngThread = new Thread(new ThreadStart(delegate
                    {
                        image.Save(string.Format("result{0:D5}.png", chkidx), ImageFormat.Png);
                        image.Dispose();
                    }));
                    pngThread.Start();
                }
            }

            Debug.Assert(Algorithm.Queue.Count == 0);

            // wait for final image
            pngThread.Join();

            Bitmap image2 = (Bitmap)Bitmap.FromFile(string.Format("result{0:D5}.png", NumFrames - 1));

            HashSet<RGB> ch = new HashSet<RGB>();
            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    Color pix = image2.GetPixel(x, y);
                    if (!ch.Add(new RGB
                    {
                        R = pix.R,
                        G = pix.G,
                        B = pix.B
                    }))
                    {
                        Console.WriteLine("Color {0}/{1}/{2} is added more that once!!!", pix.R, pix.G, pix.B);
                    }
                }
            }

            image2.Dispose();

            Console.WriteLine("DONE!! It took this long: {0}", DateTime.Now.Subtract(start));
            Console.WriteLine("pres ENTER to exit");
            Console.ReadLine();
        }