using FSpot.Tiff; namespace FSpot.Mrw { // Minolta raw format // see http://www.dalibor.cz/minolta/raw_file_format.htm for details // note that the blocks can be in any order. public class Block { protected byte [] name; protected uint Length; protected long Start; protected System.IO.Stream stream; byte [] data; public Block (System.IO.Stream stream) { this.stream = stream; Start = stream.Position; name = new byte [4]; byte [] tmp = new byte [8]; stream.Read (tmp, 0, tmp.Length); System.Array.Copy (tmp, name, name.Length); System.Console.WriteLine (this.Name); Length = BitConverter.ToUInt32 (tmp, name.Length, false); stream.Position = stream.Position + Length; } public string Name { get { return System.Text.Encoding.ASCII.GetString (this.name, 1, 3); } } public byte [] Data { get { if (data == null) data = ReadData (); return data; } } public static Block Create (System.IO.Stream stream) { byte [] tmp = new byte [4]; stream.Read (tmp, 0, tmp.Length); stream.Position -= 4; string name = System.Text.Encoding.ASCII.GetString (tmp, 1, 3); switch (name) { case "TTW": return new TtwBlock (stream); case "PRD": return new PrdBlock (stream); default: return new Block (stream); } } protected byte [] ReadData () { stream.Position = Start + 8; byte [] data = new byte [this.Length]; stream.Read (data, 0, data.Length); return data; } } public class PrdBlock : Block { public PrdBlock (System.IO.Stream stream) : base (stream) { } public ulong Version { get { return BitConverter.ToUInt64 (this.Data, 0, false); } } public ushort CCDSizeY { get { return BitConverter.ToUInt16 (this.Data, 8, false); } } public ushort CCDSizeX { get { return BitConverter.ToUInt16 (this.Data, 10, false); } } public ushort ImageSizeY { get { return BitConverter.ToUInt16 (this.Data, 12, false); } } public ushort ImageSizeX { get { return BitConverter.ToUInt16 (this.Data, 14, false); } } public byte Depth { get { return this.Data [16]; } } public byte SampleDepth { get { return this.Data [17]; } } } internal class TtwBlock : Block { FSpot.Tiff.Header header; public TtwBlock (System.IO.Stream stream) : base (stream) { if (this.Name != "TTW") throw new System.Exception (System.String.Format ("invalid block name {0}", this.Name)); } public FSpot.Tiff.Header TiffHeader { get { if (header == null) { try { System.IO.MemoryStream mem = new System.IO.MemoryStream (this.Data); System.Console.WriteLine ("before header"); header = new Header (mem); } catch (System.Exception e) { System.Console.WriteLine (e.ToString ()); } } return header; } } } internal class MrmBlock : Block { Block [] blocks; public MrmBlock (System.IO.Stream stream) : base (stream) {} protected void Load () { stream.Position = Start + 8; System.Collections.ArrayList list = new System.Collections.ArrayList (); while (stream.Position < Start + 8 + Length) { list.Add (Block.Create (stream)); } blocks = (Block []) list.ToArray (typeof (Block)); } public Block [] Blocks { get { if (blocks == null) { Load (); } return blocks; } } } public class MrwFile : ImageFile, SemWeb.StatementSource { MrmBlock mrm; FSpot.Tiff.Header header; public MrwFile (System.Uri uri) : base (uri) { } // false seems a safe default public bool Distinct { get { return false; } } public MrwFile (string path) : base (path) { } public FSpot.Tiff.Header Header { get { if (mrm == null) LoadBlocks (); return header; } } public override System.DateTime Date { get { DirectoryEntry e = this.Header.Directory.Lookup (TagId.DateTime); if (e != null) return DirectoryEntry.DateTimeFromString (e.StringValue).ToUniversalTime (); else return base.Date; } } public void Select (SemWeb.StatementSink sink) { this.Header.Select (sink); } public override System.IO.Stream PixbufStream () { return DCRawFile.RawPixbufStream (uri); } public override Gdk.Pixbuf Load () { using (System.IO.Stream stream = Open ()) { return new Gdk.Pixbuf (PixbufStream ()); } } public override Gdk.Pixbuf Load (int width, int height) { return PixbufUtils.ScaleToMaxSize (this.Load (), width, height); } protected void LoadBlocks () { using (System.IO.Stream file = Open ()) { mrm = new MrmBlock (file); try { foreach (Block b in mrm.Blocks) { if (b is TtwBlock) { TtwBlock ttw = (TtwBlock) b; header = ttw.TiffHeader; //Header.Dump ("TTW:"); break; } } } catch (System.Exception e) { System.Console.WriteLine (e.ToString ()); } } } } }