/* Parse FUJI information */ /* It is a simpler form of Tiff IFD, so we add them as TiffEntries */ void ParseFuji(uint offset) { try { IFD tempIFD = new IFD(ifd.endian, ifd.Depth); ImageBinaryReaderBigEndian bytes = new ImageBinaryReaderBigEndian(stream, offset); uint entries = bytes.ReadUInt32(); if (entries > 255) { throw new RawDecoderException("Too many entries"); } for (int i = 0; i < entries; i++) { UInt16 tag = bytes.ReadUInt16(); uint length = bytes.ReadUInt16(); Tag t; // Set types of known tags switch (tag) { case 0x100: case 0x121: case 0x2ff0: t = new Tag((TagType)tag, TiffDataType.SHORT, length / 2); for (int k = 0; k < t.dataCount; k++) { t.data[k] = bytes.ReadUInt16(); } break; case 0xc000: // This entry seem to have swapped endianness: t = new Tag((TagType)tag, TiffDataType.LONG, length / 4); for (int k = 0; k < t.dataCount; k++) { t.data[k] = bytes.ReadUInt32(); } break; default: t = new Tag((TagType)tag, TiffDataType.UNDEFINED, length); for (int k = 0; k < t.dataCount; k++) { t.data[k] = bytes.ReadByte(); } break; } tempIFD.tags.Add(t.TagId, t); //bytes.ReadBytes((int)length); } ifd.subIFD.Add(tempIFD); } catch (IOException) { throw new RawDecoderException("IO error occurred during parsing. Skipping the rest"); } }
protected void Parse(uint offset) { //parse the ifd if (stream.Length < 16) { throw new RawDecoderException("Not a TIFF file (size too small)"); } Endianness endian = Endianness.Little; byte[] data = new byte[5]; stream.Position = offset; stream.Read(data, 0, 4); if (data[0] == 0x4D || data[1] == 0x4D) { //open binaryreader reader = new ImageBinaryReaderBigEndian(stream); endian = Endianness.Big; if (data[3] != 42 && data[3] != 0x4f) // ORF sometimes has 0x4f! { throw new RawDecoderException("Not a TIFF file (magic 42)"); } } else if (data[0] == 0x49 || data[1] == 0x49) { reader = new ImageBinaryReader(stream); if (data[2] != 42 && data[2] != 0x52 && data[2] != 0x55) // ORF has 0x52, RW2 0x55! { throw new RawDecoderException("Not a TIFF file (magic 42)"); } } else { throw new RawDecoderException("Not a TIFF file (ID)"); } reader.Position = offset + 4; var newIfd = new IFD(reader, reader.ReadUInt32(), endian, 0, (int)offset); if (ifd == null) { ifd = newIfd; } else { ifd.subIFD.Add(newIfd); } uint nextIFD = newIfd.NextOffset; while (nextIFD != 0) { ifd.subIFD.Add(new IFD(reader, nextIFD, endian, 0, (int)offset)); if (ifd.subIFD.Count > 100) { throw new RawDecoderException("TIFF file has too many Sub IFDs, probably broken"); } nextIFD = (ifd.subIFD[ifd.subIFD.Count - 1]).NextOffset; } }
public FujiMakerNote(byte[] data, Endianness endian, int depth) : base(endian, depth) { ImageBinaryReader file; if (endian == Endianness.Little) { file = new ImageBinaryReader(data); } else if (endian == Endianness.Big) { file = new ImageBinaryReaderBigEndian(data); } else { throw new RawDecoderException("Endianness not correct " + endian); } file.BaseStream.Position = 12; RelativeOffset = 0; Parse(file); file.Dispose(); }
public PentaxMakernote(byte[] data, int offset, int parentOffset, Endianness endian, int depth) : base(endian, depth) { ImageBinaryReader buffer; if (data[offset] == 0x4D && data[offset + 1] == 0x4D) { buffer = new ImageBinaryReaderBigEndian(data); } else if (data[offset] == 0x49 && data[offset + 1] == 0x49) { buffer = new ImageBinaryReaderBigEndian(data); } else { throw new RawDecoderException("Makernote endianness unknown " + data[0]); } buffer.BaseStream.Position += (offset + 2); RelativeOffset = -parentOffset; //offset are from the start of the tag Parse(buffer); buffer.Dispose(); }
public NikonMakerNote(byte[] data, int depth) : base(Endianness.Little, depth) { //read the header // buffer.BaseStream.Position = offset; StringMagic = ""; for (int i = 0; i < 6; i++) { StringMagic += (char)data[i]; } Version = (ushort)(data[8] << 8 | data[7]); //buffer.BaseStream.Position = 2 + offset;//jump the padding data = data.Skip(10).ToArray(); //header = new Header(buffer, 0); //0 car beggining of the stream ImageBinaryReader buffer; if (data[0] == 0x4D && data[1] == 0x4D) { buffer = new ImageBinaryReaderBigEndian(data); endian = Endianness.Big; } else if (data[0] == 0x49 && data[1] == 0x49) { buffer = new ImageBinaryReader(data); endian = Endianness.Little; } else { throw new RawDecoderException("Makernote endianness unknown " + data[0]); } buffer.BaseStream.Position = 2; buffer.ReadUInt16(); uint TIFFoffset = buffer.ReadUInt32(); buffer.BaseStream.Position = TIFFoffset; Parse(buffer); //parse gps info buffer.Dispose(); }
public Makernote(byte[] data, uint offset, Endianness endian, int depth, int parentOffset) : base(endian, depth) { type = IFDType.Makernote; ImageBinaryReader file; if (endian == Endianness.Little) { file = new ImageBinaryReader(data); } else if (endian == Endianness.Big) { file = new ImageBinaryReaderBigEndian(data); } else { throw new RawDecoderException("Endianness not correct " + endian); } file.BaseStream.Position = offset; RelativeOffset = -parentOffset; Parse(file); file.Dispose(); }
public PanasonicMakernote(byte[] data, Endianness endian, int depth) : base(endian, depth) { //start wth a tiff headder this.type = IFDType.Makernote; ImageBinaryReader file; if (endian == Endianness.Little) { file = new ImageBinaryReader(data); } else if (endian == Endianness.Big) { file = new ImageBinaryReaderBigEndian(data); } else { throw new RawDecoderException("Endianness not correct " + endian); } file.BaseStream.Position = 8; Parse(file); file.Dispose(); }
public RAFDecoder(Stream file) : base(file, true) { //alt_layout = false; // FUJI has pointers to IFD's at fixed byte offsets // So if camera is FUJI, we cannot use ordinary TIFF parser //get first 8 char and see if equal fuji file.Position = 0; var data = new byte[110]; file.Read(data, 0, 8); string dataAsString = System.Text.Encoding.UTF8.GetString(data.Take(8).ToArray()); if (dataAsString != "FUJIFILM") { throw new RawDecoderException("Header is wrong"); } //Fuji is indexer reverse endian reader = new ImageBinaryReaderBigEndian(file); reader.BaseStream.Position = 8; //read next 8 byte dataAsString = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(8).ToArray()).Trim(); //4 byte version var version = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(4).ToArray()); //8 bytes unknow ?? var unknow = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(8).ToArray()).Trim(); //32 byte a string (camera model) dataAsString = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(32).ToArray()).Trim(); //Directory //4 bytes version version = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(4).ToArray()); //20 bytes unkown ?? dataAsString = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(20).ToArray()).Trim(); //parse the ifd uint first_ifd = reader.ReadUInt32(); relativeOffset = first_ifd + 12; reader.ReadInt32(); //raw header // RAW information IFD on older uint third_ifd = reader.ReadUInt32(); reader.ReadUInt32(); uint secondIFD = reader.ReadUInt32(); uint count = reader.ReadUInt32(); try { Parse(secondIFD); } catch (Exception) { //old format ifd = new IFD(Endianness.Big, 0); //raw image var entry = new Tag(TagType.FUJI_STRIPOFFSETS, TiffDataType.LONG, 1); entry.data[0] = secondIFD; ifd.tags.Add(entry.TagId, entry); entry = new Tag(TagType.FUJI_STRIPBYTECOUNTS, TiffDataType.LONG, 1); entry.data[0] = count; ifd.tags.Add(entry.TagId, entry); } Parse(first_ifd + 12); ParseFuji(third_ifd); }
public void DecodePentax(IFD root, uint offset, uint size) { // Prepare huffmann table 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 = 16 entries byte[] pentax_tree = { 0, 2, 3, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 2, 5, 1, 6, 0, 7, 8, 9, 10, 11, 12 }; // 0 1 2 3 4 5 6 7 8 9 0 1 2 = 13 entries /* Attempt to read huffman table, if found in makernote */ Tag t = root.GetEntryRecursive((TagType)0x220); if (t != null) { if (t.dataType == TiffDataType.UNDEFINED) { ImageBinaryReader stream; if (root.endian == Common.GetHostEndianness()) { stream = new ImageBinaryReader(t.GetByteArray()); } else { stream = new ImageBinaryReaderBigEndian(t.GetByteArray()); } int depth = (stream.ReadUInt16() + 12) & 0xf; stream.ReadBytes(12); uint[] v0 = new uint[16]; uint[] v1 = new uint[16]; uint[] v2 = new uint[16]; for (int i = 0; i < depth; i++) { v0[i] = stream.ReadUInt16(); } for (int i = 0; i < depth; i++) { v1[i] = stream.ReadByte(); } /* Reset bits */ for (int i = 0; i < 17; i++) { huff[0].bits[i] = 0; } /* Calculate codes and store bitcounts */ for (int c = 0; c < depth; c++) { v2[c] = v0[c] >> (int)(12 - v1[c]); huff[0].bits[v1[c]]++; } /* Find smallest */ for (int i = 0; i < depth; i++) { uint sm_val = 0xfffffff; uint sm_num = 0xff; for (uint j = 0; j < depth; j++) { if (v2[j] <= sm_val) { sm_num = j; sm_val = v2[j]; } } huff[0].huffval[i] = sm_num; v2[sm_num] = 0xffffffff; } stream.Dispose(); } else { throw new RawDecoderException("Unknown Huffman table type."); } } else { /* Initialize with legacy data */ uint acc = 0; for (int i = 0; i < 16; i++) { huff[0].bits[i + 1] = pentax_tree[i]; acc += huff[0].bits[i + 1]; } huff[0].bits[0] = 0; for (int i = 0; i < acc; i++) { huff[0].huffval[i] = pentax_tree[i + 16]; } } huff[0].UseBigTable = true; huff[0].Create(frame.precision); input.BaseStream.Position = 0; huff[0].bitPump = new BitPumpMSB(input, offset, size); int[] pUp1 = { 0, 0 }; int[] pUp2 = { 0, 0 }; int pLeft1 = 0; int pLeft2 = 0; for (int y = 0; y < raw.fullSize.dim.height; y++) { var realY = y * raw.fullSize.dim.width; pUp1[y & 1] += huff[0].Decode(); pUp2[y & 1] += huff[0].Decode(); raw.fullSize.rawView[realY] = (ushort)(pLeft1 = pUp1[y & 1]); raw.fullSize.rawView[realY + 1] = (ushort)(pLeft2 = pUp2[y & 1]); for (int x = 2; x < raw.fullSize.dim.width; x += 2) { pLeft1 += huff[0].Decode(); pLeft2 += huff[0].Decode(); raw.fullSize.rawView[realY + x] = (ushort)pLeft1; raw.fullSize.rawView[realY + x + 1] = (ushort)pLeft2; } } }