Exemple #1
0
        public bool isThisInside(ref iRectangle2D otherPoint)
        {
            iPoint2D br1 = getBottomRight();
            iPoint2D br2 = otherPoint.getBottomRight();

            return(pos.x >= otherPoint.pos.x && pos.y >= otherPoint.pos.y && br1.x <= br2.x && br1.y <= br2.y);
        }
Exemple #2
0
        public Camera(Camera camera, UInt32 alias_num)
        {
            if (alias_num >= camera.aliases.Count)
            {
                throw new CameraMetadataException("Camera: Internal error, alias number out of range specified.");
            }

            make            = camera.make;
            model           = camera.aliases[(int)alias_num];
            canonical_make  = camera.canonical_make;
            canonical_model = camera.canonical_model;
            canonical_alias = camera.canonical_aliases[(int)alias_num];
            canonical_id    = camera.canonical_id;
            mode            = camera.mode;
            cfa             = camera.cfa;
            supported       = camera.supported;
            cropSize        = camera.cropSize;
            cropPos         = camera.cropPos;
            decoderVersion  = camera.decoderVersion;
            for (Int32 i = 0; i < camera.blackAreas.Count; i++)
            {
                blackAreas.Add(camera.blackAreas[i]);
            }
            for (Int32 i = 0; i < camera.sensorInfo.Count; i++)
            {
                sensorInfo.Add(camera.sensorInfo[i]);
            }
            foreach (KeyValuePair <string, string> mi in camera.hints)
            {
                hints.Add(mi.Key, mi.Value);
            }
        }
Exemple #3
0
        iRectangle2D getOverlap(ref iRectangle2D other)
        {
            iRectangle2D overlap = new iRectangle2D();
            iPoint2D     br1     = getBottomRight();
            iPoint2D     br2     = other.getBottomRight();

            overlap.setAbsolute(Math.Max(pos.x, other.pos.x), Math.Max(pos.y, other.pos.y), Math.Min(br1.x, br2.x), Math.Min(br1.y, br2.y));
            return(overlap);
        }
Exemple #4
0
        iRectangle2D combine(ref iRectangle2D other)
        {
            iRectangle2D combined = new iRectangle2D();
            iPoint2D     br1      = getBottomRight();
            iPoint2D     br2      = other.getBottomRight();

            combined.setAbsolute(Math.Min(pos.x, other.pos.x), Math.Min(pos.y, other.pos.y), Math.Max(br1.x, br2.x), Math.Max(br2.y, br2.y));
            return(combined);
        }
Exemple #5
0
        public void setCFA(iPoint2D in_size, CFAColor color1, CFAColor color2, CFAColor color3, CFAColor color4)
        {
            if (in_size != size)
            {
                setSize(in_size);
            }

            cfa[0] = color1;
            cfa[1] = color2;
            cfa[2] = color3;
            cfa[3] = color4;
        }
Exemple #6
0
 public void setColorAt(iPoint2D pos, CFAColor c)
 {
     if (pos.x >= size.x || pos.x < 0)
     {
         throw new RawDecoderException("SetColor: position out of CFA pattern");
     }
     if (pos.y >= size.y || pos.y < 0)
     {
         throw new RawDecoderException("SetColor: position out of CFA pattern");
     }
     cfa[pos.x + pos.y * size.x] = c;
 }
Exemple #7
0
        public ColorFilterArray(UInt32 filters)
        {
            size = new iPoint2D(8, 2);
            cfa  = null;
            setSize(size);

            for (int x = 0; x < 8; x++)
            {
                for (int y = 0; y < 2; y++)
                {
                    CFAColor c = toRawspeedColor(FC(filters, y, x));
                    setColorAt(new iPoint2D(x, y), c);
                }
            }
        }
Exemple #8
0
        /* This will make sure that offset is positive, and make the area smaller if needed */
        /* This will return true if there is any area left */
        bool cropOffsetToZero()
        {
            iPoint2D crop_pixels = new iPoint2D();

            if (pos.x < 0)
            {
                crop_pixels.x = -(pos.x);
                pos.x         = 0;
            }
            if (pos.y < 0)
            {
                crop_pixels.y = -pos.y;
                pos.y         = 0;
            }
            dim -= crop_pixels;
            return(cropArea());
        }
Exemple #9
0
        public void subFrame(iRectangle2D crop)
        {
            if (!crop.dim.isThisInside(dim - crop.pos))
            {
                Debug.WriteLine("WARNING: RawImageData::subFrame - Attempted to create new subframe larger than original size. Crop skipped.");
                return;
            }
            if (crop.pos.x < 0 || crop.pos.y < 0 || !crop.hasPositiveArea())
            {
                Debug.WriteLine("WARNING: RawImageData::subFrame - Negative crop offset. Crop skipped.");
                return;
            }

            mOffset += crop.pos;

            dim = crop.dim;
        }
Exemple #10
0
 public void setSize(iPoint2D _size)
 {
     size = _size;
     cfa  = null;
     if (size.area() > 100)
     {
         throw new RawDecoderException("ColorFilterArray:setSize if your CFA pattern is really " + size.area() + " pixels in area we may as well give up now");
     }
     if (size.area() <= 0)
     {
         return;
     }
     cfa = new CFAColor[size.area()];
     if (cfa == null)
     {
         throw new RawDecoderException("ColorFilterArray:setSize Unable to allocate memory");
     }
     //Common.memset(cfa, CFAColor.UNKNOWN, (int)(size.area()));
 }
Exemple #11
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. */

            masked.getIntArray(out Int32[] rects, nrects * 4);

            iPoint2D top = mRaw.mOffset;

            for (UInt32 i = 0; i < nrects; i++)
            {
                iPoint2D topleft     = new iPoint2D(rects[i * 4 + 1], rects[i * 4]);
                iPoint2D bottomright = new iPoint2D(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.x <= top.x && bottomright.x >= (mRaw.dim.x + top.x))
                {
                    mRaw.blackAreas.Add(new BlackArea(topleft.y, bottomright.y - topleft.y, false));
                }
                // Is it a vertical box, only add it if it covers the active height of the image
                else if (topleft.y <= top.y && bottomright.y >= (mRaw.dim.y + top.y))
                {
                    mRaw.blackAreas.Add(new BlackArea(topleft.x, bottomright.x - topleft.x, true));
                }
            }
            return(mRaw.blackAreas.Count != 0);
        }
Exemple #12
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);
                    }
                }
            }
        }
Exemple #13
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;
            }
        }
Exemple #14
0
 /* Set BR  */
 public void setBottomRightAbsolute(iPoint2D bottom_right)
 {
     dim = new iPoint2D(bottom_right) - pos;
 }
Exemple #15
0
 public bool isThisInside(iPoint2D otherPoint)
 {
     return(x <= otherPoint.x && y <= otherPoint.y);
 }
Exemple #16
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);
        }
Exemple #17
0
        bool decodeBlackLevels(IFD raw)
        {
            iPoint2D blackdim = new iPoint2D(1, 1);

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

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

            if (blackdim.x == 0 || blackdim.y == 0)
            {
                return(false);
            }

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

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

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

            if ((int)black_entry.dataCount < blackdim.x * blackdim.y)
            {
                throw new RawDecoderException("DNG: BLACKLEVEL entry is too small");
            }

            if (blackdim.x < 2 || blackdim.y < 2)
            {
                // We so not have enough to fill all individually, read a single and copy it
                //TODO check if float
                float value = black_entry.getFloat();
                for (int y = 0; y < 2; y++)
                {
                    for (int x = 0; x < 2; x++)
                    {
                        mRaw.blackLevelSeparate[y * 2 + x] = (int)value;
                    }
                }
            }
            else
            {
                for (int y = 0; y < 2; y++)
                {
                    for (int x = 0; x < 2; x++)
                    {
                        mRaw.blackLevelSeparate[y * 2 + x] = (int)black_entry.getFloat(y * blackdim.x + 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 < mRaw.dim.y)
                {
                    throw new RawDecoderException("DNG: BLACKLEVELDELTAV array is too small");
                }
                float[] black_sum = { 0.0f, 0.0f };
                for (int i = 0; i < mRaw.dim.y; i++)
                {
                    black_sum[i & 1] += blackleveldeltav.getFloat(i);
                }

                for (int i = 0; i < 4; i++)
                {
                    mRaw.blackLevelSeparate[i] += (int)(black_sum[i >> 1] / mRaw.dim.y * 2.0f);
                }
            }


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

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

                for (int i = 0; i < 4; i++)
                {
                    mRaw.blackLevelSeparate[i] += (int)(black_sum[i & 1] / mRaw.dim.x * 2.0f);
                }
            }
            return(true);
        }
Exemple #18
0
 public void setAbsolute(iPoint2D top_left, iPoint2D bottom_right)
 {
     pos = top_left; setBottomRightAbsolute(bottom_right);
 }
Exemple #19
0
 public void setSize(iPoint2D size)
 {
     dim = size;
 }
Exemple #20
0
 public iRectangle2D(iRectangle2D r)
 {
     dim = new iPoint2D(r.dim); pos = new iPoint2D(r.pos);
 }
Exemple #21
0
 public iRectangle2D(int x_pos, int y_pos, int w, int h)
 {
     dim = new iPoint2D(w, h); pos = new iPoint2D(x_pos, y_pos);
 }
Exemple #22
0
 public iRectangle2D(int w, int h)
 {
     dim = new iPoint2D(w, h);
 }
Exemple #23
0
 public iPoint2D getSmallest(iPoint2D otherPoint)
 {
     return(new iPoint2D(Math.Min(x, otherPoint.x), Math.Min(y, otherPoint.y)));
 }
Exemple #24
0
        public void setMetaData(CameraMetaData meta, string make, string model, string mode, int iso_speed)
        {
            mRaw.metadata.isoSpeed = iso_speed;
            make  = make.Trim();
            model = model.Trim();
            Camera cam = meta.getCamera(make, model, mode);

            if (cam == null)
            {
                Debug.WriteLine("ISO:" + iso_speed);
                Debug.WriteLine("Unable to find camera in database: " + make + " " + model + " " + mode + "\nPlease upload file to ftp.rawstudio.org, thanks!");
                return;
            }

            mRaw.cfa = cam.cfa;
            mRaw.metadata.canonical_make  = cam.canonical_make;
            mRaw.metadata.canonical_model = cam.canonical_model;
            mRaw.metadata.canonical_alias = cam.canonical_alias;
            mRaw.metadata.canonical_id    = cam.canonical_id;
            mRaw.metadata.make            = make;
            mRaw.metadata.model           = model;
            mRaw.metadata.mode            = mode;

            if (applyCrop)
            {
                iPoint2D new_size = cam.cropSize;

                // If crop size is negative, use relative cropping
                if (new_size.x <= 0)
                {
                    new_size.x = mRaw.dim.x - cam.cropPos.x + new_size.x;
                }

                if (new_size.y <= 0)
                {
                    new_size.y = mRaw.dim.y - cam.cropPos.y + new_size.y;
                }

                mRaw.subFrame(new iRectangle2D(cam.cropPos, new_size));


                // Shift CFA to match crop
                mRaw.UncroppedCfa = new ColorFilterArray(mRaw.cfa);
                if ((cam.cropPos.x & 1) != 0)
                {
                    mRaw.cfa.shiftLeft(0);
                }
                if ((cam.cropPos.y & 1) != 0)
                {
                    mRaw.cfa.shiftDown(0);
                }
            }

            CameraSensorInfo sensor = cam.getSensorInfo(iso_speed);

            mRaw.blackLevel = sensor.blackLevel;
            mRaw.whitePoint = (uint)sensor.whiteLevel;
            mRaw.blackAreas = cam.blackAreas;
            if (mRaw.blackAreas.Count == 0 && sensor.mBlackLevelSeparate.Count != 0)
            {
                if (mRaw.isCFA && mRaw.cfa.size.area() <= sensor.mBlackLevelSeparate.Count)
                {
                    for (UInt32 i = 0; i < mRaw.cfa.size.area(); i++)
                    {
                        mRaw.blackLevelSeparate[i] = sensor.mBlackLevelSeparate[(int)i];
                    }
                }
                else if (!mRaw.isCFA && mRaw.cpp <= sensor.mBlackLevelSeparate.Count)
                {
                    for (UInt32 i = 0; i < mRaw.cpp; i++)
                    {
                        mRaw.blackLevelSeparate[i] = sensor.mBlackLevelSeparate[(int)i];
                    }
                }
            }

            // Allow overriding individual blacklevels. Values are in CFA order
            // (the same order as the in the CFA tag)
            // A hint could be:
            // <Hint name="override_cfa_black" value="10,20,30,20"/>
            cam.hints.TryGetValue("override_cfa_black", out string value);
            if (value != null)
            {
                string rgb = value;
                var    v   = rgb.Split(',');
                if (v.Length != 4)
                {
                    mRaw.errors.Add("Expected 4 values '10,20,30,20' as values for override_cfa_black hint.");
                }
                else
                {
                    for (int i = 0; i < 4; i++)
                    {
                        mRaw.blackLevelSeparate[i] = Int32.Parse(v[i]);
                    }
                }
            }
        }
Exemple #25
0
 public void setAbsolute(int x1, int y1, int x2, int y2)
 {
     pos = new iPoint2D(x1, y1); dim = new iPoint2D(x2 - x1, y2 - y1);
 }
Exemple #26
0
 public ColorFilterArray(iPoint2D _size)
 {
     setSize(_size);
 }
Exemple #27
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);
        }
Exemple #28
0
 public ColorFilterArray()
 {
     size = new iPoint2D(0, 0);
 }
Exemple #29
0
 public iRectangle2D(iPoint2D _pos, iPoint2D size)
 {
     dim = size;
     pos = _pos;
 }
Exemple #30
0
 public iPoint2D(iPoint2D pt)
 {
     x = pt.x; y = pt.y;
 }