Skip to content

Commit 19e364f

Browse files
committed
WIP
1 parent f15124b commit 19e364f

File tree

1 file changed

+118
-3
lines changed

1 file changed

+118
-3
lines changed

MetadataExtractor/NewApi.cs

Lines changed: 118 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,12 @@ public enum PcxProperty
637637
Version,
638638
}
639639

640-
public sealed class PcxDirectory : Directory<IEntry>
640+
public sealed class PcxDirectory : IDirectory
641641
{
642+
public const int HeaderSizeBytes = 74;
643+
644+
private readonly byte[] _bytes;
645+
642646
// NOTE this directory must be strict about the values it can receive for properties.
643647
// Version, for example, must be a byte. Other types are invalid and cannot be written.
644648
// This is different to TIFF, for example, where a value has an expected type, but may
@@ -652,15 +656,126 @@ public sealed class PcxDirectory : Directory<IEntry>
652656
// operations work directly on that byte array. Maybe all read/write operations provide the
653657
// directory instance. This would also help with Exif tags that need to read multiple values
654658
// as part of their description, but will make the API uglier I think.
659+
660+
private static readonly IndexedTable _pcxVersionTable = new IndexedTable(new[]
661+
{
662+
"2.5 with fixed EGA palette information",
663+
null,
664+
"2.8 with modifiable EGA palette information",
665+
"2.8 without palette information (default palette)",
666+
"PC Paintbrush for Windows",
667+
"3.0 or better"
668+
});
669+
670+
private static readonly IndexedTable _pcxColorPlanesTable = new IndexedTable(new[] { "24-bit color", "16 colors" }, baseIndex: 3);
671+
private static readonly IndexedTable _pcxPaletteTypeTable = new IndexedTable(new[] { "Color or B&W", "Grayscale" }, baseIndex: 1);
672+
673+
public PcxDirectory(byte[] bytes)
674+
{
675+
if (bytes == null)
676+
throw new ArgumentNullException(nameof(bytes));
677+
if (bytes.Length != HeaderSizeBytes)
678+
throw new ArgumentException($"Must contain {HeaderSizeBytes} bytes", nameof(bytes));
679+
_bytes = bytes;
680+
}
681+
682+
public byte Version
683+
{
684+
get => _bytes[1];
685+
set => _bytes[1] = value;
686+
}
687+
688+
public byte BitsPerPixel
689+
{
690+
get => _bytes[3];
691+
set => _bytes[3] = value;
692+
}
693+
694+
// TODO additional properties
695+
696+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
697+
698+
public IEnumerator<IEntry> GetEnumerator()
699+
{
700+
yield return new Entry<byte>("Version", Version, index => _pcxVersionTable.LookUp(index));
701+
yield return new Entry<byte>("Bits Per Pixel", BitsPerPixel);
702+
yield return new Entry<ushort>("X Min", XMin);
703+
yield return new Entry<ushort>("Y Min", YMin);
704+
yield return new Entry<ushort>("X Max", XMax);
705+
yield return new Entry<ushort>("Y Max", YMax);
706+
yield return new Entry<ushort>("Horizontal DPI", HorizontalDpi);
707+
yield return new Entry<ushort>("Vertical DPI", VerticalDpi);
708+
yield return new Entry<byte[]>("Palette", Palette);
709+
yield return new Entry<byte>("Color Planes", ColorPlanes, index => _pcxColorPlanesTable.LookUp(index));
710+
yield return new Entry<ushort>("Bytes Per Line", BytesPerLine);
711+
yield return new Entry<ushort>("Palette Type", PalleteType, index => _pcxPaletteTypeTable.LookUp(index));
712+
}
713+
714+
public int Count => 14;
715+
716+
public string Name => "PCX";
717+
718+
public IEnumerable<IDirectory> SubDirectories => Enumerable.Empty<IDirectory>();
719+
}
720+
721+
internal sealed class IndexedTable
722+
{
723+
public IndexedTable(string?[] strings, int baseIndex = 0)
724+
{
725+
}
726+
727+
public string? LookUp(int index)
728+
{
729+
asdf
730+
}
731+
}
732+
733+
public class Entry<T> : IEntry
734+
{
735+
private readonly Func<T, string> _descriptor;
736+
737+
public Entry(string name, T value, Func<T, string>? descriptor = null)
738+
{
739+
_descriptor = descriptor;
740+
Name = name;
741+
Value = value;
742+
}
743+
744+
private T Value { get; }
745+
object IEntry.Value => Value;
746+
public string Name { get; }
747+
public string Description => _descriptor == null ? Value.ToString() : _descriptor(Value);
655748
}
656749

657750
public sealed class PcxReader
658751
{
659752
public PcxDirectory Extract(SequentialReader reader)
660753
{
661-
reader = reader.WithByteOrder(isMotorolaByteOrder: false);
754+
byte[] bytes;
755+
try
756+
{
757+
bytes = reader.GetBytes(PcxDirectory.HeaderSizeBytes);
758+
}
759+
catch (Exception ex)
760+
{
761+
return WithError("Exception reading PCX metadata: " + ex.Message);
762+
}
763+
764+
if (bytes[0] != 0x0A)
765+
return WithError("Invalid PCX identifier byte");
766+
if (bytes[2] != 0x01)
767+
return WithError("Invalid PCX encoding byte");
768+
769+
// reader = reader.WithByteOrder(isMotorolaByteOrder: false);
770+
771+
return new PcxDirectory(bytes);
662772

663-
var directory = new PcxDirectory();
773+
static PcxDirectory WithError(string errorMessage)
774+
{
775+
var directory = new PcxDirectory();
776+
directory.AddError(errorMessage);
777+
return directory;
778+
}
664779

665780
try
666781
{

0 commit comments

Comments
 (0)