Search code examples
c#metafile

How do I parse a PolyPolygon16 metafile record out of a byte[] c#


I need a little help in defining the following Windows GDI type in C#. I have the data in the form of a byte[] in C#, and I need to somehow marshal or cast it as the following in C#.

This is the type:

http://java.freehep.org/vectorgraphics/apidocs/org/freehep/graphicsio/emf/gdi/PolyPolygon16.html

http://msdn.microsoft.com/en-us/library/cc230665%28PROT.10%29.aspx

Edit: I have been able to get this far, close but not quite:

                    UInt32 rectLeft = BitConverter.ToUInt32(dataArray, 0);
                UInt32 rectTop = BitConverter.ToUInt32(dataArray, 4);
                UInt32 rectRight = BitConverter.ToUInt32(dataArray, 8);
                UInt32 rectBottom = BitConverter.ToUInt32(dataArray, 12);
                UInt32 rectNumberOfPolygons = BitConverter.ToUInt32(dataArray, 16);
                // Number of points in each polygon
                int l_nIndex = 20;
                UInt32[] lengths = new UInt32[rectNumberOfPolygons];
                for (int i = 0; i < lengths.Length; i++)
                {
                    lengths[i] = BitConverter.ToUInt32(dataArray, l_nIndex);
                    l_nIndex += 4;
                }
                // Extract points
                foreach (int l_nPolygonLength in lengths)
                {
                    List<Point> l_lstPoints = new List<Point>();
                    for (int i = 0; i < l_nIndex + l_nPolygonLength; i++)
                    {
                        UInt16 pointX = BitConverter.ToUInt16(dataArray, l_nIndex);
                        UInt16 pointY = BitConverter.ToUInt16(dataArray, l_nIndex + 2);
                        l_lstPoints.Add(new Point((int)pointX, (int)pointY));
                        l_nIndex += 4;
                    }
                }

Solution

  • RectL Object:

    public static Rectangle ReadRectangle32(this BinaryReader reader)
    {
        // Left (4 bytes)
        int left = reader.ReadInt32();
    
        // Top (4 bytes)
        int top = reader.ReadInt32();
    
        // Right (4 bytes)
        int right = reader.ReadInt32();
    
        // Bottom (4 bytes)
        int bottom = reader.ReadInt32();
    
        return Rectangle.FromLTRB(left, top, right, bottom);
    }
    

    PointS Object:

    public static Point ReadPoint16(this BinaryReader reader)
    {
        // x (2 bytes)
        int x = reader.ReadUInt16();
    
        // y (2 bytes)
        int y = reader.ReadUInt16();
    
        return new Point(x, y);
    }
    

    EMR_POLYPOLYGON16 Record (without type and size):

    public static PolyPolygon ReadPolyPolygon16(this BinaryReader reader)
    {
        // Bounds (16 bytes)
        Rectangle bounds = reader.ReadRectangle32();
    
        // NumberOfPolygons (4 bytes)
        int numberOfPolygons = reader.ReadInt32();
    
        // Count (4 bytes)
        int count = reader.ReadInt32();
    
        // PolygonPointCount (variable):
        //      A NumberOfPolygons length array of 32-bit unsigned integers
        var polygonPointCount = new int[numberOfPolygons];
        for (int i = 0; i < polygonPointCount.Length; i++)
        {
            polygonPointCount[i] = reader.ReadInt32();
        }
    
        // aPoints (variable):
        //      A Count length array of WMF PointS objects
        var points = new Point[count];
        for (int i = 0; i < points.Length; i++)
        {
            points[i] = reader.ReadPoint16();
        }
    
        return new PolyPolygon(bounds, numberOfPolygons, polygonPointCount, points);
    }
    

    Usage:

    byte[] buffer;
    using (var stream = new MemoryStream(buffer))
    using (var reader = new BinaryReader(stream))
    {
        var polypolygon = reader.ReadPolyPolygon16();
    }
    

    (Untested)