public void DecompressNikon(TIFFBinaryReader metadata, UInt32 w, UInt32 h, UInt32 bitsPS, UInt32 offset, UInt32 size) { metadata.Position = 0; UInt32 v0 = metadata.ReadByte(); UInt32 v1 = metadata.ReadByte(); UInt32 huffSelect = 0; UInt32 split = 0; int[] pUp1 = new int[2]; int[] pUp2 = new int[2]; mUseBigtable = true; //_RPT2(0, "Nef version v0:%u, v1:%u\n", v0, v1); if (v0 == 73 || v1 == 88) { metadata.ReadBytes(2110); } if (v0 == 70) { huffSelect = 2; } if (bitsPS == 14) { huffSelect += 3; } pUp1[0] = metadata.ReadInt16(); pUp1[1] = metadata.ReadInt16(); pUp2[0] = metadata.ReadInt16(); pUp2[1] = metadata.ReadInt16(); int _max = 1 << (int)bitsPS & 0x7fff; UInt32 step = 0; UInt32 csize = metadata.ReadUInt16(); if (csize > 1) { step = (uint)_max / (csize - 1); } if (v0 == 68 && v1 == 32 && step > 0) { for (UInt32 i = 0; i < csize; i++) { curve[i * step] = (ushort)metadata.ReadInt16(); } for (int i = 0; i < _max; i++) { curve[i] = (ushort)((curve[i - i % step] * (step - i % step) + curve[i - i % step + step] * (i % step)) / step); } metadata.Position = (562); split = metadata.ReadUInt16(); } else if (v0 != 70 && csize <= 0x4001) { for (UInt32 i = 0; i < csize; i++) { curve[i] = metadata.ReadUInt16(); } _max = (int)csize; } initTable(huffSelect); mRaw.whitePoint = curve[_max - 1]; mRaw.blackLevel = curve[0]; if (!uncorrectedRawValues) { mRaw.setTable(curve, _max, true); } UInt32 x, y; BitPumpMSB bits = new BitPumpMSB(ref input, offset, size); UInt32 pitch = w; int pLeft1 = 0; int pLeft2 = 0; UInt32 cw = w / 2; UInt32 random = bits.peekBits(24); for (y = 0; y < h; y++) { if (split != 0 && (y == split)) { initTable(huffSelect + 1); } pUp1[y & 1] += HuffDecodeNikon(bits); pUp2[y & 1] += HuffDecodeNikon(bits); pLeft1 = pUp1[y & 1]; pLeft2 = pUp2[y & 1]; uint dest = y * pitch; mRaw.setWithLookUp((ushort)Common.clampbits(pLeft1, 15), ref mRaw.rawData, dest++, ref random); mRaw.setWithLookUp((ushort)Common.clampbits(pLeft2, 15), ref mRaw.rawData, dest++, ref random); for (x = 1; x < cw; x++) { bits.checkPos(); pLeft1 += HuffDecodeNikon(bits); pLeft2 += HuffDecodeNikon(bits); mRaw.setWithLookUp((ushort)Common.clampbits(pLeft1, 15), ref mRaw.rawData, dest++, ref random); mRaw.setWithLookUp((ushort)Common.clampbits(pLeft2, 15), ref mRaw.rawData, dest++, ref random); } } if (uncorrectedRawValues) { mRaw.setTable(curve, _max, false); } else { mRaw.table = (null); } }
/* This will attempt to parse makernotes and return it as an IFD */ IFD parseMakerNote(TIFFBinaryReader reader, uint off, Endianness parent_end) { IFD maker_ifd = null; uint offset = 0; TIFFBinaryReader mFile = null; reader.Position = off; byte[] data = reader.ReadBytes(100); // Pentax makernote starts with AOC\0 - If it's there, skip it if (data[0] == 0x41 && data[1] == 0x4f && data[2] == 0x43 && data[3] == 0) { //data = data.Skip(4).ToArray(); offset += 4; } // Pentax also has "PENTAX" at the start, makernote starts at 8 if (data[0 + offset] == 0x50 && data[1 + offset] == 0x45 && data[2 + offset] == 0x4e && data[3 + offset] == 0x54 && data[4 + offset] == 0x41 && data[5 + offset] == 0x58) { mFile = new TIFFBinaryReader(reader.BaseStream, offset + off, (uint)data.Length); parent_end = getTiffEndianness(data.Skip(8).ToArray()); if (parent_end == Endianness.unknown) { throw new TiffParserException("Cannot determine Pentax makernote endianness"); } //data = data.Skip(10).ToArray(); offset += 10; // Check for fuji signature in else block so we don't accidentally leak FileMap } else if (Common.memcmp(ref fuji_signature, ref data)) { offset = 12; mFile = new TIFFBinaryReader(reader.BaseStream, offset + off, (uint)data.Length); } else if (Common.memcmp(ref nikon_v3_signature, ref data)) { //offset = 10; offset = 10; // Read endianness if (data[0 + offset] == 0x49 && data[1 + offset] == 0x49) { parent_end = Endianness.little; mFile = new TIFFBinaryReader(reader.BaseStream, offset + off, (uint)data.Length); offset = 8; } else if (data[0 + offset] == 0x4D && data[1 + offset] == 0x4D) { parent_end = Endianness.big; mFile = new TIFFBinaryReaderRE(reader.BaseStream, offset + off, (uint)data.Length); offset = 8; } } // Panasonic has the word Exif at byte 6, a complete Tiff header starts at byte 12 // This TIFF is 0 offset based if (data[6] == 0x45 && data[7] == 0x78 && data[8] == 0x69 && data[9] == 0x66) { parent_end = getTiffEndianness(data.Skip(12).ToArray()); if (parent_end == Endianness.unknown) { throw new TiffParserException("Cannot determine Panasonic makernote endianness"); } offset = 20; } // Some have MM or II to indicate endianness - read that if (data[0] == 0x49 && data[1] == 0x49) { offset += 2; parent_end = Endianness.little; } else if (data[0] == 0x4D && data[1] == 0x4D) { parent_end = Endianness.big; offset += 2; } // Olympus starts the makernote with their own name, sometimes truncated if (Common.strncmp(data, "OLYMP", 5)) { offset += 8; if (Common.strncmp(data, "OLYMPUS", 7)) { offset += 4; } } // Epson starts the makernote with its own name if (Common.strncmp(data, "EPSON", 5)) { offset += 8; } // Attempt to parse the rest as an IFD try { if (mFile == null) { if (parent_end == Endianness.little) { mFile = new TIFFBinaryReader(reader.BaseStream, offset + off, (uint)data.Length); } else if (parent_end == Endianness.big) { mFile = new TIFFBinaryReaderRE(reader.BaseStream, offset + off, (uint)data.Length); } } /* if (parent_end == getHostEndianness()) * maker_ifd = new IFD(mFile, offset, depth); * else * maker_ifd = new IFDBE(mFile, offset, depth);*/ maker_ifd = new IFD(mFile, offset, endian, depth); } catch (Exception e) { Debug.WriteLine(e.Message); return(null); } // If the structure cannot be read, a TiffParserException will be thrown. return(maker_ifd); }
public IFD(TIFFBinaryReader fileStream, uint offset, Endianness endian) { this.endian = endian; fileStream.Position = offset; tagNumber = fileStream.ReadUInt16(); tags = new Dictionary <TagType, Tag>(); for (int i = 0; i < tagNumber; i++) { Tag temp = new Tag(); temp.tagId = (TagType)fileStream.ReadUInt16(); //add the displayname temp.displayName = null; temp.dataType = (TiffDataType)fileStream.ReadUInt16(); temp.dataCount = fileStream.ReadUInt32(); //IF makernote, do not parse data //if (temp.tagId == TagType.MAKERNOTE || temp.tagId == TagType.MAKERNOTE_ALT) temp.dataCount = 0; temp.dataOffset = 0; if (((temp.dataCount * temp.getTypeSize(temp.dataType) > 4))) { temp.dataOffset = fileStream.ReadUInt32(); } //Get the tag data temp.data = new Object[temp.dataCount]; long firstPosition = fileStream.Position; if (temp.dataOffset > 1) { fileStream.Position = temp.dataOffset; //todo check if correct } if (temp.tagId != TagType.MAKERNOTE && temp.tagId != TagType.MAKERNOTE_ALT) { for (int j = 0; j < temp.dataCount; j++) { switch (temp.dataType) { case TiffDataType.BYTE: case TiffDataType.UNDEFINED: case TiffDataType.ASCII: case TiffDataType.OFFSET: temp.data[j] = fileStream.ReadByte(); break; case TiffDataType.SHORT: temp.data[j] = fileStream.ReadUInt16(); break; case TiffDataType.LONG: temp.data[j] = fileStream.ReadUInt32(); break; case TiffDataType.RATIONAL: temp.data[j] = fileStream.ReadDouble(); break; case TiffDataType.SBYTE: temp.data[j] = fileStream.ReadSByte(); break; case TiffDataType.SSHORT: temp.data[j] = fileStream.ReadInt16(); //if (temp.dataOffset == 0 && temp.dataCount == 1) fileStream.ReadInt16(); break; case TiffDataType.SLONG: temp.data[j] = fileStream.ReadInt32(); break; case TiffDataType.SRATIONAL: //Because the nikonmakernote is broken with the tag 0x19 wich is double but offset of zero. //TODO remove this Fix if (temp.dataOffset == 0) { temp.data[j] = .0; } else { temp.data[j] = fileStream.ReadDouble(); } break; case TiffDataType.FLOAT: temp.data[j] = fileStream.ReadSingle(); break; case TiffDataType.DOUBLE: temp.data[j] = fileStream.ReadDouble(); break; } } }//Special tag switch (temp.tagId) { case TagType.DNGPRIVATEDATA: { try { IFD maker_ifd = parseDngPrivateData(temp); if (maker_ifd != null) { subIFD.Add(maker_ifd); } temp.data = null; } catch (TiffParserException) { // Unparsable private data are added as entries } catch (IOException) { // Unparsable private data are added as entries } } break; case TagType.MAKERNOTE: case TagType.MAKERNOTE_ALT: { try { //save current position long pos = fileStream.Position; IFD makernote = parseMakerNote(fileStream, temp.dataOffset, endian); if (makernote != null) { subIFD.Add(makernote); } //correct here fileStream.BaseStream.Position = pos; //return to current position } catch (TiffParserException) { // Unparsable makernotes are added as entries } catch (IOException) { // Unparsable makernotes are added as entries } } break; case TagType.FUJI_RAW_IFD: if (temp.dataType == TiffDataType.OFFSET) // FUJI - correct type { temp.dataType = TiffDataType.LONG; } goto case TagType.SUBIFDS; case TagType.SUBIFDS: case TagType.EXIFIFDPOINTER: case TagType.NIKONTHUMB: long p = fileStream.Position; try { for (Int32 k = 0; k < temp.dataCount; k++) { subIFD.Add(new IFD(fileStream, Convert.ToUInt32(temp.data[k]), endian, depth)); } } catch (TiffParserException) { // Unparsable subifds are added as entries } catch (IOException) { // Unparsable subifds are added as entries } fileStream.BaseStream.Position = p; break; } //transform data ToString if (temp.dataType == TiffDataType.ASCII) { //remove \0 if any if ((byte)temp.data[temp.dataCount - 1] == 0) { temp.data[temp.dataCount - 1] = (byte)' '; } string t = Encoding.ASCII.GetString(temp.data.Cast <byte>().ToArray()); temp.data = new Object[1]; temp.data[0] = t; } if (temp.dataOffset > 1) { fileStream.BaseStream.Position = firstPosition; } else if (temp.dataOffset == 0) { int k = (int)temp.dataCount * temp.getTypeSize(temp.dataType); if (k < 4) { fileStream.ReadBytes(4 - k); } } /*else * { * temp.dataCount = 0; * temp.data = null; * }*/ if (!tags.ContainsKey(temp.tagId)) { tags.Add(temp.tagId, temp); } else { Debug.WriteLine("tags already exist"); } } nextOffset = fileStream.ReadUInt16(); }
public void parseSOS() { if (!frame.initialized) { throw new Exception("parseSOS: Frame not yet initialized (SOF Marker not parsed)"); } UInt32 headerLength = (uint)input.ReadInt16(); UInt32 soscps = input.ReadByte(); if (frame.cps != soscps) { throw new Exception("parseSOS: Component number mismatch."); } for (UInt32 i = 0; i < frame.cps; i++) { UInt32 cs = input.ReadByte(); UInt32 count = 0; // Find the correct component while (frame.compInfo[count].componentId != cs) { if (count >= frame.cps) { throw new Exception("parseSOS: Invalid Component Selector"); } count++; } UInt32 b1 = input.ReadByte(); UInt32 td = b1 >> 4; if (td > 3) { throw new Exception("parseSOS: Invalid Huffman table selection"); } if (!huff[td].initialized) { throw new Exception("parseSOS: Invalid Huffman table selection, not defined."); } if (count > 3) { throw new Exception("parseSOS: Component count out of range"); } frame.compInfo[count].dcTblNo = td; } // Get predictor pred = input.ReadByte(); if (pred > 7) { throw new Exception("parseSOS: Invalid predictor mode."); } input.ReadBytes(1); // Se + Ah Not used in LJPEG UInt32 b = input.ReadByte(); Pt = b & 0xf; // Point Transform UInt32 cheadersize = 3 + frame.cps * 2 + 3; //_ASSERTE(cheadersize == headerLength); bits = new BitPumpJPEG(input); decodeScan(); input.ReadBytes((int)bits.getOffset()); }