/* *-------------------------------------------------------------- * * 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); }
/* 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); } } } }