public static StructuredDataRecord ReadStructuredDataRecord(MetafileReader reader) { // overall length seems to be encoded similar to the string length [ISO/IEC 8632-3 7, Table 1, Note 12] // (ie. one byte, followed by one word if its 255). int length = reader.ReadByte(); if (length == 255) { // FIXME: does an SDR also have a long form similar to a string? length = reader.ReadWord(); } var elements = new List <StructuredDataElement>(); long startPosition = reader.Position; // require at least the number of bytes for the enum and the count; which depends on integer/index precision: // > The integer of the "data count" and the index of the "data type index" are represented respectively at the current // > Integer Precision and the current Index Precision of the metafile. [ISO/IEC 8632-1 H.2.2] // some files seem to include padding or similar, which throws this off by having an extra byte available at the end while (reader.HasMoreData((reader.Descriptor.IndexPrecision + reader.Descriptor.IntegerPrecision) / 8)) { // enum is an index at the current index precision for SDR [ISO/IEC 8632-1 H.2.2] DataTypeIndex type = (DataTypeIndex)Enum.ToObject(typeof(DataTypeIndex), reader.ReadIndex()); // count is an interger at the current integer precision for SDR [ISO/IEC 8632-1 H.2.2] int count = reader.ReadInteger(); object[] values = new object[count]; for (int i = 0; i < count; i++) { values[i] = ReadValue(reader, type); } elements.Add(new StructuredDataElement(type, values)); // only read as much as specified by length if (reader.Position - startPosition >= length) { break; } } return(new StructuredDataRecord(elements)); }
public static CellArray CellArray(MetafileReader reader, CommandHeader commandHeader) { // P1: (point) corner point P // P2: (point) corner point Q // P3: (point) corner point R // P4: (integer) nx // P5: (integer) ny // P6: (integer) local colour precision: valid values are 0, 1, 2, 4, 8, 16, 24, and 32. If the value is zero (the // 'default colour precision indicator' value), the COLOUR (INDEX) PRECISION for the picture indicates the // precision with which the colour list is encoded. If the value is non-zero, the precision with which the colour // data is encoded is given by the value. // P7: (enumerated) cell representation mode: valid values are // 0 run length list mode // 1 packed list mode // P8: (colour list) array of cell colour values. // If the COLOUR SELECTION MODE is 'direct', the values will be direct colour values. If the COLOUR // SELECTION MODE is 'indexed', the values will be indexes into the COLOUR TABLE. // If the cell representation mode is 'packed list', the colour values are represented by rows of values, each // row starting on a word boundary. If the cell representation mode is 'run length', the colour list values are // represented by rows broken into runs of constant colour; each row starts on a word boundary. Each list // item consists of a cell count (integer) followed by a colour value. With the exception of the first run of a // row, the integer count of each run immediately follows the colour specifier of the preceding run with no // intervening padding. var p = reader.ReadPoint(); var q = reader.ReadPoint(); var r = reader.ReadPoint(); int nx = reader.ReadInteger(); int ny = reader.ReadInteger(); int localColorPrecision = reader.ReadInteger(); if (localColorPrecision == 0) { if (reader.Descriptor.ColorSelectionMode == ColorModeType.Direct) { localColorPrecision = reader.Descriptor.ColorPrecision; } else { localColorPrecision = reader.Descriptor.ColorIndexPrecision; } } // might be either 1/2/4 or 8/16/32 here; but we want byte-sizes in ReadColor if (localColorPrecision >= 8) { localColorPrecision /= 8; } var cellRepresentationMode = reader.ReadEnum <CellRepresentationMode>(); int totalCount = nx * ny; var colors = new List <MetafileColor>(); while (colors.Count < totalCount) { // chunks are split into rows; each row is word-aligned // word-align the next read if necessary if (reader.Position % 2 == 1 && reader.HasMoreData()) { reader.ReadByte(); } int rowCount = nx; while (rowCount > 0) { if (cellRepresentationMode == CellRepresentationMode.RunLengthList) { int cellCount = reader.ReadInteger(); rowCount -= cellCount; var cellColor = reader.ReadColor(localColorPrecision); colors.AddRange(Enumerable.Range(0, cellCount).Select(i => cellColor)); } else { rowCount--; colors.Add(reader.ReadColor(localColorPrecision)); } } } return(new CellArray(p, q, r, nx, ny, colors.ToArray())); }