/* Check if the decoder can decode the image from this camera */ /* A RawDecoderException will be thrown if the camera isn't supported */ /* Unknown cameras does NOT generate any specific feedback */ /* This function must be overridden by actual decoders */ public void decodeUncompressed(ref IFD rawIFD, BitOrder order) { UInt32 nslices = rawIFD.getEntry(TagType.STRIPOFFSETS).dataCount; Tag offsets = rawIFD.getEntry(TagType.STRIPOFFSETS); Tag counts = rawIFD.getEntry(TagType.STRIPBYTECOUNTS); UInt32 yPerSlice = rawIFD.getEntry(TagType.ROWSPERSTRIP).getUInt(); Int32 width = rawIFD.getEntry(TagType.IMAGEWIDTH).getInt(); UInt32 height = rawIFD.getEntry(TagType.IMAGELENGTH).getUInt(); int bitPerPixel = rawIFD.getEntry(TagType.BITSPERSAMPLE).getInt(); List <RawSlice> slices = new List <RawSlice>(); UInt32 offY = 0; for (UInt32 s = 0; s < nslices; s++) { RawSlice slice = new RawSlice() { offset = (uint)offsets.data[s], count = (uint)counts.data[s] }; if (offY + yPerSlice > height) { slice.h = height - offY; } else { slice.h = yPerSlice; } offY += yPerSlice; if (mFile.isValid(slice.offset, slice.count)) // Only decode if size is valid { slices.Add(slice); } } if (0 == slices.Count) { throw new RawDecoderException("RAW Decoder: No valid slices found. File probably truncated."); } mRaw.dim.x = width; mRaw.dim.y = (int)offY; mRaw.whitePoint = (uint)(1 << bitPerPixel) - 1; offY = 0; for (int i = 0; i < slices.Count; i++) { RawSlice slice = slices[i]; var stream = mFile.BaseStream; TIFFBinaryReader input; if (mFile is TIFFBinaryReaderRE) { input = new TIFFBinaryReaderRE(mFile.BaseStream, slice.offset, slice.count); } else { input = new TIFFBinaryReader(mFile.BaseStream, slice.offset, slice.count); } iPoint2D size = new iPoint2D(width, (int)slice.h); iPoint2D pos = new iPoint2D(0, (int)offY); bitPerPixel = (int)(slice.count * 8u / (slice.h * width)); try { readUncompressedRaw(ref input, size, pos, width * bitPerPixel / 8, bitPerPixel, order); } catch (RawDecoderException) { if (i > 0) { //TODO add something } else { throw; } } catch (IOException e) { if (i > 0) { //TODO add something } else { throw new RawDecoderException("RAW decoder: IO error occurred in first slice, unable to decode more. Error is: " + e); } } offY += slice.h; } }
/* 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); }