public void DecompressNikon(TIFFBinaryReader metadata, UInt32 w, UInt32 h, UInt32 bitsPS, UInt32 offset, UInt32 size) { metadata.Position = 0; UInt32 v0 = metadata.ReadByte(); UInt32 v1 = metadata.ReadByte(); UInt32 huffSelect = 0; UInt32 split = 0; int[] pUp1 = new int[2]; int[] pUp2 = new int[2]; mUseBigtable = true; //_RPT2(0, "Nef version v0:%u, v1:%u\n", v0, v1); if (v0 == 73 || v1 == 88) { metadata.ReadBytes(2110); } if (v0 == 70) { huffSelect = 2; } if (bitsPS == 14) { huffSelect += 3; } pUp1[0] = metadata.ReadInt16(); pUp1[1] = metadata.ReadInt16(); pUp2[0] = metadata.ReadInt16(); pUp2[1] = metadata.ReadInt16(); int _max = 1 << (int)bitsPS & 0x7fff; UInt32 step = 0; UInt32 csize = metadata.ReadUInt16(); if (csize > 1) { step = (uint)_max / (csize - 1); } if (v0 == 68 && v1 == 32 && step > 0) { for (UInt32 i = 0; i < csize; i++) { curve[i * step] = (ushort)metadata.ReadInt16(); } for (int i = 0; i < _max; i++) { curve[i] = (ushort)((curve[i - i % step] * (step - i % step) + curve[i - i % step + step] * (i % step)) / step); } metadata.Position = (562); split = metadata.ReadUInt16(); } else if (v0 != 70 && csize <= 0x4001) { for (UInt32 i = 0; i < csize; i++) { curve[i] = metadata.ReadUInt16(); } _max = (int)csize; } initTable(huffSelect); mRaw.whitePoint = curve[_max - 1]; mRaw.blackLevel = curve[0]; if (!uncorrectedRawValues) { mRaw.setTable(curve, _max, true); } UInt32 x, y; BitPumpMSB bits = new BitPumpMSB(ref input, offset, size); UInt32 pitch = w; int pLeft1 = 0; int pLeft2 = 0; UInt32 cw = w / 2; UInt32 random = bits.peekBits(24); for (y = 0; y < h; y++) { if (split != 0 && (y == split)) { initTable(huffSelect + 1); } pUp1[y & 1] += HuffDecodeNikon(bits); pUp2[y & 1] += HuffDecodeNikon(bits); pLeft1 = pUp1[y & 1]; pLeft2 = pUp2[y & 1]; uint dest = y * pitch; mRaw.setWithLookUp((ushort)Common.clampbits(pLeft1, 15), ref mRaw.rawData, dest++, ref random); mRaw.setWithLookUp((ushort)Common.clampbits(pLeft2, 15), ref mRaw.rawData, dest++, ref random); for (x = 1; x < cw; x++) { bits.checkPos(); pLeft1 += HuffDecodeNikon(bits); pLeft2 += HuffDecodeNikon(bits); mRaw.setWithLookUp((ushort)Common.clampbits(pLeft1, 15), ref mRaw.rawData, dest++, ref random); mRaw.setWithLookUp((ushort)Common.clampbits(pLeft2, 15), ref mRaw.rawData, dest++, ref random); } } if (uncorrectedRawValues) { mRaw.setTable(curve, _max, false); } else { mRaw.table = (null); } }
/* 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); } } } }