public void Decode12BitRawBE(TIFFBinaryReader input, UInt32 w, UInt32 h) { if (w < 2) { throw new IOException("Are you mad? 1 pixel wide raw images are no fun"); } UInt32 pitch = mRaw.pitch; if (input.getRemainSize() < ((w * 12 / 8) * h)) { if ((UInt32)input.getRemainSize() > (w * 12 / 8)) { h = (uint)(input.getRemainSize() / (w * 12 / 8) - 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."); } } for (UInt32 y = 0; y < h; y++) { for (UInt32 x = 0; x < w; x += 2) { UInt32 g1 = input.ReadByte(); UInt32 g2 = input.ReadByte(); mRaw.rawData[y * pitch + x] = (ushort)((g1 << 4) | (g2 >> 4)); UInt32 g3 = input.ReadByte(); mRaw.rawData[y * pitch + x + 1] = (ushort)(((g2 & 0x0f) << 8) | g3); } } }
public void Decode12BitRawUnpacked(TIFFBinaryReader input, UInt32 w, UInt32 h) { UInt32 pitch = mRaw.pitch; if (input.getRemainSize() < w * h * 2) { if ((UInt32)input.getRemainSize() > w * 2) { h = (uint)(input.getRemainSize() / (w * 2) - 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."); } } for (UInt32 y = 0; y < h; y++) { for (UInt32 x = 0; x < w; x += 1) { UInt32 g1 = input.ReadByte(); UInt32 g2 = input.ReadByte(); mRaw.rawData[y * pitch + x] = (ushort)(((g2 << 8) | g1) >> 4); } } }
public void Decode12BitRawBEInterlaced(TIFFBinaryReader input, UInt32 w, UInt32 h) { if (w < 2) { throw new IOException("Are you mad? 1 pixel wide raw images are no fun"); } UInt32 pitch = mRaw.pitch; if (input.getRemainSize() < ((w * 12 / 8) * h)) { if ((UInt32)input.getRemainSize() > (w * 12 / 8)) { h = (uint)(input.getRemainSize() / (w * 12 / 8) - 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."); } } UInt32 half = (h + 1) >> 1; UInt32 y = 0; for (UInt32 row = 0; row < h; row++) { y = row % half * 2 + row / half; if (y == 1) { // The second field starts at a 2048 byte aligment UInt32 offset = ((half * w * 3 / 2 >> 11) + 1) << 11; if (offset > input.getRemainSize()) { throw new IOException("Decode12BitSplitRaw: Trying to jump to invalid offset " + offset); } input.Position = offset; } for (UInt32 x = 0; x < w; x += 2) { UInt32 g1 = input.ReadByte(); UInt32 g2 = input.ReadByte(); mRaw.rawData[y * pitch + x] = (ushort)((g1 << 4) | (g2 >> 4)); UInt32 g3 = input.ReadByte(); mRaw.rawData[y * pitch + x + 1] = (ushort)(((g2 & 0x0f) << 8) | g3); } } }
/*** Used for entropy encoded sections, for now only Nikon Coolpix ***/ public BitPumpMSB32(ref TIFFBinaryReader s) { s.Read(buffer, (int)s.Position, (int)s.BaseStream.Length); size = (uint)(s.getRemainSize() + sizeof(UInt32)); MIN_GET_BITS = (BITS_PER_LONG_LONG - 33); init(); }
public void Decode12BitRawBEWithControl(ref TIFFBinaryReader input, UInt32 w, UInt32 h) { if (w < 2) { throw new IOException("Are you mad? 1 pixel wide raw images are no fun"); } UInt32 pitch = mRaw.pitch; // Calulate expected bytes per line. UInt32 perline = (w * 12 / 8); // Add skips every 10 pixels perline += ((w + 2) / 10); // If file is too short, only decode as many lines as we have if (input.getRemainSize() < (perline * h)) { if ((UInt32)input.getRemainSize() > perline) { h = (uint)(input.getRemainSize() / perline - 1); mRaw.errors.Add("Image truncated (file is too short)"); } else { throw new IOException("Decode12BitRawBEWithControl: Not enough data to decode a single line. Image file truncated."); } } UInt32 x; for (UInt32 y = 0; y < h; y++) { for (x = 0; x < w; x += 2) { UInt32 g1 = input.ReadByte(); UInt32 g2 = input.ReadByte(); mRaw.rawData[(y * pitch) + x] = (ushort)((g1 << 4) | (g2 >> 4)); UInt32 g3 = input.ReadByte(); mRaw.rawData[(y * pitch) + x + 1] = (ushort)(((g2 & 0x0f) << 8) | g3); if ((x % 10) == 8) { input.Position++; } } } }
public void Decode8BitRaw(ref TIFFBinaryReader input, UInt32 w, UInt32 h) { ushort[] data = mRaw.rawData; UInt32 pitch = mRaw.pitch; if (input.getRemainSize() < w * h) { if ((UInt32)input.getRemainSize() > w) { h = (uint)(input.getRemainSize() / w - 1); mRaw.errors.Add("Image truncated (file is too short)"); } else { throw new IOException("Decode8BitRaw: Not enough data to decode a single line. Image file truncated."); } } UInt32 random = 0; for (UInt32 y = 0; y < h; y++) { for (UInt32 x = 0; x < w; x += 1) { if (uncorrectedRawValues) { mRaw.rawData[(y * pitch) + x] = input.ReadByte(); } else { mRaw.setWithLookUp(input.ReadByte(), ref mRaw.rawData, x, ref random); input.Position++; } } } }
/* 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); } } } }
int MIN_GET_BITS;// = (BITS_PER_LONG - 7); /* max value for long getBuffer */ public BitPumpPlain(ref TIFFBinaryReader s) { MIN_GET_BITS = (BITS_PER_LONG - 7); s.Read(buffer, (int)s.Position, (int)s.BaseStream.Length); size = (uint)(8 * s.getRemainSize()); }