如何将Geometry保存为图像?

时间:2012-01-31 13:21:42

标签: c# wpf image geometry geometrydrawing

如何将Geometry保存为图像?

例如,我有List<Geometry>

我希望它如下:

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);
}

更新

我几个小时前写的代码:

    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;
    }

但我得Img2而不是Img1

更新2:  我改变了这个:

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

为:

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

并补充说:

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

一切正常。

4 个答案:

答案 0 :(得分:2)

对于想要以固定大小居中呈现几何体的任何人,这是执行此操作的代码:

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);
}

答案 1 :(得分: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);

根据您对上述部分的评论,看起来您正在尝试为字体创建一个字形表并将其保存到图像文件中。以下是您完成此任务的方法:

// 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 :(得分:1)

我用这个:

        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();
        }
    }

答案 3 :(得分:-1)

查看我的其他answer。通常,您应该使用RenderTargetBitmap类。