Exemple #1
0
        public WTStipple(Image source, WangTileSet tileSet, int tonalRange, Bitmap dest)
        {
            // Convert source image to grayscale

            Bitmap   bmp = new Bitmap(source.Width, source.Height);
            Graphics g   = Graphics.FromImage(bmp);

            g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height));
            float[,] grayscale = ToDensity(bmp);
            this.tileSet       = tileSet;

            // Subdivide image recusively as long as we need more density on each leave's tile
            // to account for the underlying sampled region on the image
            ImageTreeNode root = new ImageTreeNode();
            Random        r    = new Random(tileSet.tiles.Count);

            root.tile = r.Next(tileSet.tiles.Count);
            Rectangle rect    = new Rectangle(0, 0, bmp.Width, bmp.Height);
            int       minSize = 8;

            Graphics g2 = Graphics.FromImage(dest);

            g2.Clear(Color.White);
            Refine_r(root, rect, grayscale, minSize, 0, 5, tonalRange, dest);
        }
Exemple #2
0
        public WTStipple(Image source, WangTileSet tileSet, int tonalRange, Bitmap dest )
        {
            // Convert source image to grayscale

            Bitmap bmp = new Bitmap(source.Width, source.Height);
            Graphics g = Graphics.FromImage(bmp);
            g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height));
            float[,] grayscale = ToDensity(bmp);
            this.tileSet = tileSet;

            // Subdivide image recusively as long as we need more density on each leave's tile
            // to account for the underlying sampled region on the image
            ImageTreeNode root = new ImageTreeNode();
            Random r = new Random(tileSet.tiles.Count);
            root.tile = r.Next(tileSet.tiles.Count);
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            int minSize = 8;

            Graphics g2 = Graphics.FromImage(dest);
            g2.Clear(Color.White);
            Refine_r(root, rect, grayscale, minSize, 0, 5, tonalRange, dest );
        }
Exemple #3
0
        private void Refine_r(ImageTreeNode node, Rectangle rect, float[,] density, int minSize, int depth, int maxDepth, int toneScale, Bitmap dest)
        {
            Debug.Assert(node.tile != -1);
            List<PoissonDist.PoissonSample> distribution = tileSet.tiles[node.tile].distribution;
            float tileMaxDensity = (float)distribution.Count;
            float requiredDensity = AreaDensity(density, rect);

            // Cover the area with the current tile

            float tileAvgDensity = Math.Min(1.0f, tileMaxDensity / (rect.Width * rect.Height));

            for (int i = 0; i < distribution.Count; i++)
            {
                int stippleX = rect.Left + (int)(rect.Width * distribution[i].x);
                int stippleY = rect.Top + (int)(rect.Height * distribution[i].y);
                float r = 1;//Math.Max(1, (distribution[i].radius * rect.Width));
                float area = (float)(r*r * Math.PI);
                float diskDensity = DiskDensity(density, new Point(stippleX, stippleY), (int)r);
                float diskAvgDensity = diskDensity / area;

                float factor = (float)(0.1f / Math.Pow(1, -2) * Math.Pow(4, 2.0f * depth) / toneScale);
                if (diskAvgDensity < (float)i * factor) continue;
                dest.SetPixel(stippleX, stippleY, Color.Black);
            }

            // Check whether we need to keep subdividing

            if (rect.Width <= minSize || rect.Height <= minSize || depth == maxDepth) return;

            if (Math.Pow(0.1, -2) / Math.Pow(4, 2 * depth) * toneScale - tileMaxDensity >  16 * tileMaxDensity )
            {
                // we need to subdivide
                int[,] subd;
                int splitsPerDimension;
                tileSet.GetSubdivisions(node.tile, out subd, out splitsPerDimension);
                node.children = new ImageTreeNode[splitsPerDimension, splitsPerDimension];
                Size childRectSize = new Size((int)Math.Floor((float)rect.Width / splitsPerDimension),
                                              (int)Math.Floor((float)rect.Height / splitsPerDimension));
                for (int j = 0; j < splitsPerDimension; j++)
                {
                    for (int i = 0; i < splitsPerDimension; i++)
                    {
                        node.children[i, j] = new ImageTreeNode();
                        node.children[i, j].tile = subd[i, j];
                        Rectangle childRect = new Rectangle(rect.X + i * childRectSize.Width,
                                                            rect.Y + j * childRectSize.Height,
                                                            childRectSize.Width,
                                                            childRectSize.Height);
                        if (i == splitsPerDimension - 1) // adjust borders
                            childRect.Width = rect.Right - childRect.X;
                        if (j == splitsPerDimension - 1) // adjust borders
                            childRect.Height = rect.Bottom - childRect.Y;
                        Refine_r(node.children[i, j], childRect, density, minSize, depth + 1, maxDepth, toneScale, dest);
                    }
                }
            }
        }
Exemple #4
0
        private void Refine_r(ImageTreeNode node, Rectangle rect, float[,] density, int minSize, int depth, int maxDepth, int toneScale, Bitmap dest)
        {
            Debug.Assert(node.tile != -1);
            List <PoissonDist.PoissonSample> distribution = tileSet.tiles[node.tile].distribution;
            float tileMaxDensity  = (float)distribution.Count;
            float requiredDensity = AreaDensity(density, rect);

            // Cover the area with the current tile

            float tileAvgDensity = Math.Min(1.0f, tileMaxDensity / (rect.Width * rect.Height));

            for (int i = 0; i < distribution.Count; i++)
            {
                int   stippleX       = rect.Left + (int)(rect.Width * distribution[i].x);
                int   stippleY       = rect.Top + (int)(rect.Height * distribution[i].y);
                float r              = 1;//Math.Max(1, (distribution[i].radius * rect.Width));
                float area           = (float)(r * r * Math.PI);
                float diskDensity    = DiskDensity(density, new Point(stippleX, stippleY), (int)r);
                float diskAvgDensity = diskDensity / area;

                float factor = (float)(0.1f / Math.Pow(1, -2) * Math.Pow(4, 2.0f * depth) / toneScale);
                if (diskAvgDensity < (float)i * factor)
                {
                    continue;
                }
                dest.SetPixel(stippleX, stippleY, Color.Black);
            }

            // Check whether we need to keep subdividing

            if (rect.Width <= minSize || rect.Height <= minSize || depth == maxDepth)
            {
                return;
            }

            if (Math.Pow(0.1, -2) / Math.Pow(4, 2 * depth) * toneScale - tileMaxDensity > 16 * tileMaxDensity)
            {
                // we need to subdivide
                int[,] subd;
                int splitsPerDimension;
                tileSet.GetSubdivisions(node.tile, out subd, out splitsPerDimension);
                node.children = new ImageTreeNode[splitsPerDimension, splitsPerDimension];
                Size childRectSize = new Size((int)Math.Floor((float)rect.Width / splitsPerDimension),
                                              (int)Math.Floor((float)rect.Height / splitsPerDimension));
                for (int j = 0; j < splitsPerDimension; j++)
                {
                    for (int i = 0; i < splitsPerDimension; i++)
                    {
                        node.children[i, j]      = new ImageTreeNode();
                        node.children[i, j].tile = subd[i, j];
                        Rectangle childRect = new Rectangle(rect.X + i * childRectSize.Width,
                                                            rect.Y + j * childRectSize.Height,
                                                            childRectSize.Width,
                                                            childRectSize.Height);
                        if (i == splitsPerDimension - 1) // adjust borders
                        {
                            childRect.Width = rect.Right - childRect.X;
                        }
                        if (j == splitsPerDimension - 1) // adjust borders
                        {
                            childRect.Height = rect.Bottom - childRect.Y;
                        }
                        Refine_r(node.children[i, j], childRect, density, minSize, depth + 1, maxDepth, toneScale, dest);
                    }
                }
            }
        }