/* *-------------------------------------------------------------- * * 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. * *-------------------------------------------------------------- */ int HuffDecodeNikon(BitPumpMSB bits) { int rv; int l, temp; int code, val; HuffmanTable* dctbl1 = &huff[0]; bits.fill(); code = bits.peekBitsNoFill(14); val = dctbl1.bigTable[code]; if ((val & 0xff) != 0xff) { bits.skipBitsNoFill(val & 0xff); return val >> 8; } rv = 0; code = bits.peekByteNoFill(); val = dctbl1.numbits[code]; l = val & 15; if (l) { bits.skipBitsNoFill(l); rv = val >> 4; } else { bits.skipBits(8); l = 8; while (code > dctbl1.maxcode[l]) { temp = bits.getBitNoFill(); code = (code << 1) | temp; l++; } if (l > 16) { throw new Exception("Corrupt JPEG data: bad Huffman code:%u\n", l); } else { rv = dctbl1.huffval[dctbl1.valptr[l] + ((int)(code - dctbl1.((code[l]))];
void DecodeARW(ImageBinaryReader input, long w, long h) { BitPumpMSB bits = new BitPumpMSB(input); int sum = 0; for (long x = w; (x--) != 0;) { for (int y = 0; y < h + 1; y += 2) { bits.Fill(); if (y == h) { y = 1; } int len = 4 - (int)bits.GetBits(2); if (len == 3 && bits.GetBit() != 0) { len = 0; } if (len == 4) { while (len < 17 && bits.GetBit() == 0) { len++; } } int diff = (int)bits.GetBits(len); if (len != 0 && (diff & (1 << (len - 1))) == 0) { diff -= (1 << len) - 1; } sum += diff; Debug.Assert((sum >> 12) == 0); if (y < h) { rawImage.fullSize.rawView[x + y * rawImage.fullSize.dim.width] = (ushort)sum; } } } }
void DecompressNikon(ByteStream* metadata, UInt32 w, UInt32 h, UInt32 bitsPS, UInt32 offset, UInt32 size) { UInt32 v0 = metadata.getByte(); UInt32 v1 = metadata.getByte(); 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.skipBytes(2110); if (v0 == 70) huffSelect = 2; if (bitsPS == 14) huffSelect += 3; pUp1[0] = metadata.getShort(); pUp1[1] = metadata.getShort(); pUp2[0] = metadata.getShort(); pUp2[1] = metadata.getShort(); int _max = 1 << bitsPS & 0x7fff; UInt32 step = 0; UInt32 csize = metadata.getShort(); if (csize > 1) step = _max / (csize - 1); if (v0 == 68 && v1 == 32 && step > 0) { for (UInt32 i = 0; i < csize; i++) curve[i * step] = metadata.getShort(); for (int i = 0; i < _max; i++) curve[i] = (curve[i - i % step] * (step - i % step) + curve[i - i % step + step] * (i % step)) / step; metadata.setAbsoluteOffset(562); split = metadata.getShort(); } else if (v0 != 70 && csize <= 0x4001) { for (UInt32 i = 0; i < csize; i++) { curve[i] = metadata.getShort(); } _max = 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(mFile, offset, size); byte* draw = mRaw.getData(); UInt16* dest; UInt32 pitch = mRaw.pitch; int pLeft1 = 0; int pLeft2 = 0; UInt32 cw = w / 2; UInt32 random = bits.peekBits(24); //allow gcc to devirtualize the calls below RawImageDataU16[] rawdata = mRaw.get(); for (y = 0; y < h; y++) { if (split && y == split) { initTable(huffSelect + 1); } dest = (UInt16*)&draw[y * pitch]; // Adjust destination pUp1[y & 1] += HuffDecodeNikon(bits); pUp2[y & 1] += HuffDecodeNikon(bits); pLeft1 = pUp1[y & 1]; pLeft2 = pUp2[y & 1]; rawdata.setWithLookUp(clampbits(pLeft1, 15), (byte8*)dest++, &random); rawdata.setWithLookUp(clampbits(pLeft2, 15), (byte8*)dest++, &random); for (x = 1; x < cw; x++) { bits.checkPos(); pLeft1 += HuffDecodeNikon(bits); pLeft2 += HuffDecodeNikon(bits); rawdata.setWithLookUp(clampbits(pLeft1, 15), (byte8*)dest++, &random); rawdata.setWithLookUp(clampbits(pLeft2, 15), (byte8*)dest++, &random); } } if (uncorrectedRawValues) { mRaw.setTable(curve, _max, false); } else { mRaw.setTable(null); } }
/* This is probably the slowest decoder of them all. * I cannot see any way to effectively speed up the prediction * phase, which is by far the slowest part of this algorithm. * Also there is no way to multithread this code, since prediction * is based on the output of all previous pixel (bar the first four) */ private void DecodeCompressed(ImageBinaryReader s, uint width, uint height) { int nbits; long left0, nw0, left1, nw1; long sign, low, high; long[] acarry0 = new long[3], acarry1 = new long[3]; long pred, diff; //uint pitch = rawImage.pitch; /* Build a table to quickly look up "high" value */ byte[] bittable = new byte[4096]; for (int i = 0; i < 4096; i++) { int b = i; for (high = 0; high < 12; high++) { if (((b >> (11 - (int)high)) & 1) != 0) { break; } } bittable[i] = (byte)Math.Min(12, high); } left0 = nw0 = left1 = nw1 = 0; s.ReadBytes(7); BitPumpMSB bits = new BitPumpMSB(s); for (int y = 0; y < height; y++) { var pos = y * rawImage.fullSize.UncroppedDim.width; acarry0 = new long[3]; acarry1 = new long[3]; bool y_border = y < 2; bool border = true; for (int x = 0; x < width; x++) { bits.Fill(); int i = 0; if (acarry0[2] < 3) { i = 2; } for (nbits = 2 + i; acarry0[0] >> (nbits + i) != 0; nbits++) { ; } uint b = bits.PeekBits(15); sign = (b >> 14) * -1; low = (b >> 12) & 3; high = bittable[b & 4095]; // Skip bytes used above or read bits if (high == 12) { bits.SkipBits(15); high = bits.GetBits(16 - nbits) >> 1; } else { bits.SkipBits((int)high + 1 + 3); } acarry0[0] = (high << nbits) | bits.GetBits(nbits); diff = (acarry0[0] ^ sign) + acarry0[1]; acarry0[1] = (diff * 3 + acarry0[1]) >> 5; acarry0[2] = acarry0[0] > 16 ? 0 : acarry0[2] + 1; if (border) { if (y_border && x < 2) { pred = 0; } else if (y_border) { pred = left0; } else { pred = nw0 = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x]; } rawImage.fullSize.rawView[pos + x] = (ushort)(pred + ((diff << 2) | low)); // Set predictor left0 = rawImage.fullSize.rawView[pos + x]; } else { // Have local variables for values used several tiles // (having a "UInt16 *dst_up" that caches dest[-pitch+((int)x)] is actually slower, probably stack spill or aliasing) int up = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x]; long leftMinusNw = left0 - nw0; long upMinusNw = up - nw0; // Check if sign is different, and one is not zero if (leftMinusNw * upMinusNw < 0) { if (Other_abs(leftMinusNw) > 32 || Other_abs(upMinusNw) > 32) { pred = left0 + upMinusNw; } else { pred = (left0 + up) >> 1; } } else { pred = Other_abs(leftMinusNw) > Other_abs(upMinusNw) ? left0 : up; } rawImage.fullSize.rawView[pos + x] = (ushort)(pred + ((diff << 2) | low)); // Set predictors left0 = rawImage.fullSize.rawView[pos + x]; nw0 = up; } // ODD PIXELS x += 1; bits.Fill(); i = 0; if (acarry1[2] < 3) { i = 2; } for (nbits = 2 + i; acarry1[0] >> (nbits + i) != 0; nbits++) { ; } b = bits.PeekBits(15); sign = (b >> 14) * -1; low = (b >> 12) & 3; high = bittable[b & 4095]; // Skip bytes used above or read bits if (high == 12) { bits.SkipBits(15); high = bits.GetBits(16 - nbits) >> 1; } else { bits.SkipBits((int)high + 1 + 3); } acarry1[0] = (high << nbits) | bits.GetBits(nbits); diff = (acarry1[0] ^ sign) + acarry1[1]; acarry1[1] = (diff * 3 + acarry1[1]) >> 5; acarry1[2] = acarry1[0] > 16 ? 0 : acarry1[2] + 1; if (border) { if (y_border && x < 2) { pred = 0; } else if (y_border) { pred = left1; } else { pred = nw1 = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x]; } rawImage.fullSize.rawView[pos + x] = (ushort)(left1 = pred + ((diff << 2) | low)); } else { int up = rawImage.fullSize.rawView[pos - rawImage.fullSize.UncroppedDim.width + x]; long leftminusNw = left1 - nw1; long upminusNw = up - nw1; // Check if sign is different, and one is not zero if (leftminusNw * upminusNw < 0) { if (Other_abs(leftminusNw) > 32 || Other_abs(upminusNw) > 32) { pred = left1 + upminusNw; } else { pred = (left1 + up) >> 1; } } else { pred = Other_abs(leftminusNw) > Other_abs(upminusNw) ? left1 : up; } rawImage.fullSize.rawView[pos + x] = (ushort)(left1 = pred + ((diff << 2) | low)); nw1 = up; } border = y_border; } } }