Example #1
0
        void DecodeUncompressed(IFD raw)
        {
            uint width  = raw.GetEntry(TagType.IMAGEWIDTH).GetUInt(0);
            uint height = raw.GetEntry(TagType.IMAGELENGTH).GetUInt(0);
            uint off    = raw.GetEntry(TagType.STRIPOFFSETS).GetUInt(0);

            rawImage.fullSize.dim = new Point2D(width, height);
            rawImage.Init(false);
            ImageBinaryReader input = new ImageBinaryReader(reader.BaseStream, off);

            /*
             *  RawDecompressor.Decode14BitRawBEunpacked(input, width, height, rawImage);
             */
            RawDecompressor.Decode16BitRawUnpacked(input, new Point2D(width, height), new Point2D(), rawImage);
        }
Example #2
0
        public override void DecodeRaw()
        {
            List <IFD> data = ifd.GetIFDsWithTag(TagType.STRIPOFFSETS);

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

            IFD raw = data[0];

            int compression = raw.GetEntry(TagType.COMPRESSION).GetInt(0);

            if (1 == compression || compression == 32773)
            {
                DecodeUncompressed(raw, BitOrder.Jpeg);
                return;
            }

            if (65535 != compression)
            {
                throw new RawDecoderException("Unsupported compression");
            }

            Tag offsets = raw.GetEntry(TagType.STRIPOFFSETS);
            Tag counts  = raw.GetEntry(TagType.STRIPBYTECOUNTS);

            if (offsets.dataCount != 1)
            {
                throw new RawDecoderException("Multiple Strips found: " + offsets.dataCount);
            }
            if (counts.dataCount != offsets.dataCount)
            {
                throw new RawDecoderException("Byte count number does not match strip size: count:" + counts.dataCount + ", strips:" + offsets.dataCount);
            }
            if (!reader.IsValid(offsets.GetUInt(0), counts.GetUInt(0)))
            {
                throw new RawDecoderException("Truncated file.");
            }

            rawImage.fullSize.dim = new Point2D(raw.GetEntry(TagType.IMAGEWIDTH).GetUInt(0), raw.GetEntry(TagType.IMAGELENGTH).GetUInt(0));
            rawImage.Init(false);
            PentaxDecompressor l = new PentaxDecompressor(reader, rawImage);

            l.DecodePentax(ifd, offsets.GetUInt(0), counts.GetUInt(0));
            reader.Dispose();
        }
Example #3
0
 void SetBlack(IFD raw)
 {
     if (raw.tags.ContainsKey(TagType.MASKEDAREAS))
     {
         if (DecodeMaskedAreas(raw))
         {
             return;
         }
     }
     if (raw.GetEntry(TagType.BLACKLEVEL) != null)
     {
         Decodeblacks(raw);
     }
 }
Example #4
0
        /* Decodes DNG masked areas into blackareas in the image */
        bool DecodeMaskedAreas(IFD raw)
        {
            Tag masked = raw.GetEntry(TagType.MASKEDAREAS);

            if (masked.dataType != TiffDataType.SHORT && masked.dataType != TiffDataType.LONG)
            {
                return(false);
            }

            Int32 nrects = (int)masked.dataCount / 4;

            if (0 == nrects)
            {
                return(false);
            }

            /* Since we may both have short or int, copy it to int array. */
            var rects = masked.GetUIntArray();

            Point2D top = rawImage.fullSize.offset;

            for (int i = 0; i < nrects; i++)
            {
                Point2D topleft     = new Point2D(rects[i * 4 + 1], rects[i * 4]);
                Point2D bottomright = new Point2D(rects[i * 4 + 3], rects[i * 4 + 2]);
                // Is this a horizontal box, only add it if it covers the active width of the image
                if (topleft.width <= top.width && bottomright.width >= (rawImage.fullSize.dim.width + top.width))
                {
                    rawImage.blackAreas.Add(new BlackArea(topleft.height, bottomright.height - topleft.height, false));
                }
                else if (topleft.height <= top.height && bottomright.height >= (rawImage.fullSize.dim.height + top.height))
                {
                    // Is it a vertical box, only add it if it covers the active height of the image
                    rawImage.blackAreas.Add(new BlackArea(topleft.width, bottomright.width - topleft.width, true));
                }
            }
            return(rawImage.blackAreas.Count != 0);
        }
Example #5
0
        void GetWB()
        {
            // Set the whitebalance for all the modern ARW formats (everything after A100)
            Tag priv = ifd.GetEntryRecursive(TagType.DNGPRIVATEDATA);

            if (priv != null)
            {
                byte[] data = priv.GetByteArray();
                uint   off  = ((((uint)(data)[3]) << 24) | (((uint)(data)[2]) << 16) | (((uint)(data)[1]) << 8) | (data)[0]);
                IFD    sony_private;
                sony_private = new IFD(reader, off, ifd.endian, ifd.Depth);

                Tag sony_offset = sony_private.GetEntryRecursive(TagType.SONY_OFFSET);
                Tag sony_length = sony_private.GetEntryRecursive(TagType.SONY_LENGTH);
                Tag sony_key    = sony_private.GetEntryRecursive(TagType.SONY_KEY);
                if (sony_offset == null || sony_length == null || sony_key == null || sony_key.dataCount != 4)
                {
                    throw new RawDecoderException("Couldn't find the correct metadata for white balance decoding");
                }

                off = sony_offset.GetUInt(0);
                uint len = sony_length.GetUInt(0);
                data = sony_key.GetByteArray();
                uint key = (uint)((data[3] << 24) | (data[2] << 16) | (data[1] << 8) | (data)[0]);
                reader.BaseStream.Position = off;
                byte[] ifp_data = reader.ReadBytes((int)len);
                SonyDecrypt(ifp_data, len / 4, key);
                using (var reader = new ImageBinaryReader(ifp_data))
                {
                    sony_private = new IFD(reader, 0, ifd.endian, 0, -(int)off);
                }
                Tag wb = sony_private.GetEntry(TagType.SONYGRBGLEVELS);
                if (wb != null)
                {
                    if (wb.dataCount != 4)
                    {
                        throw new RawDecoderException("White balance has " + wb.dataCount + " entries instead of 4");
                    }
                    rawImage.metadata.WbCoeffs = new WhiteBalance(wb.GetInt(1), wb.GetInt(0), wb.GetInt(2), rawImage.fullSize.ColorDepth);
                }
                else if ((wb = sony_private.GetEntry(TagType.SONYRGGBLEVELS)) != null)
                {
                    if (wb.dataCount != 4)
                    {
                        throw new RawDecoderException("White balance has " + wb.dataCount + " entries instead of 4");
                    }
                    rawImage.metadata.WbCoeffs = new WhiteBalance(wb.GetInt(0), wb.GetInt(1), wb.GetInt(3), rawImage.fullSize.ColorDepth);
                }

                //TODO read the color matrix 0x7800

                Tag black = sony_private.GetEntry((TagType)0x7300) ?? sony_private.GetEntry((TagType)0x7310);
                if (black != null)
                {
                    rawImage.black = black.GetLong(0);
                }

                Tag white = sony_private.GetEntry((TagType)0x787f);
                if (white != null)
                {
                    rawImage.whitePoint = white.GetLong(0);
                }
            }
        }
Example #6
0
        public override void DecodeRaw()
        {
            List <IFD> data = ifd.GetIFDsWithTag(TagType.STRIPOFFSETS);

            if (data.Count == 0)
            {
                Tag model = ifd.GetEntryRecursive(TagType.MODEL);
                if (model != null && model.DataAsString == "DSLR-A100")
                {
                    DecodeA100();
                    return;
                }
                else
                {
                    DecodeCryptedUncompressed();
                    return;
                }
            }
            IFD raw         = data[0];
            int compression = raw.GetEntry(TagType.COMPRESSION).GetInt(0);

            if (1 == compression)
            {
                DecodeUncompressed(raw);
                return;
            }

            if (32767 != compression)
            {
                throw new RawDecoderException("ARW Decoder: Unsupported compression");
            }

            Tag offsets = raw.GetEntry(TagType.STRIPOFFSETS);
            Tag counts  = raw.GetEntry(TagType.STRIPBYTECOUNTS);

            if (offsets.dataCount != 1)
            {
                throw new RawDecoderException("ARW Decoder: Multiple Strips found: " + offsets.dataCount);
            }
            if (counts.dataCount != offsets.dataCount)
            {
                throw new RawDecoderException("ARW Decoder: Byte count number does not match strip size: count:" + counts.dataCount + ", strips:%u " + offsets.dataCount);
            }
            uint width       = raw.GetEntry(TagType.IMAGEWIDTH).GetUInt(0);
            uint height      = raw.GetEntry(TagType.IMAGELENGTH).GetUInt(0);
            int  bitPerPixel = raw.GetEntry(TagType.BITSPERSAMPLE).GetInt(0);

            rawImage.fullSize.ColorDepth = (ushort)bitPerPixel;
            // Sony E-550 marks compressed 8bpp ARW with 12 bit per pixel
            // this makes the compression detect it as a ARW v1.
            // This camera has however another MAKER entry, so we MAY be able
            // to detect it this way in the future.
            data = ifd.GetIFDsWithTag(TagType.MAKE);
            if (data.Count > 1)
            {
                for (Int32 i = 0; i < data.Count; i++)
                {
                    string make = data[i].GetEntry(TagType.MAKE).DataAsString;
                    // Check for maker "SONY" without spaces
                    if (make != "SONY")
                    {
                        bitPerPixel = 8;
                    }
                }
            }

            bool arw1 = counts.GetInt(0) * 8 != width * height * bitPerPixel;

            if (arw1)
            {
                height += 8;
            }

            rawImage.fullSize.dim = new Point2D(width, height);
            rawImage.Init(false);


            UInt16[] curve = new UInt16[0x4001];
            Tag      c     = raw.GetEntry(TagType.SONY_CURVE);

            uint[] sony_curve = { 0, 0, 0, 0, 0, 4095 };

            for (int i = 0; i < 4; i++)
            {
                sony_curve[i + 1] = (uint)(c.GetShort(i) >> 2) & 0xfff;
            }

            for (int i = 0; i < 0x4001; i++)
            {
                curve[i] = (ushort)i;
            }

            for (int i = 0; i < 5; i++)
            {
                for (uint j = sony_curve[i] + 1; j <= sony_curve[i + 1]; j++)
                {
                    curve[j] = (ushort)(curve[j - 1] + (1 << i));
                }
            }
            var table = new TableLookUp(curve, 0x4000, true);

            long c2  = counts.GetUInt(0);
            uint off = offsets.GetUInt(0);

            if (!reader.IsValid(off))
            {
                throw new RawDecoderException("Sony ARW decoder: Data offset after EOF, file probably truncated");
            }

            if (!reader.IsValid(off, c2))
            {
                c2 = reader.BaseStream.Length - off;
            }

            ImageBinaryReader input = new ImageBinaryReader(reader.BaseStream, off);

            if (arw1)
            {
                DecodeARW(input, width, height);
            }
            else
            {
                DecodeARW2(input, width, height, bitPerPixel);
            }

            //table was already applyed
            rawImage.table = null;
        }
Example #7
0
        public override void DecodeMetadata()
        {
            base.DecodeMetadata();
            //get transform matrix
            var matrix = ifd.GetEntryRecursive(TagType.FORWARDMATRIX1);

            if (matrix == null)
            {
                matrix = ifd.GetEntryRecursive(TagType.FORWARDMATRIX2);
            }
            if (matrix != null)
            {
                rawImage.convertionM = new double[3, 3];
                for (int i = 0; i < 3; i++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        rawImage.convertionM[i, k] = matrix.GetDouble(i * 3 + k);
                    }
                }
            }

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

            if (lintable != null)
            {
                rawImage.table = new TableLookUp(lintable.GetUShortArray(), (int)lintable.dataCount, true);
            }

            Tag as_shot_neutral = ifd.GetEntryRecursive(TagType.ASSHOTNEUTRAL);

            if (as_shot_neutral != null)
            {
                if (as_shot_neutral.dataCount == 3)
                {
                    rawImage.metadata.WbCoeffs = new WhiteBalance(1.0f / as_shot_neutral.GetFloat(0), 1.0f / as_shot_neutral.GetFloat(1), 1.0f / as_shot_neutral.GetFloat(2));
                }
            }
            else
            {
                Tag as_shot_white_xy = ifd.GetEntryRecursive(TagType.ASSHOTWHITEXY);
                if (as_shot_white_xy != null)
                {
                    if (as_shot_white_xy.dataCount == 2)
                    {
                        float[] d65_white = { 0.950456F, 1, 1.088754F };
                        rawImage.metadata.WbCoeffs = new WhiteBalance(
                            as_shot_white_xy.GetFloat(0) / d65_white[0],
                            as_shot_white_xy.GetFloat(1) / d65_white[1],
                            (1 - rawImage.metadata.WbCoeffs.Red - rawImage.metadata.WbCoeffs.Green) / d65_white[2]);
                    }
                }
            }

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

            if (active_area != null)
            {
                if (active_area.dataCount != 4)
                {
                    throw new RawDecoderException("Active area has " + active_area.dataCount + " values instead of 4");
                }

                if (new Point2D(active_area.GetUInt(1), active_area.GetUInt(0)).IsThisInside(rawImage.fullSize.dim))
                {
                    if (new Point2D(active_area.GetUInt(3), active_area.GetUInt(2)).IsThisInside(rawImage.fullSize.dim))
                    {
                        Rectangle2D crop = new Rectangle2D(active_area.GetUInt(1), active_area.GetUInt(0),
                                                           active_area.GetUInt(3) - active_area.GetUInt(1), active_area.GetUInt(2) - active_area.GetUInt(0));
                        rawImage.Crop(crop);
                    }
                }
            }

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

            if (origin_entry != null && size_entry != null)
            {
                Rectangle2D cropped = new Rectangle2D(0, 0, rawImage.fullSize.dim.width, rawImage.fullSize.dim.height);
                /* Read crop position (sometimes is rational so use float) */

                if (new Point2D(origin_entry.GetUInt(0), origin_entry.GetUInt(1)).IsThisInside(rawImage.fullSize.dim))
                {
                    cropped = new Rectangle2D(origin_entry.GetUInt(0), origin_entry.GetUInt(1), 0, 0);
                }

                cropped.Dimension = rawImage.fullSize.dim - cropped.Position;
                /* Read size (sometimes is rational so use float) */

                Point2D size = new Point2D(size_entry.GetUInt(0), size_entry.GetUInt(1));
                if ((size + cropped.Position).IsThisInside(rawImage.fullSize.dim))
                {
                    cropped.Dimension = size;
                }

                if (!cropped.HasPositiveArea())
                {
                    throw new RawDecoderException("No positive crop area");
                }

                rawImage.Crop(cropped);
                if (rawImage.isCFA && cropped.Position.width % 2 == 1)
                {
                    rawImage.colorFilter.ShiftLeft(1);
                }
                if (rawImage.isCFA && cropped.Position.height % 2 == 1)
                {
                    rawImage.colorFilter.ShiftDown(1);
                }
            }
            if (rawImage.fullSize.dim.Area <= 0)
            {
                throw new RawDecoderException("No image left after crop");
            }

            // Default white level is (2 ** BitsPerSample) - 1
            rawImage.whitePoint = (1 >> raw.GetEntry(TagType.BITSPERSAMPLE).GetInt(0) - 1);

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

            if (whitelevel != null)
            {
                rawImage.whitePoint = whitelevel.GetInt(0);
            }

            // Set black
            SetBlack(raw);
        }
Example #8
0
        bool Decodeblacks(IFD raw)
        {
            Point2D blackdim = new Point2D(1, 1);

            Tag bleveldim = raw.GetEntry(TagType.BLACKLEVELREPEATDIM);

            if (bleveldim != null)
            {
                if (bleveldim.dataCount != 2)
                {
                    return(false);
                }
                blackdim = new Point2D(bleveldim.GetUInt(0), bleveldim.GetUInt(1));
            }

            if (blackdim.width == 0 || blackdim.height == 0)
            {
                return(false);
            }

            if (raw.GetEntry(TagType.BLACKLEVEL) == null)
            {
                return(true);
            }

            if (rawImage.fullSize.cpp != 1)
            {
                return(false);
            }

            Tag black_entry = raw.GetEntry(TagType.BLACKLEVEL);

            if ((int)black_entry.dataCount < blackdim.width * blackdim.height)
            {
                throw new RawDecoderException("Black level entry is too small");
            }

            if (black_entry.dataCount > 1)
            {
                Debug.Assert(black_entry.GetFloat(0) == black_entry.GetFloat(1));
            }
            rawImage.black = (int)black_entry.GetFloat(0);

            /*
             * if (blackdim.Width < 2 || blackdim.Height < 2)
             * {
             *  // We so not have enough to fill all individually, read a single and copy it
             *  rawImage.black = (int)black_entry.GetFloat(0);
             * }
             * else
             * {
             *  for (int y = 0; y < 2; y++)
             *  {
             *      for (int x = 0; x < 2; x++)
             *          rawImage.blackLevelSeparate[y * 2 + x] = (int)black_entry.GetFloat((int)(y * blackdim.Width + x));
             *  }
             * }*/

            // DNG Spec says we must add black in deltav and deltah
            Tag blackleveldeltav = raw.GetEntry(TagType.BLACKLEVELDELTAV);

            if (blackleveldeltav != null)
            {
                if ((int)blackleveldeltav.dataCount < rawImage.fullSize.dim.height)
                {
                    throw new RawDecoderException("BLACKLEVELDELTAV array is too small");
                }
                float[] black_sum = { 0.0f, 0.0f };
                for (int i = 0; i < rawImage.fullSize.dim.height; i++)
                {
                    black_sum[i & 1] += blackleveldeltav.GetFloat(i);
                }

                Debug.Assert(black_sum[0] == black_sum[1]);
                rawImage.black += (int)(black_sum[0] / rawImage.fullSize.dim.height * 2.0f);
                //for (int i = 0; i < 4; i++)                  rawImage.blackLevelSeparate[i] += (int)(black_sum[i >> 1] / rawImage.raw.dim.Height * 2.0f);
            }


            Tag blackleveldeltah = raw.GetEntry(TagType.BLACKLEVELDELTAH);

            if (blackleveldeltah != null)
            {
                if ((int)blackleveldeltah.dataCount < rawImage.fullSize.dim.width)
                {
                    throw new RawDecoderException("BLACKLEVELDELTAH array is too small");
                }
                float[] black_sum = { 0.0f, 0.0f };
                for (int i = 0; i < rawImage.fullSize.dim.width; i++)
                {
                    black_sum[i & 1] += blackleveldeltah.GetFloat(i);
                }

                Debug.Assert(black_sum[0] == black_sum[1]);
                rawImage.black += (int)(black_sum[0] / rawImage.fullSize.dim.width * 2.0f);
                //for (int i = 0; i < 4; i++)                    rawImage.blackLevelSeparate[i] += (int)(black_sum[i & 1] / rawImage.raw.dim.Width * 2.0f);
            }
            return(true);
        }
Example #9
0
        public override void DecodeRaw()
        {
            List <IFD> data = ifd.GetIFDsWithTag(TagType.COMPRESSION);

            if (data.Count == 0)
            {
                throw new RawDecoderException("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).GetInt(0);
                bool isSubsampled = false;
                try
                {
                    isSubsampled = ((i.GetEntry(TagType.NEWSUBFILETYPE)?.GetInt(0) ?? 0) & 1) != 0; // bit 0 is on if image is subsampled
                }
                catch (RawDecoderException) { }
                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("No RAW chunks found");
            }

            raw = data[0];
            int sampleFormat = 1;
            int bps          = raw.GetEntry(TagType.BITSPERSAMPLE).GetInt(0);

            if (raw.tags.ContainsKey(TagType.SAMPLEFORMAT))
            {
                sampleFormat = raw.GetEntry(TagType.SAMPLEFORMAT).GetInt(0);
            }

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

            rawImage.isCFA = (raw.GetEntry(TagType.PHOTOMETRICINTERPRETATION).GetUShort(0) == 32803);

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

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

            rawImage.fullSize.dim = new Point2D()
            {
                width  = raw.GetEntry(TagType.IMAGEWIDTH).GetUInt(0),
                height = raw.GetEntry(TagType.IMAGELENGTH).GetUInt(0)
            };

            rawImage.Init(false);
            rawImage.fullSize.ColorDepth = (ushort)bps;
            int compression = raw.GetEntry(TagType.COMPRESSION).GetShort(0);

            // Now load the image
            switch (compression)
            {
            case 1:
                uint cpp = raw.GetEntry(TagType.SAMPLESPERPIXEL).GetUInt(0);
                if (cpp > 4)
                {
                    throw new RawDecoderException("More than 4 samples per pixel is not supported.");
                }
                rawImage.fullSize.cpp = cpp;
                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;
                }
                DecodeUncompressed(raw, big_endian ? BitOrder.Jpeg : BitOrder.Plain);
                break;

            case 7:
            case 0x884c:
                rawImage.fullSize.cpp = raw.GetEntry(TagType.SAMPLESPERPIXEL).GetUInt(0);                        // Let's try loading it as tiles instead

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

                DngDecoderSlices slices = new DngDecoderSlices(reader, rawImage);
                if (raw.tags.ContainsKey(TagType.TILEOFFSETS))
                {
                    int tilew = raw.GetEntry(TagType.TILEWIDTH).GetInt(0);
                    int tileh = raw.GetEntry(TagType.TILELENGTH).GetInt(0);
                    if (tilew == 0 || tileh == 0)
                    {
                        throw new RawDecoderException("Invalid tile size");
                    }

                    long tilesX = (rawImage.fullSize.dim.width + tilew - 1) / tilew;
                    long tilesY = (rawImage.fullSize.dim.height + tileh - 1) / tileh;
                    long 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("Tile count mismatch: offsets:" + offsets.dataCount + " count:" + counts.dataCount + ", calculated:" + nTiles);
                    }

                    slices.FixLjpeg = fixLjpeg;

                    for (int y = 0; y < tilesY; y++)
                    {
                        for (int x = 0; x < tilesX; x++)
                        {
                            DngSliceElement e = new DngSliceElement(offsets.GetUInt((int)(x + y * tilesX)), counts.GetUInt((int)(x + y * tilesX)), (uint)(tilew * x), (uint)(tileh * y))
                            {
                                mUseBigtable = tilew * tileh > 1024 * 1024
                            };
                            slices.slices.Add(e);
                        }
                    }
                }
                else
                {      // Strips
                    Tag  offsets   = raw.GetEntry(TagType.STRIPOFFSETS);
                    Tag  counts    = raw.GetEntry(TagType.STRIPBYTECOUNTS);
                    uint yPerSlice = raw.GetEntry(TagType.ROWSPERSTRIP).GetUInt(0);

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

                    if (yPerSlice == 0 || yPerSlice > rawImage.fullSize.dim.height)
                    {
                        throw new RawDecoderException("Invalid y per slice");
                    }

                    uint offY = 0;
                    for (int s = 0; s < counts.dataCount; s++)
                    {
                        DngSliceElement e = new DngSliceElement(offsets.GetUInt(s), counts.GetUInt(s), 0, offY)
                        {
                            mUseBigtable = yPerSlice * rawImage.fullSize.dim.height > 1024 * 1024
                        };
                        offY += yPerSlice;

                        if (reader.IsValid(e.byteOffset, e.byteCount))     // Only decode if size is valid
                        {
                            slices.slices.Add(e);
                        }
                    }
                }

                if (slices.slices.Count == 0)
                {
                    throw new RawDecoderException("No valid slices found.");
                }

                slices.DecodeSlice();
                if (rawImage.errors.Count >= slices.slices.Count)
                {
                    throw new RawDecoderException("Too many errors encountered. Giving up.\nFirst Error:" + rawImage.errors[0]);
                }
                break;

            default:
                throw new RawDecoderException("Unknown compression: " + compression);
            }
        }
Example #10
0
        public override void DecodeRaw()
        {
            List <IFD> data = ifd.GetIFDsWithTag(TagType.PANASONIC_STRIPOFFSET);

            bool isOldPanasonic = false;

            if (data.Count == 0)
            {
                data = ifd.GetIFDsWithTag(TagType.STRIPOFFSETS);
                if (data == null)
                {
                    throw new RawDecoderException("No image data found");
                }
                isOldPanasonic = true;
            }

            raw = data[0];
            uint height = raw.GetEntry((TagType)3).GetUInt(0);
            uint width  = raw.GetEntry((TagType)2).GetUInt(0);

            if (isOldPanasonic)
            {
                Tag offsets = raw.GetEntry(TagType.STRIPOFFSETS);

                if (offsets.dataCount != 1)
                {
                    throw new RawDecoderException("Multiple Strips found:" + offsets.dataCount);
                }
                uint off = offsets.GetUInt(0);
                if (!reader.IsValid(off))
                {
                    throw new RawDecoderException("Invalid image data offset, cannot decode.");
                }

                rawImage.fullSize.dim = new Point2D(width, height);
                rawImage.Init(false);

                UInt32 size = (uint)(reader.BaseStream.Length - off);
                input_start = new ImageBinaryReader(stream, off);

                if (size >= width * height * 2)
                {
                    // It's completely unpacked little-endian
                    RawDecompressor.Decode12BitRawUnpacked(input_start, new Point2D(width, height), new Point2D(), rawImage);
                    rawImage.fullSize.ColorDepth = 12;
                }
                else if (size >= width * height * 3 / 2)
                {
                    // It's a packed format
                    RawDecompressor.Decode12BitRawWithControl(input_start, new Point2D(width, height), new Point2D(), rawImage);
                    rawImage.fullSize.ColorDepth = 12;
                }
                else
                {
                    var colorTag = raw.GetEntry((TagType)5);
                    if (colorTag != null)
                    {
                        rawImage.fullSize.ColorDepth = colorTag.GetUShort(0);
                    }
                    else
                    {
                        //try to load with 12bits colordepth
                    }
                    // It's using the new .RW2 decoding method
                    load_flags = 0;
                    DecodeRw2();
                }
            }
            else
            {
                rawImage.fullSize.dim = new Point2D(width, height);
                rawImage.Init(false);
                Tag offsets = raw.GetEntry(TagType.PANASONIC_STRIPOFFSET);

                if (offsets.dataCount != 1)
                {
                    throw new RawDecoderException("Multiple Strips found:" + offsets.dataCount);
                }

                load_flags = 0x2008;
                uint off = offsets.GetUInt(0);

                if (!reader.IsValid(off))
                {
                    throw new RawDecoderException("Invalid image data offset, cannot decode.");
                }

                input_start = new ImageBinaryReader(stream, off);
                DecodeRw2();
            }
        }
Example #11
0
        public override void DecodeMetadata()
        {
            base.DecodeMetadata();

            if (rawImage.metadata.Model == null)
            {
                throw new RawDecoderException("Model name not found");
            }
            if (rawImage.metadata.Make == null)
            {
                throw new RawDecoderException("Make name not found");
            }

            string mode = GuessMode();

            SetMetadata(rawImage.metadata.Model);
            rawImage.metadata.Mode = mode;

            //in panasonic, exif are in ifd 0
            if (rawImage.fullSize.ColorDepth == 16)
            {
                rawImage.fullSize.ColorDepth = 12;
            }

            //panasonic iso is in a special tag
            if (rawImage.metadata.IsoSpeed == 0)
            {
                var t = raw.GetEntryRecursive(TagType.PANASONIC_ISO_SPEED);
                if (t != null)
                {
                    rawImage.metadata.IsoSpeed = t.GetInt(0);
                }
            }

            // Read blacklevels
            var bias = raw.GetEntry((TagType)0x08).GetInt(0) + raw.GetEntry((TagType)0x09).GetInt(0) + raw.GetEntry((TagType)0x0a).GetInt(0);

            var rTag = raw.GetEntry((TagType)0x1c);
            var gTag = raw.GetEntry((TagType)0x1d);
            var bTag = raw.GetEntry((TagType)0x1e);

            if (rTag != null && gTag != null && bTag != null)
            {
                Debug.Assert(bTag.GetInt(0) + 15 == rTag.GetInt(0) + 15);
                Debug.Assert(bTag.GetInt(0) + 15 == gTag.GetInt(0) + 15);
                rawImage.black = rTag.GetInt(0) + bias;

                /*
                 * rawImage.blackLevelSeparate[0] = rTag.GetInt(0) + 15;
                 * rawImage.blackLevelSeparate[1] = rawImage.blackLevelSeparate[2] = gTag.GetInt(0) + 15;
                 * rawImage.blackLevelSeparate[3] = bTag.GetInt(0) + 15;*/
            }

            // Read WB levels
            var rWBTag = raw.GetEntry((TagType)0x0024);
            var gWBTag = raw.GetEntry((TagType)0x0025);
            var bWBTag = raw.GetEntry((TagType)0x0026);

            if (rWBTag != null && gWBTag != null && bWBTag != null)
            {
                rawImage.metadata.WbCoeffs = new WhiteBalance(bWBTag.GetShort(0), gWBTag.GetShort(0), rWBTag.GetShort(0), rawImage.fullSize.ColorDepth);
            }
            else
            {
                var wb1Tag = raw.GetEntry((TagType)0x0011);
                var wb2Tag = raw.GetEntry((TagType)0x0012);
                if (wb1Tag != null && wb2Tag != null)
                {
                    rawImage.metadata.WbCoeffs = new WhiteBalance(wb1Tag.GetShort(0), 1, wb2Tag.GetShort(0));
                }
            }
        }
Example #12
0
        public override Thumbnail DecodeThumb()
        {
            //find the preview IFD (usually the first if any)
            List <IFD> potential = ifd.GetIFDsWithTag(TagType.NEWSUBFILETYPE);
            IFD        thumbIFD  = null;

            if (potential?.Count != 0)
            {
                for (int i = 0; i < potential.Count; i++)
                {
                    var subFile = potential[i].GetEntry(TagType.NEWSUBFILETYPE);
                    if (subFile.GetInt(0) == 1)
                    {
                        thumbIFD = potential[i];
                        break;
                    }
                }
            }

            if (thumbIFD != null)
            {
                //there is a thumbnail
                uint    bps = thumbIFD.GetEntry(TagType.BITSPERSAMPLE).GetUInt(0);
                Point2D dim = new Point2D(thumbIFD.GetEntry(TagType.IMAGEWIDTH).GetUInt(0), thumbIFD.GetEntry(TagType.IMAGELENGTH).GetUInt(0));

                int compression = thumbIFD.GetEntry(TagType.COMPRESSION).GetShort(0);
                // Now load the image
                if (compression == 1)
                {
                    // Uncompressed
                    uint cpp = thumbIFD.GetEntry(TagType.SAMPLESPERPIXEL).GetUInt(0);
                    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);
                    uint yPerSlice = thumbIFD.GetEntry(TagType.ROWSPERSTRIP).GetUInt(0);

                    reader.BaseStream.Position = offsets.GetInt(0) + offsets.parent_offset;

                    return(new JPEGThumbnail(reader.ReadBytes(counts.GetInt(0))));
                }
                else if (compression == 6)
                {
                    var offset = thumbIFD.GetEntry((TagType)0x0201);
                    var size   = thumbIFD.GetEntry((TagType)0x0202);
                    if (size == null || offset == null)
                    {
                        return(null);
                    }

                    //get the makernote offset
                    List <IFD> exifs = ifd.GetIFDsWithTag((TagType)0x927C);

                    if (exifs == null || exifs.Count == 0)
                    {
                        return(null);
                    }

                    Tag makerNoteOffsetTag = exifs[0].GetEntryRecursive((TagType)0x927C);
                    if (makerNoteOffsetTag == null)
                    {
                        return(null);
                    }
                    reader.Position = offset.GetUInt(0) + 10 + makerNoteOffsetTag.dataOffset;
                    return(new JPEGThumbnail(reader.ReadBytes(size.GetInt(0))));
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                var previews = ifd.GetIFDsWithTag(TagType.JPEGINTERCHANGEFORMAT);

                //no thumbnail
                if (previews?.Count == 0)
                {
                    return(null);
                }
                var preview = previews[0];
                var thumb   = preview.GetEntry(TagType.JPEGINTERCHANGEFORMAT);
                var size    = preview.GetEntry(TagType.JPEGINTERCHANGEFORMATLENGTH);
                if (size == null || thumb == null)
                {
                    return(null);
                }

                reader.Position = thumb.GetUInt(0) + thumb.parent_offset;
                return(new JPEGThumbnail(reader.ReadBytes(size.GetInt(0))));
            }
        }
Example #13
0
        public override void DecodeRaw()
        {
            List <IFD> data = ifd.GetIFDsWithTag(TagType.FUJI_STRIPOFFSETS);

            if (data.Count <= 0)
            {
                throw new RawDecoderException("Fuji decoder: Unable to locate raw IFD");
            }

            IFD  raw    = data[0];
            uint height = 0;
            uint width  = 0;

            var dim = raw.GetEntry(TagType.FUJI_RAWIMAGEFULLHEIGHT);

            if (dim != null)
            {
                height = dim.GetUInt(0);
                width  = raw.GetEntry(TagType.FUJI_RAWIMAGEFULLWIDTH).GetUInt(0);
            }
            else
            {
                Tag wtag = raw.GetEntryRecursive(TagType.IMAGEWIDTH);
                if (wtag != null)
                {
                    if (wtag.dataCount < 2)
                    {
                        throw new RawDecoderException("Fuji decoder: Size array too small");
                    }
                    height = wtag.GetUShort(0);
                    width  = wtag.GetUShort(1);
                }
            }

            Tag e = raw.GetEntryRecursive(TagType.FUJI_LAYOUT);

            if (e != null)
            {
                if (e.dataCount < 2)
                {
                    throw new RawDecoderException("Fuji decoder: Layout array too small");
                }
                byte[] layout = e.GetByteArray();
                //alt_layout = !(layout[0] >> 7);
            }

            if (width <= 0 || height <= 0)
            {
                throw new RawDecoderException("RAF decoder: Unable to locate image size");
            }

            Tag offsets = raw.GetEntry(TagType.FUJI_STRIPOFFSETS);
            Tag counts  = raw.GetEntry(TagType.FUJI_STRIPBYTECOUNTS);

            if (offsets.dataCount != 1 || counts.dataCount != 1)
            {
                throw new RawDecoderException("RAF Decoder: Multiple Strips found: " + offsets.dataCount + " " + counts.dataCount);
            }

            int off   = offsets.GetInt(0);
            int count = counts.GetInt(0);

            ushort bps    = 12;
            var    bpsTag = raw.GetEntryRecursive(TagType.FUJI_BITSPERSAMPLE) ?? raw.GetEntryRecursive(TagType.BITSPERSAMPLE);

            if (bpsTag != null)
            {
                bps = bpsTag.GetUShort(0);
            }
            else
            {
                rawImage.errors.Add("BPS not found");
            }
            rawImage.fullSize.ColorDepth = bps;

            // x-trans sensors report 14bpp, but data isn't packed so read as 16bpp
            if (bps == 14)
            {
                bps = 16;
            }

            // Some fuji SuperCCD cameras include a second raw image next to the first one
            // that is identical but darker to the first. The two combined can produce
            // a higher dynamic range image. Right now we're ignoring it.
            //bool double_width = hints.ContainsKey("double_width_unpacked");

            rawImage.fullSize.dim = new Point2D(width, height);
            rawImage.Init(false);
            ImageBinaryReader input = new ImageBinaryReader(stream, (uint)(off + raw.RelativeOffset));
            Point2D           pos   = new Point2D(0, 0);

            if (count * 8 / (width * height) < 10)
            {
                throw new RawDecoderException("Don't know how to decode compressed images");
            }
            else if (ifd.endian == Endianness.Big)
            {
                RawDecompressor.Decode16BitRawUnpacked(input, new Point2D(width, height), pos, rawImage);
            }
            else
            {
                //       RawDecompressor.ReadUncompressedRaw(input, rawImage.raw.dim, pos, width * bps / 8, bps, BitOrder.Jpeg32, rawImage);
                RawDecompressor.ReadUncompressedRaw(input, new Point2D(width, height), pos, width * bps / 8, bps, BitOrder.Plain, rawImage);
            }
        }
Example #14
0
        public override void DecodeMetadata()
        {
            base.DecodeMetadata();
            if (rawImage.metadata.Model == null)
            {
                throw new RawDecoderException("ORF Meta Decoder: Model name found");
            }
            SetMetaData(rawImage.metadata.Model);

            rawImage.metadata.Lens = ifd.GetEntryRecursive((TagType)42036)?.DataAsString;

            var rMul = ifd.GetEntryRecursive(TagType.OLYMPUSREDMULTIPLIER);
            var bMul = ifd.GetEntryRecursive(TagType.OLYMPUSBLUEMULTIPLIER);

            if (rMul != null && bMul != null)
            {
                rawImage.metadata.WbCoeffs = new WhiteBalance(
                    ifd.GetEntryRecursive(TagType.OLYMPUSREDMULTIPLIER).GetShort(0),
                    1,
                    ifd.GetEntryRecursive(TagType.OLYMPUSREDMULTIPLIER).GetShort(0));
            }
            else
            {
                IFD image_processing = ifd.GetIFDWithType(IFDType.Makernote).subIFD[0];
                Tag wb = image_processing.GetEntry((TagType)0x0100);
                // Get the WB
                if (wb?.dataCount == 2 || wb?.dataCount == 4)
                {
                    rawImage.metadata.WbCoeffs = new WhiteBalance(wb.GetInt(0), 256, wb.GetInt(1), rawImage.fullSize.ColorDepth);
                }

                //TODO fix (the sub makernote doesn't read the correct value
                rawImage.metadata.WbCoeffs = new WhiteBalance(1, 1, 1);

                Tag blackEntry = image_processing.GetEntry((TagType)0x0600);
                // Get the black levels
                if (blackEntry != null)
                {
                    Debug.Assert(blackEntry.GetInt(0) == blackEntry.GetInt(1));
                    rawImage.black = blackEntry.GetInt(0);
                    // Order is assumed to be RGGB
                    if (blackEntry.dataCount == 4)
                    {
                        //blackEntry.parent_offset = img_entry.parent_offset - 12;
                        //blackEntry.offsetFromParent();

                        /*for (int i = 0; i < 4; i++)
                         * {
                         *  if (rawImage.colorFilter.cfa[(i & 1) * 2 + i >> 1] == CFAColor.Red)
                         *      rawImage.blackLevelSeparate[i] = blackEntry.GetShort(0);
                         *  else if (rawImage.colorFilter.cfa[(i & 1) * 2 + i >> 1] == CFAColor.Blue)
                         *      rawImage.blackLevelSeparate[i] = blackEntry.GetShort(3);
                         *  else if (rawImage.colorFilter.cfa[(i & 1) * 2 + i >> 1] == CFAColor.Green && i < 2)
                         *      rawImage.blackLevelSeparate[i] = blackEntry.GetShort(1);
                         *  else if (rawImage.colorFilter.cfa[(i & 1) * 2 + i >> 1] == CFAColor.Green)
                         *      rawImage.blackLevelSeparate[i] = blackEntry.GetShort(2);
                         * }*/
                        // Adjust whitelevel based on the read black (we assume the dynamic range is the same)
                        //rawImage.whitePoint -= rawImage.black - rawImage.bla[0];
                    }
                }
            }
        }
Example #15
0
        public override void DecodeRaw()
        {
            List <IFD> data = ifd.GetIFDsWithTag(TagType.STRIPOFFSETS);

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

            IFD raw         = data[0];
            int compression = raw.GetEntry(TagType.COMPRESSION).GetInt(0);

            if (1 != compression)
            {
                throw new RawDecoderException("ORF Decoder: Unsupported compression");
            }

            Tag offsets = raw.GetEntry(TagType.STRIPOFFSETS);
            Tag counts  = raw.GetEntry(TagType.STRIPBYTECOUNTS);

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

            uint off  = raw.GetEntry(TagType.STRIPOFFSETS).GetUInt(0);
            uint size = 0;

            for (int i = 0; i < counts.dataCount; i++)
            {
                size += counts.GetUInt(i);
            }

            if (!reader.IsValid(off, size))
            {
                throw new RawDecoderException("ORF Decoder: Truncated file");
            }

            uint width  = raw.GetEntry(TagType.IMAGEWIDTH).GetUInt(0);
            uint height = raw.GetEntry(TagType.IMAGELENGTH).GetUInt(0);

            rawImage.fullSize.dim = new Point2D(width, height);
            rawImage.Init(false);

            // We add 3 bytes slack, since the bitpump might be a few bytes ahead.
            ImageBinaryReader input = new ImageBinaryReader(reader.BaseStream, off);

            input.BaseStream.Position = off;
            try
            {
                if (offsets.dataCount != 1)
                {
                    DecodeUncompressed(input, width, height, size, raw.endian);
                }
                else
                {
                    DecodeCompressed(input, width, height);
                }
            }
            catch (IOException e)
            {
                rawImage.errors.Add(e.Message);
            }
        }
Example #16
0
        protected void DecodeUncompressed(IFD rawIFD, BitOrder order)
        {
            uint nslices = rawIFD.GetEntry(TagType.STRIPOFFSETS).dataCount;
            Tag  offsets = rawIFD.GetEntry(TagType.STRIPOFFSETS);
            Tag  counts  = rawIFD.GetEntry(TagType.STRIPBYTECOUNTS);

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

            uint   yPerSlice   = rawIFD.GetEntry(TagType.ROWSPERSTRIP).GetUInt(0);
            uint   width       = rawIFD.GetEntry(TagType.IMAGEWIDTH).GetUInt(0);
            uint   height      = rawIFD.GetEntry(TagType.IMAGELENGTH).GetUInt(0);
            ushort bitPerPixel = rawIFD.GetEntry(TagType.BITSPERSAMPLE).GetUShort(0);

            rawImage.fullSize.ColorDepth = bitPerPixel;
            uint            offY   = 0;
            List <RawSlice> slices = new List <RawSlice>();

            for (int s = 0; s < nslices; s++)
            {
                RawSlice slice = new RawSlice()
                {
                    offset  = offsets.GetUInt(s),
                    count   = counts.GetUInt(s),
                    offsetY = offY
                };
                if (offY + yPerSlice > height)
                {
                    slice.h = height - offY;
                }
                else
                {
                    slice.h = yPerSlice;
                }

                offY += yPerSlice;

                if (reader.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.");
            }

            rawImage.fullSize.dim = new Point2D(width, offY);
            rawImage.whitePoint   = (ushort)((1 << bitPerPixel) - 1);

            offY = 0;
            for (int i = 0; i < slices.Count; i++)
            {
                RawSlice slice = slices[i];
                reader.BaseStream.Position = slice.offset;
                bitPerPixel = (ushort)(slice.count * 8u / (slice.h * width));
                RawDecompressor.ReadUncompressedRaw(reader, new Point2D(width, slice.h), new Point2D(0, slice.offsetY), rawImage.fullSize.cpp * width * bitPerPixel / 8, bitPerPixel, order, rawImage);
                offY += slice.h;
            }
        }