Example #1
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 #2
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 #3
0
        public void DecodePentax(IFD root, uint offset, uint size)
        {
            // Prepare huffmann table              0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 = 16 entries
            byte[] pentax_tree = { 0, 2, 3, 1, 1, 1, 1, 1, 1, 2,  0,  0, 0, 0, 0, 0,
                                   3, 4, 2, 5, 1, 6, 0, 7, 8, 9, 10, 11, 12 };
            //                                     0 1 2 3 4 5 6 7 8 9  0  1  2 = 13 entries

            /* Attempt to read huffman table, if found in makernote */
            Tag t = root.GetEntryRecursive((TagType)0x220);

            if (t != null)
            {
                if (t.dataType == TiffDataType.UNDEFINED)
                {
                    ImageBinaryReader stream;
                    if (root.endian == Common.GetHostEndianness())
                    {
                        stream = new ImageBinaryReader(t.GetByteArray());
                    }
                    else
                    {
                        stream = new ImageBinaryReaderBigEndian(t.GetByteArray());
                    }

                    int depth = (stream.ReadUInt16() + 12) & 0xf;

                    stream.ReadBytes(12);
                    uint[] v0 = new uint[16];
                    uint[] v1 = new uint[16];
                    uint[] v2 = new uint[16];
                    for (int i = 0; i < depth; i++)
                    {
                        v0[i] = stream.ReadUInt16();
                    }

                    for (int i = 0; i < depth; i++)
                    {
                        v1[i] = stream.ReadByte();
                    }

                    /* Reset bits */
                    for (int i = 0; i < 17; i++)
                    {
                        huff[0].bits[i] = 0;
                    }

                    /* Calculate codes and store bitcounts */
                    for (int c = 0; c < depth; c++)
                    {
                        v2[c] = v0[c] >> (int)(12 - v1[c]);
                        huff[0].bits[v1[c]]++;
                    }
                    /* Find smallest */
                    for (int i = 0; i < depth; i++)
                    {
                        uint sm_val = 0xfffffff;
                        uint sm_num = 0xff;
                        for (uint j = 0; j < depth; j++)
                        {
                            if (v2[j] <= sm_val)
                            {
                                sm_num = j;
                                sm_val = v2[j];
                            }
                        }
                        huff[0].huffval[i] = sm_num;
                        v2[sm_num]         = 0xffffffff;
                    }
                    stream.Dispose();
                }
                else
                {
                    throw new RawDecoderException("Unknown Huffman table type.");
                }
            }
            else
            {
                /* Initialize with legacy data */
                uint acc = 0;
                for (int i = 0; i < 16; i++)
                {
                    huff[0].bits[i + 1] = pentax_tree[i];
                    acc += huff[0].bits[i + 1];
                }
                huff[0].bits[0] = 0;
                for (int i = 0; i < acc; i++)
                {
                    huff[0].huffval[i] = pentax_tree[i + 16];
                }
            }
            huff[0].UseBigTable = true;
            huff[0].Create(frame.precision);

            input.BaseStream.Position = 0;
            huff[0].bitPump           = new BitPumpMSB(input, offset, size);
            int[] pUp1   = { 0, 0 };
            int[] pUp2   = { 0, 0 };
            int   pLeft1 = 0;
            int   pLeft2 = 0;

            for (int y = 0; y < raw.fullSize.dim.height; y++)
            {
                var realY = y * raw.fullSize.dim.width;
                pUp1[y & 1] += huff[0].Decode();
                pUp2[y & 1] += huff[0].Decode();
                raw.fullSize.rawView[realY]     = (ushort)(pLeft1 = pUp1[y & 1]);
                raw.fullSize.rawView[realY + 1] = (ushort)(pLeft2 = pUp2[y & 1]);
                for (int x = 2; x < raw.fullSize.dim.width; x += 2)
                {
                    pLeft1 += huff[0].Decode();
                    pLeft2 += huff[0].Decode();
                    raw.fullSize.rawView[realY + x]     = (ushort)pLeft1;
                    raw.fullSize.rawView[realY + x + 1] = (ushort)pLeft2;
                }
            }
        }
Example #4
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 #5
0
        public override void DecodeRaw()
        {
            int photoMetric = ifd.GetEntryRecursive((TagType)0x0106)?.GetInt(0) ?? throw new FormatException("File not correct");;

            if (photoMetric != 2)
            {
                throw new FormatException("Photometric interpretation " + photoMetric + " not supported yet");
            }

            uint height = ifd.GetEntryRecursive((TagType)0x0101)?.GetUInt(0) ?? throw new FormatException("File not correct");
            uint width  = ifd.GetEntryRecursive((TagType)0x0100)?.GetUInt(0) ?? throw new FormatException("File not correct");

            rawImage.isCFA                 = false;
            rawImage.fullSize.dim          = new Point2D(width, height);
            rawImage.fullSize.UncroppedDim = rawImage.fullSize.dim;
            rawImage.fullSize.ColorDepth   = ifd.GetEntryRecursive((TagType)0x0102)?.GetUShort(0) ?? throw new FormatException("File not correct");
            rawImage.fullSize.cpp          = 3;
            rawImage.Init(true);
            rawImage.IsGammaCorrected = false;

            int compression = ifd.GetEntryRecursive((TagType)0x0103)?.GetInt(0) ?? throw new FormatException("File not correct");

            if (compression == 1)
            {
                DecodeUncompressed(ifd, BitOrder.Plain);
            }
            else if (compression == 32773 && rawImage.fullSize.ColorDepth <= 8)
            {
                /*Loop until you get the number of unpacked bytes you are expecting:
                 * Read the next source byte into n.
                 * If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
                 * Else if n is between - 127 and - 1 inclusive, copy the next byte -n + 1
                 * times.
                 * Else if n is - 128, noop.
                 * Endloop
                 */
                long rowperstrip    = ifd.GetEntryRecursive((TagType)0x0116)?.GetLong(0) ?? throw new FormatException("File not correct");
                long strips         = height / rowperstrip;
                long lastStrip      = height % rowperstrip;
                var  imageOffsetTag = ifd.GetEntryRecursive((TagType)0x0111) ?? throw new FormatException("File not correct");
                int  cpp            = ifd.GetEntryRecursive((TagType)0x0115)?.GetInt(0) ?? throw new FormatException("File not correct");
                for (int i = 0; i < strips + ((lastStrip == 0) ? 0 : 1); i++)
                {
                    //for each complete strip
                    //move to the offset
                    reader.Position = imageOffsetTag.GetLong(i);
                    for (int y = 0; y < rowperstrip && !(i == strips && y < lastStrip); y++)
                    {
                        //uncompress line by line of pixel
                        ushort[] temp   = new ushort[3 * width];
                        short    buffer = 0;
                        int      count  = 0;
                        for (int x = 0; x < width * 3;)
                        {
                            buffer = reader.ReadByte();
                            count  = 0;
                            if (buffer >= 0)
                            {
                                for (int k = 0; k < count; ++k, ++x)
                                {
                                    temp[x] = reader.ReadByte();
                                }
                            }
                            else
                            {
                                count  = -buffer;
                                buffer = reader.ReadByte();
                                for (int k = 0; k < count; ++k, ++x)
                                {
                                    temp[x] = (ushort)buffer;
                                }
                            }
                        }

                        for (int x = 0; x < width * 3; x++)
                        {
                            //red
                            rawImage.fullSize.red[(y + i * rowperstrip) * width + x] = temp[x * 3];
                            //green
                            rawImage.fullSize.green[(y + i * rowperstrip) * width + x] = temp[x * 3 + 1];
                            //blue
                            rawImage.fullSize.blue[(y + i * rowperstrip) * width + x] = temp[x * 3 + 2];
                            for (int z = 0; z < (cpp - 3); z++)
                            {
                                //pass the other pixel if more light
                                reader.ReadByte();
                            }
                        }
                    }
                }
            }
            else
            {
                //we know it's tiff so tiff decoder id
                var decoder = BitmapDecoder.CreateAsync(BitmapDecoder.TiffDecoderId, stream.AsRandomAccessStream()).AsTask();
                decoder.Wait();
                var bitmapasync = decoder.Result.GetSoftwareBitmapAsync().AsTask();
                bitmapasync.Wait();
                rawImage.fullSize.ColorDepth = 8;
                using (var img = bitmapasync.Result)
                    using (BitmapBuffer buffer = img.LockBuffer(BitmapBufferAccessMode.Write))
                        using (IMemoryBufferReference reference = buffer.CreateReference())
                        {
                            BitmapPlaneDescription bufferLayout = buffer.GetPlaneDescription(0);
                            rawImage.fullSize.dim = new Point2D((uint)bufferLayout.Width, (uint)bufferLayout.Height);
                            rawImage.Init(true);
                            unsafe
                            {
                                ((IMemoryBufferByteAccess)reference).GetBuffer(out var temp, out uint capacity);
                                for (int y = 0; y < rawImage.fullSize.dim.height; y++)
                                {
                                    long realY   = y * rawImage.fullSize.dim.width;
                                    long bufferY = y * rawImage.fullSize.dim.width * 4 + +bufferLayout.StartIndex;
                                    for (int x = 0; x < rawImage.fullSize.dim.width; x++)
                                    {
                                        long realPix   = realY + x;
                                        long bufferPix = bufferY + (4 * x);
                                        rawImage.fullSize.red[realPix]   = temp[bufferPix + 2];
                                        rawImage.fullSize.green[realPix] = temp[bufferPix + 1];
                                        rawImage.fullSize.blue[realPix]  = temp[bufferPix];
                                    }
                                }
                            }
                        }
            }
        }