How to save Geometry as image?

北城以北 提交于 2019-12-05 01:47:36

问题


How to save Geometry as image?

For example i have List<Geometry>.

I want it to be as follows:

for (int i = 0; i < GeometryList.Count; i++)
{
       Pen TestPen = new Pen(Brushes.Black, 1);
       GeometryDrawing TestDrawing = new GeometryDrawing(Brushes.Black, TestPen, TestGeometry);

       Bitmap b = TestDrawing as Bitmap;

       b.Save(System.AppDomain.CurrentDomain.BaseDirectory + i + ".png", ImageFormat.Png);
}

Update:

The code I wrote a few hours ago:

    private void CreateFontMap(string PathTofont)
    {

        GlyphTypeface font = new GlyphTypeface(new Uri(PathTofont));


        List<ushort> fontNum = new List<ushort>();

        foreach (KeyValuePair<int, ushort> kvp in font.CharacterToGlyphMap)
        {
            fontNum.Add(kvp.Value);
        }

        if (fontNum.Count > 0)
        {
            int mapWidth = 50 * 20;
            int mapHeight = 50 * (getRowNum(fontNum.Count + 1) + 1);

            Bitmap b = new Bitmap(mapWidth, mapHeight);
            Graphics g = Graphics.FromImage(b);

            System.Windows.Media.Pen glyphPen = new System.Windows.Media.Pen(System.Windows.Media.Brushes.Red, 1);
            Geometry glyphGeometry;

            for (int i = 0; i < fontNum.Count; i++)
            {                    
                glyphGeometry = font.GetGlyphOutline(fontNum[i], 50, 1);

                RenderTargetBitmap bmp = new RenderTargetBitmap(50, 50, 96, 96, PixelFormats.Pbgra32);

                DrawingVisual viz = new DrawingVisual();
                DrawingContext dc = viz.RenderOpen();
                dc.DrawGeometry(System.Windows.Media.Brushes.Red, null, glyphGeometry);
                dc.Close();

                bmp.Render(viz);

                PngBitmapEncoder encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bmp));

                MemoryStream myStream = new MemoryStream();

                encoder.Save(myStream);

                int rowNum = (getRowNum(i));
                g.DrawImage(System.Drawing.Bitmap.FromStream(myStream), new PointF((i - rowNum * 20) * 50, rowNum * 50));
            }
            g.Dispose();
            b.Save(System.AppDomain.CurrentDomain.BaseDirectory + "map.png", ImageFormat.Png);
            b.Dispose();
        }
    }

    private int getRowNum(int p)
    {
        return p / 20;
    }

But instead of

, I get Img2.

Update 2: I changed this:

DrawingVisual viz = new DrawingVisual();
DrawingContext dc = viz.RenderOpen();
dc.DrawGeometry(System.Windows.Media.Brushes.Red, null, glyphGeometry);
dc.Close();

to:

DrawingVisual viz = new DrawingVisual();
DrawingContext dc = viz.RenderOpen();
dc.DrawImage(geometryImage, new Rect(0, 0, 50, 50));
dc.Close();

and added:

glyphDrawing = new GeometryDrawing(System.Windows.Media.Brushes.Black,  glyphPen, glyphGeometry);
DrawingImage geometryImage = new DrawingImage(glyphDrawing);
geometryImage.Freeze();
img1.Source = geometryImage;

And all working.


回答1:


// Create the bitmap we'll render to
RenderTargetBitmap bmp = 
            new RenderTargetBitmap(100, 100, // Size
                                                    96, 96, // DPI 
                                                    PixelFormats.Pbgra32);

// Create a list of random circle geometries
List<Geometry> geoList = new List<Geometry>();
Random rand = new Random();
for (int i=0; i<10; i++)
{
    double radius = rand.Next(5, 10);
    Point center = new Point(rand.Next(25, 75), rand.Next(25,75));
    geoList.Add(new EllipseGeometry(center, radius, radius));
}
// The light-weight visual element that will draw the geometries
DrawingVisual viz = new DrawingVisual();
using (DrawingContext dc = viz.RenderOpen())
{ // The DC lets us draw to the DrawingVisual directly
    foreach (var g in geoList)
        dc.DrawGeometry(Brushes.Red, null, g);
} // the DC is closed as it falls out of the using statement

// draw the visual on the bitmap
bmp.Render(viz);

// instantiate an encoder to save the file
PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
// add this bitmap to the encoders set of frames
pngEncoder.Frames.Add(BitmapFrame.Create(bmp));

// save the bitmap as an .png file
using (FileStream file = new FileStream("Spots.png", FileMode.Create))
    pngEncoder.Save(file);

Based on your comments to the section above, it looks like you're trying to create a table of glyphs for a font and save it out to an image file. Here's how you accomplish this:

// I'm generating the glyphs differently for testing.
// I tested with fontName="Arial"
Typeface face = new Typeface(fontName);
GlyphTypeface font;

if (!face.TryGetGlyphTypeface(out font))
    return; // bail if something goes wrong

int ColumnCount = 10;
int MaxDrawCount = 30; // use int.MaxValue to draw them all            
double fontSize = 50d;
// the height of each cell has to include over/underhanging glyphs
Size cellSize = new Size(fontSize, fontSize * font.Height);

var Glyphs = from glyphIndex in font.CharacterToGlyphMap.Values
                    select font.GetGlyphOutline(glyphIndex, fontSize, 1d);            

// now create the visual we'll draw them to
DrawingVisual viz = new DrawingVisual();
int drawCount = -1;
using (DrawingContext dc = viz.RenderOpen())
{
    foreach (var g in Glyphs)
    {
        drawCount++;
        if (drawCount >= MaxDrawCount)
            break; // don't draw more than you want
        if (g.IsEmpty()) continue; // don't draw the blank ones
        // center horizontally in the cell
        double xOffset = (drawCount % ColumnCount) * cellSize.Width + cellSize.Width / 2d - g.Bounds.Width / 2d;
        // place the character on the baseline of the cell
        double yOffset = (drawCount / ColumnCount) * cellSize.Height + fontSize * font.Baseline;
        dc.PushTransform(new TranslateTransform(xOffset, yOffset));
        dc.DrawGeometry(Brushes.Red, null, g);
        dc.Pop(); // get rid of the transform
    }
}

int RowCount = drawCount / ColumnCount;
if (drawCount % ColumnCount != 0) 
    RowCount++; // to include partial rows
int bitWidth = (int)Math.Ceiling(cellSize.Width * ColumnCount);
int bitHeight = (int)Math.Ceiling(cellSize.Height * RowCount);
RenderTargetBitmap bmp = new RenderTargetBitmap(
                                                bitWidth, bitHeight,
                                                96, 96,
                                                PixelFormats.Pbgra32);
bmp.Render(viz);

PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
using (FileStream file = new FileStream("FontTable.png", FileMode.Create))
    encoder.Save(file);



回答2:


For anyone who is wanting to render geometry centered in a fixed size, this is the code to do it:

const int TargetSize = 14;

private static void Save(Geometry geometry, string fileName)
{
    var rect = geometry.GetRenderBounds(new Pen(Brushes.Black, 0));

    var bigger = rect.Width > rect.Height ? rect.Width : rect.Height;
    var scale = TargetSize / bigger;

    Geometry scaledGeometry = Geometry.Combine(geometry, geometry, GeometryCombineMode.Intersect, new ScaleTransform(scale, scale));
    rect = scaledGeometry.GetRenderBounds(new Pen(Brushes.Black, 0));

    Geometry transformedGeometry = Geometry.Combine(scaledGeometry, scaledGeometry, GeometryCombineMode.Intersect, new TranslateTransform(((TargetSize - rect.Width) / 2) - rect.Left, ((TargetSize - rect.Height) / 2) - rect.Top));

    RenderTargetBitmap bmp = new RenderTargetBitmap(TargetSize, TargetSize, // Size
                                                    96, 96, // DPI 
                                                    PixelFormats.Pbgra32);

    DrawingVisual viz = new DrawingVisual();
    using (DrawingContext dc = viz.RenderOpen())
    {
        dc.DrawGeometry(Brushes.Black, null, transformedGeometry);
    }

    bmp.Render(viz);

    PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
    pngEncoder.Frames.Add(BitmapFrame.Create(bmp));

    using (FileStream file = new FileStream(fileName, FileMode.Create))
        pngEncoder.Save(file);
}



回答3:


I use this:

        private void GenerateFontMap(string PathTofont, int GlyphsPerRow, int WidthAndHeight)       

        {

        GlyphTypeface font = new GlyphTypeface(new Uri(PathTofont));

        List<ushort> fontNum = new List<ushort>();

        foreach (KeyValuePair<int, ushort> kvp in font.CharacterToGlyphMap)
        {
            fontNum.Add(kvp.Value);
        }

        if (fontNum.Count > 0)
        {
            int mapWidth = WidthAndHeight * GlyphsPerRow;
            int mapHeight = WidthAndHeight * ((fontNum.Count + 1) / GlyphsPerRow + 1);

            Bitmap b = new Bitmap(mapWidth, mapHeight);
            Graphics g = Graphics.FromImage(b);

            System.Windows.Media.Pen glyphPen = new System.Windows.Media.Pen(System.Windows.Media.Brushes.Black, 1);
            Geometry glyphGeometry;
            GeometryDrawing glyphDrawing;
            PngBitmapEncoder encoder;
            RenderTargetBitmap bmp;
            DrawingVisual viz;

            for (int i = 0; i < fontNum.Count; i++)
            {                    
                glyphGeometry = font.GetGlyphOutline(fontNum[i], WidthAndHeight, 1);
                glyphDrawing = new GeometryDrawing(System.Windows.Media.Brushes.Black, glyphPen, glyphGeometry);

                DrawingImage geometryImage = new DrawingImage(glyphDrawing);
                geometryImage.Freeze();

                viz = new DrawingVisual();
                DrawingContext dc = viz.RenderOpen();
                dc.DrawImage(geometryImage, new Rect(0, 0, geometryImage.Width, geometryImage.Height));
                dc.Close();

                bmp = new RenderTargetBitmap(WidthAndHeight, WidthAndHeight, 96, 96, PixelFormats.Pbgra32);

                bmp.Render(viz);

                encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bmp));

                MemoryStream myStream = new MemoryStream();
                encoder.Save(myStream);

                g.DrawImage(System.Drawing.Bitmap.FromStream(myStream), new PointF((i - (i / GlyphsPerRow) * GlyphsPerRow) * WidthAndHeight, i / GlyphsPerRow * WidthAndHeight));
            }
            g.Dispose();
            b.Save("map.png", ImageFormat.Png);
            b.Dispose();
        }
    }



回答4:


See my other answer. In common, you should use the RenderTargetBitmap class.



来源:https://stackoverflow.com/questions/9080231/how-to-save-geometry-as-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!