Пример #1
0
        /*
         *--------------------------------------------------------------
         *
         * HuffDecode --
         *
         * Taken from Figure F.16: extract next coded symbol from
         * input stream.  This should becode a macro.
         *
         * Results:
         * Next coded symbol
         *
         * Side effects:
         * Bitstream is parsed.
         *
         *--------------------------------------------------------------
         */
        public int HuffDecodeNikon(BitPumpMSB bits)
        {
            int rv;
            int l, temp;
            int code, val;

            HuffmanTable dctbl1 = huff[0];

            bits.fill();
            code = (int)bits.peekBitsNoFill(14);
            val  = dctbl1.bigTable[code];
            if ((val & 0xff) != 0xff)
            {
                bits.skipBitsNoFill((uint)val & 0xff);
                return(val >> 8);
            }

            rv   = 0;
            code = (int)bits.peekByteNoFill();
            val  = (int)dctbl1.numbits[code];
            l    = val & 15;
            if (l != 0)
            {
                bits.skipBitsNoFill((uint)l);
                rv = val >> 4;
            }
            else
            {
                bits.skipBits(8);
                l = 8;
                while (code > dctbl1.maxcode[l])
                {
                    temp = (int)bits.getBitNoFill();
                    code = (code << 1) | temp;
                    l++;
                }

                if (l > 16)
                {
                    throw new Exception("Corrupt JPEG data: bad Huffman code:" + l);
                }
                else
                {
                    rv = (int)dctbl1.huffval[dctbl1.valptr[l] + (code - dctbl1.minCode[l])];
                }
            }

            if (rv == 16)
            {
                return(-32768);
            }

            /*
             * Section F.2.2.1: decode the difference and
             * Figure F.12: extend sign bit
             */
            Int32 len  = rv & 15;
            Int32 shl  = rv >> 4;
            int   diff = (int)((bits.getBits((uint)(len - shl)) << 1) + 1) << shl >> 1;

            if ((diff & (1 << (len - 1))) == 0)
            {
                //TODO optimise
                if (shl == 0)
                {
                    shl = 1;
                }
                else
                {
                    shl = 0;
                }
                diff -= (1 << len) - shl;
            }
            return(diff);
        }
Пример #2
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);
                    }
                }
            }
        }