Beispiel #1
0
        public void Decode12BitRawBE(TIFFBinaryReader input, UInt32 w, UInt32 h)
        {
            if (w < 2)
            {
                throw new IOException("Are you mad? 1 pixel wide raw images are no fun");
            }

            UInt32 pitch = mRaw.pitch;

            if (input.getRemainSize() < ((w * 12 / 8) * h))
            {
                if ((UInt32)input.getRemainSize() > (w * 12 / 8))
                {
                    h = (uint)(input.getRemainSize() / (w * 12 / 8) - 1);
                    mRaw.errors.Add("Image truncated (file is too short)");
                }
                else
                {
                    throw new IOException("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
                }
            }
            for (UInt32 y = 0; y < h; y++)
            {
                for (UInt32 x = 0; x < w; x += 2)
                {
                    UInt32 g1 = input.ReadByte();
                    UInt32 g2 = input.ReadByte();
                    mRaw.rawData[y * pitch + x] = (ushort)((g1 << 4) | (g2 >> 4));
                    UInt32 g3 = input.ReadByte();
                    mRaw.rawData[y * pitch + x + 1] = (ushort)(((g2 & 0x0f) << 8) | g3);
                }
            }
        }
        /*
         * void DecodeThread()
         * {
         *  DngDecoderThread me = _this;
         *  DngDecoderSlices parent = me.parent;
         *  try
         *  {
         *      Task
         *      parent.decodeSlice(me);
         *  }
         *  catch (Exception)
         *  {
         *      parent.mRaw.errors.Add("DNGDEcodeThread: Caught exception.");
         *  }
         *  return;
         * }*/


        public DngDecoderSlices(TIFFBinaryReader file, RawImage img, int _compression)
        {
            mFile       = (file);
            mRaw        = (img);
            mFixLjpeg   = false;
            compression = _compression;
        }
Beispiel #3
0
        public void Decode12BitRawUnpacked(TIFFBinaryReader input, UInt32 w, UInt32 h)
        {
            UInt32 pitch = mRaw.pitch;

            if (input.getRemainSize() < w * h * 2)
            {
                if ((UInt32)input.getRemainSize() > w * 2)
                {
                    h = (uint)(input.getRemainSize() / (w * 2) - 1);
                    mRaw.errors.Add("Image truncated (file is too short)");
                }
                else
                {
                    throw new IOException("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
                }
            }
            for (UInt32 y = 0; y < h; y++)
            {
                for (UInt32 x = 0; x < w; x += 1)
                {
                    UInt32 g1 = input.ReadByte();
                    UInt32 g2 = input.ReadByte();
                    mRaw.rawData[y * pitch + x] = (ushort)(((g2 << 8) | g1) >> 4);
                }
            }
        }
 /*** Used for entropy encoded sections, for now only Nikon Coolpix ***/
 public BitPumpMSB32(ref TIFFBinaryReader s)
 {
     s.Read(buffer, (int)s.Position, (int)s.BaseStream.Length);
     size         = (uint)(s.getRemainSize() + sizeof(UInt32));
     MIN_GET_BITS = (BITS_PER_LONG_LONG - 33);
     init();
 }
 public NikonDecompressor(TIFFBinaryReader file, RawImage img) : base(file, img)
 {
     for (UInt32 i = 0; i < 0x8000; i++)
     {
         curve[i] = (ushort)i;
     }
 }
Beispiel #6
0
 /*** Used for entropy encoded sections ***/
 public BitPumpMSB(ref TIFFBinaryReader s, uint offset, uint count)
 {
     MIN_GET_BITS          = (BITS_PER_LONG - 7);
     size                  = count + sizeof(UInt32);
     buffer                = new byte[size];
     s.BaseStream.Position = offset;
     s.BaseStream.Read(buffer, 0, (int)count);
     init();
 }
Beispiel #7
0
 /* Construct decoder instance - FileMap is a filemap of the file to be decoded */
 /* The FileMap is not owned by this class, will not be deleted, and must remain */
 /* valid while this object exists */
 public RawDecoder(ref TIFFBinaryReader file)
 {
     mRaw                  = new RawImage();
     mFile                 = file;
     decoderVersion        = 0;
     failOnUnknown         = false;
     interpolateBadPixels  = false;
     applyStage1DngOpcodes = true;
     applyCrop             = true;
     uncorrectedRawValues  = false;
     fujiRotate            = true;
 }
Beispiel #8
0
        public void parseData()
        {
            if (stream.Length < 16)
            {
                throw new TiffParserException("Not a TIFF file (size too small)");
            }
            Endianness endian = Endianness.little;

            byte[] data = new byte[5];
            stream.Position = 0;
            stream.Read(data, 0, 4);
            if (data[0] == 0x4D || data[1] == 0x4D)
            {
                //open binaryreader
                reader = new TIFFBinaryReaderRE(stream);
                endian = Endianness.big;

                if (data[3] != 42 && data[2] != 0x4f) // ORF sometimes has 0x4f, Lovely!
                {
                    throw new TiffParserException("Not a TIFF file (magic 42)");
                }
            }
            else if (data[0] == 0x49 || data[1] == 0x49)
            {
                reader = new TIFFBinaryReader(stream);
                if (data[2] != 42 && data[2] != 0x52 && data[2] != 0x55) // ORF has 0x52, RW2 0x55 - Brillant!
                {
                    throw new TiffParserException("Not a TIFF file (magic 42)");
                }
            }
            else
            {
                throw new TiffParserException("Not a TIFF file (ID)");
            }

            UInt32 nextIFD;

            reader.Position = 4;
            nextIFD         = reader.ReadUInt32();
            rootIFD         = new IFD(reader, nextIFD, endian, 0);
            nextIFD         = rootIFD.nextOffset;
            while (nextIFD != 0)
            {
                rootIFD.subIFD.Add(new IFD(reader, nextIFD, endian, 0));
                if (rootIFD.subIFD.Count > 100)
                {
                    throw new TiffParserException("TIFF file has too many SubIFDs, probably broken");
                }
                nextIFD = (rootIFD.subIFD[rootIFD.subIFD.Count - 1]).nextOffset;
            }
        }
Beispiel #9
0
        public void Decode12BitRawBEInterlaced(TIFFBinaryReader input, UInt32 w, UInt32 h)
        {
            if (w < 2)
            {
                throw new IOException("Are you mad? 1 pixel wide raw images are no fun");
            }

            UInt32 pitch = mRaw.pitch;

            if (input.getRemainSize() < ((w * 12 / 8) * h))
            {
                if ((UInt32)input.getRemainSize() > (w * 12 / 8))
                {
                    h = (uint)(input.getRemainSize() / (w * 12 / 8) - 1);
                    mRaw.errors.Add("Image truncated (file is too short)");
                }
                else
                {
                    throw new IOException("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
                }
            }

            UInt32 half = (h + 1) >> 1;
            UInt32 y    = 0;

            for (UInt32 row = 0; row < h; row++)
            {
                y = row % half * 2 + row / half;
                if (y == 1)
                {
                    // The second field starts at a 2048 byte aligment
                    UInt32 offset = ((half * w * 3 / 2 >> 11) + 1) << 11;
                    if (offset > input.getRemainSize())
                    {
                        throw new IOException("Decode12BitSplitRaw: Trying to jump to invalid offset " + offset);
                    }
                    input.Position = offset;
                }
                for (UInt32 x = 0; x < w; x += 2)
                {
                    UInt32 g1 = input.ReadByte();
                    UInt32 g2 = input.ReadByte();
                    mRaw.rawData[y * pitch + x] = (ushort)((g1 << 4) | (g2 >> 4));
                    UInt32 g3 = input.ReadByte();
                    mRaw.rawData[y * pitch + x + 1] = (ushort)(((g2 & 0x0f) << 8) | g3);
                }
            }
        }
 public LJpegDecompressor(TIFFBinaryReader file, RawImage img)
 {
     mRaw  = (img);
     input = file;
     skipX = skipY = 0;
     for (int i = 0; i < 4; i++)
     {
         huff[i].initialized = false;
         huff[i].bigTable    = null;
     }
     mDNGCompatible = false;
     slicesW.Clear();
     mUseBigtable       = false;
     mCanonFlipDim      = false;
     mCanonDoubleHeight = false;
 }
Beispiel #11
0
        public void Decode12BitRawBEWithControl(ref TIFFBinaryReader input, UInt32 w, UInt32 h)
        {
            if (w < 2)
            {
                throw new IOException("Are you mad? 1 pixel wide raw images are no fun");
            }

            UInt32 pitch = mRaw.pitch;

            // Calulate expected bytes per line.
            UInt32 perline = (w * 12 / 8);

            // Add skips every 10 pixels
            perline += ((w + 2) / 10);

            // If file is too short, only decode as many lines as we have
            if (input.getRemainSize() < (perline * h))
            {
                if ((UInt32)input.getRemainSize() > perline)
                {
                    h = (uint)(input.getRemainSize() / perline - 1);
                    mRaw.errors.Add("Image truncated (file is too short)");
                }
                else
                {
                    throw new IOException("Decode12BitRawBEWithControl: Not enough data to decode a single line. Image file truncated.");
                }
            }

            UInt32 x;

            for (UInt32 y = 0; y < h; y++)
            {
                for (x = 0; x < w; x += 2)
                {
                    UInt32 g1 = input.ReadByte();
                    UInt32 g2 = input.ReadByte();
                    mRaw.rawData[(y * pitch) + x] = (ushort)((g1 << 4) | (g2 >> 4));
                    UInt32 g3 = input.ReadByte();
                    mRaw.rawData[(y * pitch) + x + 1] = (ushort)(((g2 & 0x0f) << 8) | g3);
                    if ((x % 10) == 8)
                    {
                        input.Position++;
                    }
                }
            }
        }
        public void getSOF(SOFInfo sof, UInt32 offset, UInt32 size)
        {
            if (!input.isValid(offset, size))
            {
                throw new Exception("getSOF: Start offset plus size is longer than file. Truncated file.");
            }
            try
            {
                Endianness host_endian = Common.getHostEndianness();
                // JPEG is big endian
                if (host_endian == Endianness.big)
                {
                    input = new TIFFBinaryReader(input.BaseStream, offset, size);
                }
                else
                {
                    input = new TIFFBinaryReaderRE(input.BaseStream, offset, size);
                }

                if (getNextMarker(false) != JpegMarker.M_SOI)
                {
                    throw new Exception("getSOF: Image did not start with SOI. Probably not an LJPEG");
                }

                while (true)
                {
                    JpegMarker m = getNextMarker(true);
                    if (JpegMarker.M_SOF3 == m)
                    {
                        parseSOF(sof);
                        return;
                    }
                    if (JpegMarker.M_EOI == m)
                    {
                        throw new Exception("LJpegDecompressor: Could not locate Start of Frame.");
                    }
                }
            }
            catch (IOException)
            {
                throw new Exception("LJpegDecompressor: IO exception, read outside file. Corrupt File.");
            }
        }
Beispiel #13
0
        public DngDecoder(IFD rootIFD, ref TIFFBinaryReader file) : base(ref file)
        {
            mRootIFD = (rootIFD);
            List <IFD> data = mRootIFD.getIFDsWithTag(TagType.DNGVERSION);
            var        v    = data[0].getEntry(TagType.DNGVERSION).data;

            if ((byte)v[0] != 1)
            {
                throw new RawDecoderException("Not a supported DNG image format: " + (int)v[0] + (int)v[1] + (int)v[2] + (int)v[3]);
            }
            //  if (v[1] > 4)
            //    throw new RawDecoderException("Not a supported DNG image format: v%u.%u.%u.%u", (int)v[0], (int)v[1], (int)v[2], (int)v[3]);

            if (((byte)v[0] <= 1) && ((byte)v[1] < 1))  // Prior to v1.1.xxx  fix LJPEG encoding bug
            {
                mFixLjpeg = true;
            }
            else
            {
                mFixLjpeg = false;
            }
        }
Beispiel #14
0
        public void Decode8BitRaw(ref TIFFBinaryReader input, UInt32 w, UInt32 h)
        {
            ushort[] data  = mRaw.rawData;
            UInt32   pitch = mRaw.pitch;

            if (input.getRemainSize() < w * h)
            {
                if ((UInt32)input.getRemainSize() > w)
                {
                    h = (uint)(input.getRemainSize() / w - 1);
                    mRaw.errors.Add("Image truncated (file is too short)");
                }
                else
                {
                    throw new IOException("Decode8BitRaw: Not enough data to decode a single line. Image file truncated.");
                }
            }

            UInt32 random = 0;

            for (UInt32 y = 0; y < h; y++)
            {
                for (UInt32 x = 0; x < w; x += 1)
                {
                    if (uncorrectedRawValues)
                    {
                        mRaw.rawData[(y * pitch) + x] = input.ReadByte();
                    }
                    else
                    {
                        mRaw.setWithLookUp(input.ReadByte(), ref mRaw.rawData, x, ref random);
                        input.Position++;
                    }
                }
            }
        }
Beispiel #15
0
        protected override Thumbnail decodeThumbInternal()
        {
            //find the preview IFD (usually the first if any)
            try
            {
                List <IFD> potential = mRootIFD.getIFDsWithTag(TagType.NEWSUBFILETYPE);
                if (potential != null || potential.Count != 0)
                {
                    IFD thumbIFD = null;
                    for (int i = 0; i < potential.Count; i++)
                    {
                        var subFile = potential[i].getEntry(TagType.NEWSUBFILETYPE);
                        if (subFile.getInt() == 1)
                        {
                            thumbIFD = potential[i];
                            break;
                        }
                    }
                    if (thumbIFD != null)
                    {
                        //there is a thumbnail
                        UInt32   sample_format = 1;
                        UInt32   bps           = thumbIFD.getEntry(TagType.BITSPERSAMPLE).getUInt();
                        iPoint2D dim;
                        if (thumbIFD.hasEntry(TagType.SAMPLEFORMAT))
                        {
                            sample_format = thumbIFD.getEntry(TagType.SAMPLEFORMAT).getUInt();
                        }
                        try
                        {
                            dim = new iPoint2D()
                            {
                                x = thumbIFD.getEntry(TagType.IMAGEWIDTH).getInt(),
                                y = thumbIFD.getEntry(TagType.IMAGELENGTH).getInt()
                            };
                        }
                        catch (TiffParserException)
                        {
                            throw new RawDecoderException("DNG Decoder: Could not read basic image information.");
                        }

                        int compression = thumbIFD.getEntry(TagType.COMPRESSION).getShort();
                        // Now load the image
                        if (compression == 1)
                        {  // Uncompressed.
                            UInt32 cpp = thumbIFD.getEntry(TagType.SAMPLESPERPIXEL).getUInt();
                            if (cpp > 4)
                            {
                                throw new RawDecoderException("DNG Decoder: More than 4 samples per pixel is not supported.");
                            }


                            Tag    offsets   = thumbIFD.getEntry(TagType.STRIPOFFSETS);
                            Tag    counts    = thumbIFD.getEntry(TagType.STRIPBYTECOUNTS);
                            UInt32 yPerSlice = thumbIFD.getEntry(TagType.ROWSPERSTRIP).getUInt();
                            UInt32 width     = thumbIFD.getEntry(TagType.IMAGEWIDTH).getUInt();
                            UInt32 height    = thumbIFD.getEntry(TagType.IMAGELENGTH).getUInt();

                            if (counts.dataCount != offsets.dataCount)
                            {
                                throw new RawDecoderException("DNG Decoder: Byte count number does not match strip size: count:" + counts.dataCount + ", strips:" + offsets.dataCount);
                            }

                            UInt32          offY   = 0;
                            List <DngStrip> slices = new List <DngStrip>();
                            for (UInt32 s = 0; s < offsets.dataCount; s++)
                            {
                                DngStrip slice = new DngStrip();
                                slice.offset  = offsets.getUInt(s);
                                slice.count   = counts.getUInt(s);
                                slice.offsetY = offY;
                                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);
                                }
                            }

                            for (int i = 0; i < slices.Count; i++)
                            {
                                DngStrip         slice = slices[i];
                                TIFFBinaryReader input = new TIFFBinaryReader(mFile.BaseStream, slice.offset, (uint)mFile.BaseStream.Length);
                                iPoint2D         size  = new iPoint2D((int)width, (int)slice.h);
                                iPoint2D         pos   = new iPoint2D(0, (int)slice.offsetY);

                                bool big_endian = (thumbIFD.endian == Endianness.big);
                                // DNG spec says that if not 8 or 16 bit/sample, always use big endian
                                if (bps != 8 && bps != 16)
                                {
                                    big_endian = true;
                                }
                                try
                                {
                                    // readUncompressedRaw(ref input, size, pos, (int)(mRaw.cpp * width * bps / 8), (int)bps, big_endian ? BitOrder.Jpeg : BitOrder.Plain);
                                }
                                catch (IOException ex)
                                {
                                    throw new RawDecoderException("DNG decoder: IO error occurred in first slice, unable to decode more. Error is: " + ex.Message);
                                }
                            }
                        }
                        else if (compression == 7 || compression == 0x884c)
                        {
                            /*
                             * // Let's try loading it as tiles instead
                             *
                             * uint cpp = (thumbIFD.getEntry(TagType.SAMPLESPERPIXEL).getUInt());
                             *
                             * if (sample_format != 1)
                             *  throw new RawDecoderException("DNG Decoder: Only 16 bit unsigned data supported for compressed data.");
                             *
                             * DngDecoderSlices slices = new DngDecoderSlices(mFile, mRaw, compression);
                             * if (thumbIFD.hasEntry(TagType.TILEOFFSETS))
                             * {
                             *  UInt32 tilew = thumbIFD.getEntry(TagType.TILEWIDTH).getUInt();
                             *  UInt32 tileh = thumbIFD.getEntry(TagType.TILELENGTH).getUInt();
                             *  if (tilew == 0 || tileh == 0)
                             *      throw new RawDecoderException("DNG Decoder: Invalid tile size");
                             *
                             *  UInt32 tilesX = (uint)(mRaw.dim.x + tilew - 1) / tilew;
                             *  UInt32 tilesY = (uint)(mRaw.dim.y + tileh - 1) / tileh;
                             *  UInt32 nTiles = tilesX * tilesY;
                             *
                             *  Tag offsets = thumbIFD.getEntry(TagType.TILEOFFSETS);
                             *  Tag counts = thumbIFD.getEntry(TagType.TILEBYTECOUNTS);
                             *  if (offsets.dataCount != counts.dataCount || offsets.dataCount != nTiles)
                             *      throw new RawDecoderException("DNG Decoder: Tile count mismatch: offsets:" + offsets.dataCount + " count:" + counts.dataCount + ", calculated:" + nTiles);
                             *
                             *  slices.mFixLjpeg = mFixLjpeg;
                             *
                             *  for (UInt32 y = 0; y < tilesY; y++)
                             *  {
                             *      for (UInt32 x = 0; x < tilesX; x++)
                             *      {
                             *          DngSliceElement e = new DngSliceElement(offsets.getUInt(x + y * tilesX), counts.getUInt(x + y * tilesX), tilew * x, tileh * y);
                             *          e.mUseBigtable = tilew * tileh > 1024 * 1024;
                             *          slices.addSlice(e);
                             *      }
                             *  }
                             * }
                             * else
                             * {  // Strips
                             *  Tag offsets = thumbIFD.getEntry(TagType.STRIPOFFSETS);
                             *  Tag counts = thumbIFD.getEntry(TagType.STRIPBYTECOUNTS);
                             *
                             *  UInt32 yPerSlice = thumbIFD.getEntry(TagType.ROWSPERSTRIP).getUInt();
                             *
                             *  if (counts.dataCount != offsets.dataCount)
                             *  {
                             *      throw new RawDecoderException("DNG Decoder: Byte count number does not match strip size: count:" + counts.dataCount + ", stips:" + offsets.dataCount);
                             *  }
                             *
                             *  if (yPerSlice == 0 || yPerSlice > (UInt32)dim.y)
                             *      throw new RawDecoderException("DNG Decoder: Invalid y per slice");
                             *
                             *  UInt32 offY = 0;
                             *  for (UInt32 s = 0; s < counts.dataCount; s++)
                             *  {
                             *      DngSliceElement e = new DngSliceElement(offsets.getUInt(s), counts.getUInt(s), 0, offY);
                             *      e.mUseBigtable = yPerSlice * mRaw.dim.y > 1024 * 1024;
                             *      offY += yPerSlice;
                             *
                             *      if (mFile.isValid(e.byteOffset, e.byteCount)) // Only decode if size is valid
                             *          slices.addSlice(e);
                             *  }
                             * }
                             * UInt32 nSlices = (uint)slices.slices.Count;
                             * if (nSlices == 0)
                             *  throw new RawDecoderException("DNG Decoder: No valid slices found.");
                             *
                             * slices.decodeSlice();
                             */
                        }
                    }
                }
            }
            catch (Exception)
            {
                //thumbnail are optional so ignore all exception
            }
            return(null);
        }
Beispiel #16
0
        protected override RawImage decodeRawInternal()
        {
            List <IFD> data = mRootIFD.getIFDsWithTag(TagType.COMPRESSION);

            if (data.Count == 0)
            {
                throw new RawDecoderException("DNG Decoder: No image data found");
            }

            // Erase the ones not with JPEG compression
            for (int k = data.Count - 1; k >= 0; k--)
            {
                IFD  i            = data[k];
                int  comp         = i.getEntry(TagType.COMPRESSION).getShort(0);
                bool isSubsampled = false;
                try
                {
                    isSubsampled = (i.getEntry(TagType.NEWSUBFILETYPE).getInt() & 1) != 0; // bit 0 is on if image is subsampled
                }
                catch (TiffParserException) { }
                if ((comp != 7 && comp != 1 && comp != 0x884c) || isSubsampled)
                {  // Erase if subsampled, or not JPEG or uncompressed
                    data.Remove(i);
                }
            }

            if (data.Count == 0)
            {
                throw new RawDecoderException("DNG Decoder: No RAW chunks found");
            }

            /*
             * if (data.size() > 1)
             * {
             *  _RPT0(0, "Multiple RAW chunks found - using first only!");
             * }*/

            IFD    raw           = data[0];
            UInt32 sample_format = 1;
            UInt32 bps           = raw.getEntry(TagType.BITSPERSAMPLE).getUInt();

            if (raw.hasEntry(TagType.SAMPLEFORMAT))
            {
                sample_format = raw.getEntry(TagType.SAMPLEFORMAT).getUInt();
            }

            if (sample_format != 1)
            {
                throw new RawDecoderException("DNG Decoder: Only 16 bit unsigned data supported.");
            }

            mRaw.isCFA = (raw.getEntry(TagType.PHOTOMETRICINTERPRETATION).getUShort() == 32803);

            /*
             * if (mRaw.isCFA)
             *  _RPT0(0, "This is a CFA image\n");
             * else
             *  _RPT0(0, "This is NOT a CFA image\n");
             */

            if (sample_format == 1 && bps > 16)
            {
                throw new RawDecoderException("DNG Decoder: Integer precision larger than 16 bits currently not supported.");
            }

            if (sample_format == 3 && bps != 32)
            {
                throw new RawDecoderException("DNG Decoder: Float point must be 32 bits per sample.");
            }

            try
            {
                mRaw.dim   = new iPoint2D();
                mRaw.dim.x = raw.getEntry(TagType.IMAGEWIDTH).getInt();
                mRaw.dim.y = raw.getEntry(TagType.IMAGELENGTH).getInt();
            }
            catch (TiffParserException)
            {
                throw new RawDecoderException("DNG Decoder: Could not read basic image information.");
            }

            //init the raw image
            mRaw.Init();
            mRaw.colorDepth = (ushort)bps;
            int compression = -1;

            try
            {
                compression = raw.getEntry(TagType.COMPRESSION).getShort();
                if (mRaw.isCFA)
                {
                    // Check if layout is OK, if present
                    if (raw.hasEntry(TagType.CFALAYOUT))
                    {
                        if (raw.getEntry(TagType.CFALAYOUT).getShort() != 1)
                        {
                            throw new RawDecoderException("DNG Decoder: Unsupported CFA Layout.");
                        }
                    }

                    Tag cfadim = raw.getEntry(TagType.CFAREPEATPATTERNDIM);
                    if (cfadim.dataCount != 2)
                    {
                        throw new RawDecoderException("DNG Decoder: Couldn't read CFA pattern dimension");
                    }
                    Tag pDim = raw.getEntry(TagType.CFAREPEATPATTERNDIM); // Get the size
                    var cPat = raw.getEntry(TagType.CFAPATTERN).data;     // Does NOT contain dimensions as some documents state

                    /*
                     *    if (raw.hasEntry(CFAPLANECOLOR)) {
                     *      Tag e = raw.getEntry(CFAPLANECOLOR);
                     *      unsigned stringcPlaneOrder = e.getData();       // Map from the order in the image, to the position in the CFA
                     *      printf("Planecolor: ");
                     *      for (UInt32 i = 0; i < e.count; i++) {
                     *        printf("%u,",cPlaneOrder[i]);
                     *      }
                     *      printf("\n");
                     *    }
                     */
                    iPoint2D cfaSize = new iPoint2D(pDim.getInt(1), pDim.getInt(0));
                    mRaw.cfa.setSize(cfaSize);
                    if (cfaSize.area() != raw.getEntry(TagType.CFAPATTERN).dataCount)
                    {
                        throw new RawDecoderException("DNG Decoder: CFA pattern dimension and pattern count does not match: " + raw.getEntry(TagType.CFAPATTERN).dataCount);
                    }

                    for (int y = 0; y < cfaSize.y; y++)
                    {
                        for (int x = 0; x < cfaSize.x; x++)
                        {
                            UInt32   c1 = Convert.ToUInt32(cPat[x + y * cfaSize.x]);
                            CFAColor c2;
                            switch (c1)
                            {
                            case 0:
                                c2 = CFAColor.RED; break;

                            case 1:
                                c2 = CFAColor.GREEN; break;

                            case 2:
                                c2 = CFAColor.BLUE; break;

                            case 3:
                                c2 = CFAColor.CYAN; break;

                            case 4:
                                c2 = CFAColor.MAGENTA; break;

                            case 5:
                                c2 = CFAColor.YELLOW; break;

                            case 6:
                                c2 = CFAColor.WHITE; break;

                            default:
                                c2 = CFAColor.UNKNOWN;
                                throw new RawDecoderException("DNG Decoder: Unsupported CFA Color.");
                            }
                            mRaw.cfa.setColorAt(new iPoint2D(x, y), c2);
                        }
                    }
                }

                // Now load the image
                if (compression == 1)
                {  // Uncompressed.
                    try
                    {
                        UInt32 cpp = raw.getEntry(TagType.SAMPLESPERPIXEL).getUInt();
                        if (cpp > 4)
                        {
                            throw new RawDecoderException("DNG Decoder: More than 4 samples per pixel is not supported.");
                        }
                        mRaw.cpp = cpp;

                        Tag    offsets   = raw.getEntry(TagType.STRIPOFFSETS);
                        Tag    counts    = raw.getEntry(TagType.STRIPBYTECOUNTS);
                        UInt32 yPerSlice = raw.getEntry(TagType.ROWSPERSTRIP).getUInt();
                        UInt32 width     = raw.getEntry(TagType.IMAGEWIDTH).getUInt();
                        UInt32 height    = raw.getEntry(TagType.IMAGELENGTH).getUInt();

                        if (counts.dataCount != offsets.dataCount)
                        {
                            throw new RawDecoderException("DNG Decoder: Byte count number does not match strip size: count:" + counts.dataCount + ", strips:" + offsets.dataCount);
                        }

                        UInt32          offY   = 0;
                        List <DngStrip> slices = new List <DngStrip>();
                        for (UInt32 s = 0; s < offsets.dataCount; s++)
                        {
                            DngStrip slice = new DngStrip();
                            slice.offset  = offsets.getUInt(s);
                            slice.count   = counts.getUInt(s);
                            slice.offsetY = offY;
                            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);
                            }
                        }

                        for (int i = 0; i < slices.Count; i++)
                        {
                            DngStrip         slice = slices[i];
                            TIFFBinaryReader input = new TIFFBinaryReader(mFile.BaseStream, slice.offset, (uint)mFile.BaseStream.Length);
                            iPoint2D         size  = new iPoint2D((int)width, (int)slice.h);
                            iPoint2D         pos   = new iPoint2D(0, (int)slice.offsetY);

                            bool big_endian = (raw.endian == Endianness.big);
                            // DNG spec says that if not 8 or 16 bit/sample, always use big endian
                            if (bps != 8 && bps != 16)
                            {
                                big_endian = true;
                            }
                            try
                            {
                                readUncompressedRaw(ref input, size, pos, (int)(mRaw.cpp * width * bps / 8), (int)bps, big_endian ? BitOrder.Jpeg : BitOrder.Plain);
                            }
                            catch (IOException ex)
                            {
                                if (i > 0)
                                {
                                    mRaw.errors.Add(ex.Message);
                                }
                                else
                                {
                                    throw new RawDecoderException("DNG decoder: IO error occurred in first slice, unable to decode more. Error is: " + ex.Message);
                                }
                            }
                        }
                    }
                    catch (TiffParserException)
                    {
                        throw new RawDecoderException("DNG Decoder: Unsupported format, uncompressed with no strips.");
                    }
                }
                else if (compression == 7 || compression == 0x884c)
                {
                    try
                    {
                        // Let's try loading it as tiles instead

                        mRaw.cpp = (raw.getEntry(TagType.SAMPLESPERPIXEL).getUInt());

                        if (sample_format != 1)
                        {
                            throw new RawDecoderException("DNG Decoder: Only 16 bit unsigned data supported for compressed data.");
                        }

                        DngDecoderSlices slices = new DngDecoderSlices(mFile, mRaw, compression);
                        if (raw.hasEntry(TagType.TILEOFFSETS))
                        {
                            UInt32 tilew = raw.getEntry(TagType.TILEWIDTH).getUInt();
                            UInt32 tileh = raw.getEntry(TagType.TILELENGTH).getUInt();
                            if (tilew == 0 || tileh == 0)
                            {
                                throw new RawDecoderException("DNG Decoder: Invalid tile size");
                            }

                            UInt32 tilesX = (uint)(mRaw.dim.x + tilew - 1) / tilew;
                            UInt32 tilesY = (uint)(mRaw.dim.y + tileh - 1) / tileh;
                            UInt32 nTiles = tilesX * tilesY;

                            Tag offsets = raw.getEntry(TagType.TILEOFFSETS);
                            Tag counts  = raw.getEntry(TagType.TILEBYTECOUNTS);
                            if (offsets.dataCount != counts.dataCount || offsets.dataCount != nTiles)
                            {
                                throw new RawDecoderException("DNG Decoder: Tile count mismatch: offsets:" + offsets.dataCount + " count:" + counts.dataCount + ", calculated:" + nTiles);
                            }

                            slices.mFixLjpeg = mFixLjpeg;

                            for (UInt32 y = 0; y < tilesY; y++)
                            {
                                for (UInt32 x = 0; x < tilesX; x++)
                                {
                                    DngSliceElement e = new DngSliceElement(offsets.getUInt(x + y * tilesX), counts.getUInt(x + y * tilesX), tilew * x, tileh * y);
                                    e.mUseBigtable = tilew * tileh > 1024 * 1024;
                                    slices.addSlice(e);
                                }
                            }
                        }
                        else
                        {  // Strips
                            Tag offsets = raw.getEntry(TagType.STRIPOFFSETS);
                            Tag counts  = raw.getEntry(TagType.STRIPBYTECOUNTS);

                            UInt32 yPerSlice = raw.getEntry(TagType.ROWSPERSTRIP).getUInt();

                            if (counts.dataCount != offsets.dataCount)
                            {
                                throw new RawDecoderException("DNG Decoder: Byte count number does not match strip size: count:" + counts.dataCount + ", stips:" + offsets.dataCount);
                            }

                            if (yPerSlice == 0 || yPerSlice > (UInt32)mRaw.dim.y)
                            {
                                throw new RawDecoderException("DNG Decoder: Invalid y per slice");
                            }

                            UInt32 offY = 0;
                            for (UInt32 s = 0; s < counts.dataCount; s++)
                            {
                                DngSliceElement e = new DngSliceElement(offsets.getUInt(s), counts.getUInt(s), 0, offY);
                                e.mUseBigtable = yPerSlice * mRaw.dim.y > 1024 * 1024;
                                offY          += yPerSlice;

                                if (mFile.isValid(e.byteOffset, e.byteCount)) // Only decode if size is valid
                                {
                                    slices.addSlice(e);
                                }
                            }
                        }
                        UInt32 nSlices = (uint)slices.slices.Count;
                        if (nSlices == 0)
                        {
                            throw new RawDecoderException("DNG Decoder: No valid slices found.");
                        }

                        slices.decodeSlice();

                        if (mRaw.errors.Count >= nSlices)
                        {
                            throw new RawDecoderException("DNG Decoding: Too many errors encountered. Giving up.\nFirst Error:" + mRaw.errors[0]);
                        }
                    }
                    catch (TiffParserException e)
                    {
                        throw new RawDecoderException("DNG Decoder: Unsupported format, tried strips and tiles:" + e.Message);
                    }
                }
                else
                {
                    throw new RawDecoderException("DNG Decoder: Unknown compression: " + compression);
                }
            }
            catch (TiffParserException e)
            {
                throw new RawDecoderException("DNG Decoder: Image could not be read:" + e.Message);
            }

            Tag as_shot_neutral = mRootIFD.getEntryRecursive(TagType.ASSHOTNEUTRAL);

            if (as_shot_neutral != null)
            {
                if (as_shot_neutral.dataCount == 3)
                {
                    for (UInt32 i = 0; i < 3; i++)
                    {
                        mRaw.metadata.wbCoeffs[i] = 1.0f / Convert.ToSingle(as_shot_neutral.data[i]);
                    }
                }
            }
            else
            {
                Tag as_shot_white_xy = mRootIFD.getEntryRecursive(TagType.ASSHOTWHITEXY);
                if (as_shot_white_xy != null)
                {
                    if (as_shot_white_xy.dataCount == 2)
                    {
                        mRaw.metadata.wbCoeffs[0] = as_shot_white_xy.getFloat(0);
                        mRaw.metadata.wbCoeffs[1] = as_shot_white_xy.getFloat(1);
                        mRaw.metadata.wbCoeffs[2] = 1 - mRaw.metadata.wbCoeffs[0] - mRaw.metadata.wbCoeffs[1];

                        float[] d65_white = { 0.950456F, 1, 1.088754F };
                        for (UInt32 i = 0; i < 3; i++)
                        {
                            mRaw.metadata.wbCoeffs[i] /= d65_white[i];
                        }
                    }
                }
            }


            // Crop
            Tag active_area = raw.getEntry(TagType.ACTIVEAREA);

            if (active_area != null)
            {
                iPoint2D new_size = new iPoint2D(mRaw.dim.x, mRaw.dim.y);
                if (active_area.dataCount != 4)
                {
                    throw new RawDecoderException("DNG: active area has " + active_area.dataCount + " values instead of 4");
                }

                active_area.getIntArray(out int[] corners, 4);
                if (new iPoint2D(corners[1], corners[0]).isThisInside(mRaw.dim))
                {
                    if (new iPoint2D(corners[3], corners[2]).isThisInside(mRaw.dim))
                    {
                        iRectangle2D crop = new iRectangle2D(corners[1], corners[0], corners[3] - corners[1], corners[2] - corners[0]);
                        mRaw.subFrame(crop);
                    }
                }
            }



            Tag origin_entry = raw.getEntry(TagType.DEFAULTCROPORIGIN);
            Tag size_entry   = raw.getEntry(TagType.DEFAULTCROPSIZE);

            if (origin_entry != null && size_entry != null)
            {
                iRectangle2D cropped = new iRectangle2D(0, 0, mRaw.dim.x, mRaw.dim.y);
                /* Read crop position (sometimes is rational so use float) */
                origin_entry.getFloatArray(out float[] tl, 2);
                if (new iPoint2D((int)tl[0], (int)tl[1]).isThisInside(mRaw.dim))
                {
                    cropped = new iRectangle2D((int)tl[0], (int)tl[1], 0, 0);
                }

                cropped.dim = mRaw.dim - cropped.pos;
                /* Read size (sometimes is rational so use float) */

                size_entry.getFloatArray(out float[] sz, 2);
                iPoint2D size = new iPoint2D((int)sz[0], (int)sz[1]);
                if ((size + cropped.pos).isThisInside(mRaw.dim))
                {
                    cropped.dim = size;
                }

                if (!cropped.hasPositiveArea())
                {
                    throw new RawDecoderException("DNG Decoder: No positive crop area");
                }

                mRaw.subFrame(cropped);
                if (mRaw.isCFA && cropped.pos.x % 2 == 1)
                {
                    mRaw.cfa.shiftLeft(1);
                }
                if (mRaw.isCFA && cropped.pos.y % 2 == 1)
                {
                    mRaw.cfa.shiftDown(1);
                }
            }
            if (mRaw.dim.area() <= 0)
            {
                throw new RawDecoderException("DNG Decoder: No image left after crop");
            }


            // Apply stage 1 opcodes
            if (applyStage1DngOpcodes)
            {
                if (raw.hasEntry(TagType.OPCODELIST1))
                {
                    // Apply stage 1 codes
                    try
                    {
                        //DngOpcodes codes = new DngOpcodes(raw.getEntry(TagType.OPCODELIST1));
                        //mRaw = codes.applyOpCodes(mRaw);
                    }
                    catch (RawDecoderException e)
                    {
                        // We push back errors from the opcode parser, since the image may still be usable
                        mRaw.errors.Add(e.Message);
                    }
                }
            }

            // Linearization
            Tag lintable = raw.getEntry(TagType.LINEARIZATIONTABLE);

            if (lintable != null)
            {
                UInt32 len = lintable.dataCount;
                lintable.getShortArray(out ushort[] table, (int)len);
                mRaw.setTable(table, (int)len, !uncorrectedRawValues);
                if (!uncorrectedRawValues)
                {
                    //TODO Fix
                    //mRaw.sixteenBitLookup();
                    //mRaw.table = (null);
                }
            }

            // Default white level is (2 ** BitsPerSample) - 1
            mRaw.whitePoint = (uint)(1 >> raw.getEntry(TagType.BITSPERSAMPLE).getShort()) - 1;


            Tag whitelevel = raw.getEntry(TagType.WHITELEVEL);

            try
            {
                mRaw.whitePoint = whitelevel.getUInt();
            }
            catch (Exception) { }

            // Set black
            setBlack(raw);

            //convert to linear value
            //*
            //TODO optimize (super slow)
            double maxVal = Math.Pow(2, mRaw.colorDepth);
            double coeff  = maxVal / (mRaw.whitePoint - mRaw.blackLevelSeparate[0]);

            Parallel.For(mRaw.mOffset.y, mRaw.dim.y + mRaw.mOffset.y, y =>
                         //for (int y = mRaw.mOffset.y; y < mRaw.dim.y + mRaw.mOffset.y; y++)
            {
                //int offset = ((y % 2) * 2);
                int realY = y * mRaw.dim.x;
                for (int x = mRaw.mOffset.x; x < mRaw.dim.x + mRaw.mOffset.x; x++)
                {
                    int pos = realY + x;
                    double val;
                    //Linearisation
                    if (mRaw.table != null)
                    {
                        val = mRaw.table.tables[mRaw.rawData[pos]];
                    }
                    else
                    {
                        val = mRaw.rawData[pos];
                    }
                    //Black sub
                    //val -= mRaw.blackLevelSeparate[offset + x % 2];
                    val -= mRaw.blackLevelSeparate[0];
                    //Rescaling
                    //val /= (mRaw.whitePoint - mRaw.blackLevelSeparate[offset + x % 2]);
                    val *= coeff; //change to take into consideration each individual blacklevel
                                  //Clip
                    if (val > maxVal)
                    {
                        val = maxVal;
                    }
                    else if (val < 0)
                    {
                        val = 0;
                    }
                    //val *= maxVal;
                    //rescale to colordepth of the original
                    mRaw.rawData[pos] = (ushort)val;
                }
            });
            //*/
            // Apply opcodes to lossy DNG
            if (compression == 0x884c && !uncorrectedRawValues)
            {
                /*
                 * if (raw.hasEntry(TagType.OPCODELIST2))
                 * {
                 *  // We must apply black/white scaling
                 *  mRaw.scaleBlackWhite();
                 *  // Apply stage 2 codes
                 *  try
                 *  {
                 *      DngOpcodes codes = new DngOpcodes(raw.getEntry(TagType.OPCODELIST2));
                 *      mRaw = codes.applyOpCodes(mRaw);
                 *  }
                 *  catch (RawDecoderException e)
                 *  {
                 *      // We push back errors from the opcode parser, since the image may still be usable
                 *      mRaw.errors.Add(e.Message);
                 *  }
                 *  mRaw.blackAreas.Clear();
                 *  mRaw.blackLevel = 0;
                 *  mRaw.blackLevelSeparate[0] = mRaw.blackLevelSeparate[1] = mRaw.blackLevelSeparate[2] = mRaw.blackLevelSeparate[3] = 0;
                 *  mRaw.whitePoint = 65535;
                 * }*/
            }
            return(mRaw);
        }
        public void startDecoder(UInt32 offset, UInt32 size, UInt32 offsetX, UInt32 offsetY)
        {
            if (!input.isValid(offset, size))
            {
                throw new Exception("startDecoder: Start offset plus size is longer than file. Truncated file.");
            }
            if ((int)offsetX >= mRaw.dim.x)
            {
                throw new Exception("startDecoder: X offset outside of image");
            }
            if ((int)offsetY >= mRaw.dim.y)
            {
                throw new Exception("startDecoder: Y offset outside of image");
            }
            offX = offsetX;
            offY = offsetY;

            try
            {
                Endianness host_endian = Common.getHostEndianness();
                // JPEG is big endian
                if (host_endian == Endianness.big)
                {
                    input = new TIFFBinaryReader(input.BaseStream, offset, size);
                }
                else
                {
                    input = new TIFFBinaryReaderRE(input.BaseStream, offset, size);
                }

                if (getNextMarker(false) != JpegMarker.M_SOI)
                {
                    throw new Exception("startDecoder: Image did not start with SOI. Probably not an LJPEG");
                }
                //    _RPT0(0,"Found SOI marker\n");

                bool moreImage = true;
                while (moreImage)
                {
                    JpegMarker m = getNextMarker(true);

                    switch (m)
                    {
                    case JpegMarker.M_SOS:
                        //          _RPT0(0,"Found SOS marker\n");
                        parseSOS();
                        break;

                    case JpegMarker.M_EOI:
                        //          _RPT0(0,"Found EOI marker\n");
                        moreImage = false;
                        break;

                    case JpegMarker.M_DHT:
                        //          _RPT0(0,"Found DHT marker\n");
                        parseDHT();
                        break;

                    case JpegMarker.M_DQT:
                        throw new Exception("LJpegDecompressor: Not a valid RAW file.");

                    case JpegMarker.M_DRI:
                        //          _RPT0(0,"Found DRI marker\n");
                        break;

                    case JpegMarker.M_APP0:
                        //          _RPT0(0,"Found APP0 marker\n");
                        break;

                    case JpegMarker.M_SOF3:
                        //          _RPT0(0,"Found SOF 3 marker:\n");
                        parseSOF(frame);
                        break;

                    default:      // Just let it skip to next marker
                                  // _RPT1(0, "Found marker:0x%x. Skipping\n", m);
                        break;
                    }
                }
            }
            catch (IOException)
            {
                throw;
            }
        }
Beispiel #18
0
        /* 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;
            }
        }
Beispiel #19
0
        protected override void decodeRawInternal()
        {
            UInt32 width = 0, height = 0, filesize = 0, bits = 0, offset = 0;

            if (cam.hints.TryGetValue("full_width", out string tmp))
            {
                width = UInt32.Parse(tmp);
            }
            else
            {
                throw new RawDecoderException("Naked: couldn't ContainsKey width");
            }

            if (cam.hints.TryGetValue("full_height", out tmp))
            {
                height = UInt32.Parse(tmp);
            }
            else
            {
                throw new RawDecoderException("Naked: couldn't ContainsKey height");
            }

            if (cam.hints.TryGetValue("filesize", out tmp))
            {
                filesize = UInt32.Parse(tmp);
            }
            else
            {
                throw new RawDecoderException("Naked: couldn't ContainsKey filesize");
            }

            if (cam.hints.TryGetValue("offset", out tmp))
            {
                offset = UInt32.Parse(tmp);
            }

            if (cam.hints.TryGetValue("bits", out tmp))
            {
                bits = UInt32.Parse(tmp);
            }
            else
            {
                bits = (filesize - offset) * 8 / width / height;
            }

            BitOrder bo = BitOrder.Jpeg16;  // Default

            if (cam.hints.TryGetValue("order", out tmp))
            {
                if (tmp == "plain")
                {
                    bo = BitOrder.Plain;
                }
                else if (tmp == "jpeg")
                {
                    bo = BitOrder.Jpeg;
                }
                else if (tmp == "jpeg16")
                {
                    bo = BitOrder.Jpeg16;
                }
                else if (tmp == "jpeg32")
                {
                    bo = BitOrder.Jpeg32;
                }
            }

            rawImage.dim = new Point2D((int)width, (int)height);
            rawImage.Init();
            reader = new TIFFBinaryReader(reader.BaseStream, offset, (uint)reader.BaseStream.Length);
            Point2D pos = new Point2D(0, 0);

            readUncompressedRaw(ref reader, rawImage.dim, pos, (int)(width * bits / 8), (int)bits, bo);
        }
Beispiel #20
0
        /* 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);
        }
Beispiel #21
0
        IFD parseDngPrivateData(Tag t)
        {
            /*
             * 1. Six bytes containing the zero-terminated string "Adobe". (The DNG specification calls for the DNGPrivateData tag to start with an ASCII string identifying the creator/format).
             * 2. 4 bytes: an ASCII string ("MakN" for a Makernote),  indicating what sort of data is being stored here. Note that this is not zero-terminated.
             * 3. A four-byte count (number of data bytes following); this is the length of the original MakerNote data. (This is always in "most significant byte first" format).
             * 4. 2 bytes: the byte-order indicator from the original file (the usual 'MM'/4D4D or 'II'/4949).
             * 5. 4 bytes: the original file offset for the MakerNote tag data (stored according to the byte order given above).
             * 6. The contents of the MakerNote tag. This is a simple byte-for-byte copy, with no modification.
             */
            uint size = t.dataCount;

            Common.ConvertArray(ref t.data, out byte[] data);
            Common.ByteToChar(ref data, out char[] dataAsChar);
            string id = new String(dataAsChar);

            if (!id.StartsWith("Adobe"))
            {
                Debug.WriteLine("Not Adobe Private data");
                return(null);
            }

            if (!(data[6] == 'M' && data[7] == 'a' && data[8] == 'k' && data[9] == 'N'))
            {
                Debug.WriteLine("Not Makernote");
                return(null);
            }

            data = data.Skip(10).ToArray();
            uint count;

            count = (uint)data[0] << 24 | (uint)data[1] << 16 | (uint)data[2] << 8 | data[3];

            data = data.Skip(4).ToArray();
            if (count > size)
            {
                Debug.WriteLine("Error reading TIFF structure (invalid size). File Corrupt");
                return(null);
            }
            Endianness makernote_endian = Endianness.unknown;

            if (data[0] == 0x49 && data[1] == 0x49)
            {
                makernote_endian = Endianness.little;
            }
            else if (data[0] == 0x4D && data[1] == 0x4D)
            {
                makernote_endian = Endianness.big;
            }
            else
            {
                Debug.WriteLine("Cannot determine endianess of DNG makernote");
                return(null);
            }
            data = data.Skip(2).ToArray();
            uint org_offset;


            org_offset = (uint)data[0] << 24 | (uint)data[1] << 16 | (uint)data[2] << 8 | data[3];

            data = data.Skip(4).ToArray();
            /* We don't parse original makernotes that are placed after 300MB mark in the original file */
            if (org_offset + count > 300 * 1024 * 1024)
            {
                Debug.WriteLine("Adobe Private data: original offset of makernote is past 300MB offset");
                return(null);
            }
            /* Create fake tiff with original offsets */
            //byte[] maker_data = new byte[count];
            // Common.memcopy(ref maker_data, ref data, count, 0, 0);
            TIFFBinaryReader maker_map = new TIFFBinaryReader(TIFFBinaryReader.streamFromArray(data));

            IFD maker_ifd;

            try
            {
                maker_ifd = parseMakerNote(maker_map, 0, makernote_endian);
            }
            catch (TiffParserException e)
            {
                Debug.WriteLine(e.Message);
                return(null);
            }
            return(maker_ifd);
        }
Beispiel #22
0
        /* Attempt to decode the image */

        /* A RawDecoderException will be thrown if the image cannot be decoded
         * public void readUncompressedRaw(ref TIFFBinaryReader input, iPoint2D size, iPoint2D offset, int inputPitch, int bitPerPixel, BitOrder order)
         * {
         *  UInt32 outPitch = mRaw.pitch;
         *  uint w = (uint)size.x;
         *  uint h = (uint)size.y;
         *  UInt32 cpp = mRaw.cpp;
         *  UInt64 ox = (ulong)offset.x;
         *  UInt64 oy = (ulong)offset.y;
         *  if (this.mRaw.rawData == null)
         *  {
         *      mRaw.rawData = new ushort[w * h * cpp];
         *  }
         *  if (input.getRemainSize() < (inputPitch * (int)h))
         *  {
         *      if (input.getRemainSize() > inputPitch)
         *      {
         *          h = (uint)(input.getRemainSize() / inputPitch - 1);
         *          mRaw.errors.Add("Image truncated (file is too short)");
         *      }
         *      else
         *          throw new IOException("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
         *  }
         *  if (bitPerPixel > 16)
         *      throw new RawDecoderException("readUncompressedRaw: Unsupported bit depth");
         *
         *  UInt32 skipBits = (uint)(inputPitch - (int)w * cpp * bitPerPixel / 8);  // Skip per line
         *  if (oy > (ulong)mRaw.dim.y)
         *      throw new RawDecoderException("readUncompressedRaw: Invalid y offset");
         *  if (ox + (ulong)size.x > (ulong)mRaw.dim.x)
         *      throw new RawDecoderException("readUncompressedRaw: Invalid x offset");
         *
         *  UInt64 y = oy;
         *  h = (uint)Math.Min(h + (uint)oy, mRaw.dim.y);
         *  /*
         *  if (mRaw.getDataType() == RawImageType.TYPE_FLOAT32)
         *  {
         *      if (bitPerPixel != 32)
         *          throw new RawDecoderException("readUncompressedRaw: Only 32 bit float point supported");
         *      BitBlt(&data[offset.x * sizeof(float) * cpp + y * outPitch], outPitch,
         *          input.getData(), inputPitch, w * mRaw.bpp, h - y);
         *      return;
         *  }
         *
         *  if (BitOrder.Jpeg == order)
         *  {
         *      BitPumpMSB bits = new BitPumpMSB(ref input);
         *      w *= cpp;
         *      for (; y < h; y++)
         *      {
         *          bits.checkPos();
         *          for (UInt32 x = 0; x < w; x++)
         *          {
         *              UInt32 b = bits.getBits((uint)bitPerPixel);
         *              mRaw.rawData[(((int)(offset.x * sizeof(UInt16) * cpp) + (int)y * (int)outPitch)) + x] = (ushort)b;
         *          }
         *          bits.skipBits(skipBits);
         *      }
         *  }
         *  else if (BitOrder.Jpeg16 == order)
         *  {
         *      BitPumpMSB16 bits = new BitPumpMSB16(input);
         *      w *= cpp;
         *      for (; y < h; y++)
         *      {
         *          bits.checkPos();
         *          for (UInt32 x = 0; x < w; x++)
         *          {
         *              UInt32 b = bits.getBits((uint)bitPerPixel);
         *              mRaw.rawData[(offset.x * sizeof(ushort) * (int)cpp + (int)y * (int)outPitch) + x] = (ushort)b;
         *          }
         *          bits.skipBits(skipBits);
         *      }
         *  }
         *  else if (BitOrder.Jpeg32 == order)
         *  {
         *      BitPumpMSB32 bits = new BitPumpMSB32(input);
         *      w *= cpp;
         *      for (; y < h; y++)
         *      {
         *          bits.checkPos();
         *          for (UInt32 x = 0; x < w; x++)
         *          {
         *              UInt32 b = bits.getBits((uint)bitPerPixel);
         *              mRaw.rawData[(offset.x * sizeof(ushort) * (int)cpp + (int)y * (int)outPitch) + x] = (ushort)b;
         *          }
         *          bits.skipBits(skipBits);
         *      }
         *  }
         *  else
         *  {
         *      if (bitPerPixel == 16)
         *      {
         *          Decode16BitRawUnpacked(input, w, h);
         *          return;
         *      }
         *      if (bitPerPixel == 12 && (int)w == inputPitch * 8 / 12)
         *      {
         *          Decode12BitRaw(input, w, h);
         *          return;
         *      }
         *      BitPumpPlain bits = new BitPumpPlain(input);
         *      w *= cpp;
         *      for (; y < h; y++)
         *      {
         *          bits.checkPos();
         *          for (UInt32 x = 0; x < w; x++)
         *          {
         *              UInt32 b = bits.getBits((uint)bitPerPixel);
         *              mRaw.rawData[(offset.x * sizeof(ushort) + (int)y * (int)outPitch) + x] = (ushort)b;
         *          }
         *          bits.skipBits(skipBits);
         *      }
         *  }
         * }
         */

        public unsafe void readUncompressedRaw(ref TIFFBinaryReader input, iPoint2D size, iPoint2D offset, int inputPitch, int bitPerPixel, BitOrder order)
        {
            fixed(ushort *d = mRaw.rawData)
            {
                byte *data     = (byte *)d;
                uint  outPitch = mRaw.pitch;
                int   w        = size.x;
                int   h        = size.y;
                uint  cpp      = mRaw.cpp;
                int   ox       = offset.x;
                int   oy       = offset.y;

                if (input.getRemainSize() < (inputPitch * h))
                {
                    if ((int)input.getRemainSize() > inputPitch)
                    {
                        h = input.getRemainSize() / inputPitch - 1;
                        mRaw.errors.Add("Image truncated (file is too short)");
                    }
                    else
                    {
                        throw new IOException("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
                    }
                }
                if (bitPerPixel > 16)
                {
                    throw new RawDecoderException("readUncompressedRaw: Unsupported bit depth");
                }

                uint skipBits = (uint)(inputPitch - w * cpp * bitPerPixel / 8);  // Skip per line

                if (oy > mRaw.dim.y)
                {
                    throw new RawDecoderException("readUncompressedRaw: Invalid y offset");
                }
                if (ox + size.x > mRaw.dim.x)
                {
                    throw new RawDecoderException("readUncompressedRaw: Invalid x offset");
                }

                int y = oy;

                h = (int)Math.Min(h + oy, (uint)mRaw.dim.y);

                /*if (mRaw.getDataType() == TYPE_FLOAT32)
                 * {
                 *  if (bitPerPixel != 32)
                 *      throw new RawDecoderException("readUncompressedRaw: Only 32 bit float point supported");
                 *  BitBlt(&data[offset.x * sizeof(float) * cpp + y * outPitch], outPitch,
                 *      input.getData(), inputPitch, w * mRaw.bpp, h - y);
                 *  return;
                 * }*/

                if (BitOrder.Jpeg == order)
                {
                    BitPumpMSB bits = new BitPumpMSB(ref input);
                    w *= (int)cpp;
                    for (; y < h; y++)
                    {
                        bits.checkPos();
                        for (uint x = 0; x < w; x++)
                        {
                            uint b = bits.getBits((uint)bitPerPixel);
                            mRaw.rawData[x + (offset.x * cpp + y * mRaw.dim.x * cpp)] = (ushort)b;
                        }
                        bits.skipBits(skipBits);
                    }
                }
                else if (BitOrder.Jpeg16 == order)
                {
                    BitPumpMSB16 bits = new BitPumpMSB16(ref input);
                    w *= (int)cpp;
                    for (; y < h; y++)
                    {
                        UInt16 *dest = (UInt16 *)&data[offset.x * sizeof(UInt16) * cpp + y * outPitch];
                        bits.checkPos();
                        for (uint x = 0; x < w; x++)
                        {
                            uint b = bits.getBits((uint)bitPerPixel);
                            dest[x] = (ushort)b;
                        }
                        bits.skipBits(skipBits);
                    }
                }
                else if (BitOrder.Jpeg32 == order)
                {
                    BitPumpMSB32 bits = new BitPumpMSB32(ref input);
                    w *= (int)cpp;
                    for (; y < h; y++)
                    {
                        UInt16 *dest = (UInt16 *)&data[offset.x * sizeof(UInt16) * cpp + y * outPitch];
                        bits.checkPos();
                        for (uint x = 0; x < w; x++)
                        {
                            uint b = bits.getBits((uint)bitPerPixel);
                            dest[x] = (ushort)b;
                        }
                        bits.skipBits(skipBits);
                    }
                }
                else
                {
                    if (bitPerPixel == 16 && Common.getHostEndianness() == Endianness.little)
                    {
                        Decode16BitRawUnpacked(input, (uint)w, (uint)h);
                        return;
                    }
                    if (bitPerPixel == 12 && (int)w == inputPitch * 8 / 12 && Common.getHostEndianness() == Endianness.little)
                    {
                        Decode12BitRaw(input, (uint)w, (uint)h);
                        return;
                    }
                    BitPumpPlain bits = new BitPumpPlain(ref input);
                    w *= (int)cpp;
                    for (; y < h; y++)
                    {
                        UInt16 *dest = (UInt16 *)&data[offset.x * sizeof(UInt16) + y * outPitch];
                        bits.checkPos();
                        for (uint x = 0; x < w; x++)
                        {
                            uint b = bits.getBits((uint)bitPerPixel);
                            dest[x] = (ushort)b;
                        }
                        bits.skipBits(skipBits);
                    }
                }
            }
        }
Beispiel #23
0
 public LJpegPlain(TIFFBinaryReader file, RawImage img) : base(file, img)
 {
 }
Beispiel #24
0
 public IFD(TIFFBinaryReader fileStream, uint offset, Endianness endian, int depth) :
     this(fileStream, offset, endian)
 {
     this.depth = depth;
 }
Beispiel #25
0
 public TiffDecoder(IFD rootifd, ref TIFFBinaryReader file) : base(ref file)
 {
     decoderVersion = 1;
     ifd            = rootifd;
     //check if no
 }
Beispiel #26
0
 /*** Used for entropy encoded sections ***/
 public BitPumpMSB(ref TIFFBinaryReader s) : this(ref s, (uint)s.Position, (uint)s.BaseStream.Length)
 {
 }
Beispiel #27
0
 public JPGParser(TIFFBinaryReader file) : base(ref file)
 {
 }
Beispiel #28
0
        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 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);
            }
        }
Beispiel #30
0
        int MIN_GET_BITS;// = (BITS_PER_LONG - 7);  /* max value for long getBuffer */

        public BitPumpPlain(ref TIFFBinaryReader s)
        {
            MIN_GET_BITS = (BITS_PER_LONG - 7);
            s.Read(buffer, (int)s.Position, (int)s.BaseStream.Length);
            size = (uint)(8 * s.getRemainSize());
        }