【问题标题】:How to save Geometry as image?如何将几何保存为图像?
【发布时间】:2012-01-31 13:21:42
【问题描述】:

如何将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,而不是。

更新 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;

一切正常。

【问题讨论】:

    标签: c# wpf image geometry geometrydrawing


    【解决方案1】:

    对于任何想要以固定大小为中心渲染几何图形的人,这是执行此操作的代码:

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

    【讨论】:

      【解决方案2】:
      // 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);
      

      根据您对上述部分的 cmets,您似乎正在尝试为字体创建字形表并将其保存到图像文件中。以下是您完成此操作的方法:

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

      【讨论】:

      • 我是几个小时前刚做的。 Code 但不是Img1,而是Img2
      • 字形很棘手,因为几何图形是从左下角开始绘制的。如果在点 (0,0) 处画一个,则字符的顶部在 (0, -glyphHeight),所以它都在屏幕外。
      【解决方案3】:

      我用这个:

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

      【讨论】:

        猜你喜欢
        • 2012-01-05
        • 2022-01-24
        • 2014-12-11
        • 1970-01-01
        • 2014-02-08
        • 2022-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多