public override void LoadRaw() { ushort[,] vpred = new ushort[2, 2]; ushort[] hpred = new ushort[2]; ushort csize; int step = 0; int huff = 0; int split = 0; int row; RawStream ifp = state.ifp; ifp.Seek(state.meta_offset, SeekOrigin.Begin); ushort ver0 = (ushort)ifp.ReadByte(); ushort ver1 = (ushort)ifp.ReadByte(); if (ver0 == 0x49 || ver1 == 0x58) { ifp.Seek(2110, SeekOrigin.Current); } if (ver0 == 0x46) { huff = 2; } if (state.tiff_bps == 14) { huff += 3; } vpred[0, 0] = ifp.get2(); vpred[0, 1] = ifp.get2(); vpred[1, 0] = ifp.get2(); vpred[1, 1] = ifp.get2(); int max = 1 << state.tiff_bps & 0x7fff; if ((csize = ifp.get2()) > 1) { step = max / (csize - 1); } if (ver0 == 0x44 && ver1 == 0x20 && step > 0) { int i; for (i = 0; i < csize; i++) { state.curve[i * step] = ifp.get2(); } for (i = 0; i < max; i++) { state.curve[i] = (ushort)((state.curve[i - i % step] * (step - i % step) + state.curve[i - i % step + step] * (i % step)) / step); } ifp.Seek(state.meta_offset + 562, SeekOrigin.Begin); split = ifp.get2(); } else if (ver0 != 0x46 && csize <= 0x4001) { max = csize; ifp.ReadShorts(state.curve, max); } int tempIdx = 0; HuffmanTree htree = new HuffmanTree(nikon_tree[huff], ref tempIdx); ifp.Seek(state.data_offset, SeekOrigin.Begin); ifp.ResetBits(); for (row = 0; row < state.height; row++) { if (split != 0 && row == split) { tempIdx = 0; htree = new HuffmanTree(nikon_tree[huff], ref tempIdx); } for (int col = 0; col < state.raw_width; col++) { int leaf = htree.ReadNextSymbolLength(ifp); int len = leaf & 15; int shl = leaf >> 4; int diff = (((int)ifp.GetBits(len - shl) << 1) + 1) << shl >> 1; if ((diff & (1 << (len - 1))) == 0) { diff -= (1 << len) - (shl == 0 ? 1 : 0); } if (col < 2) { vpred[row & 1, col] = (ushort)(vpred[row & 1, col] + diff); hpred[col] = vpred[row & 1, col]; } else { hpred[col & 1] = (ushort)(hpred[col & 1] + diff); } if (hpred[col & 1] >= max) { throw new Exception("derror()"); } if ((uint)(col - state.left_margin) < state.width) { state.BAYER_set(row, col - state.left_margin, state.curve[hpred[col & 1] & 0x3fff]); } } } }
public JHead(DcRawState state, RawStream s, bool info_only, uint dng_version) { byte[] data = new byte[0x10000]; restart = int.MaxValue; s.Read(data, 0, 2); if (data[1] != 0xd8) { // Error state (I think) throw new Exception("unexpected value in jpeg header"); //return 0; } int tag; int len; do { s.Read(data, 0, 2 * 2); tag = data[0] << 8 | data[1]; len = (data[2] << 8 | data[3]) - 2; if (tag <= 0xff00) { // Non error return; } s.Read(data, 0, len); switch (tag) { case 0xffc0: // SOF0 - Start of Frame 0 - Baseline DCT case 0xffc3: // SOF3 - Start of Frame 3 - Lossless (sequential) if (tag == 0xffc3) { sraw = ((((data[7] >> 4) * (data[7] & 15) - 1) & 3) == 0) ? false : true; } bits = data[0]; high = data[1] << 8 | data[2]; wide = data[3] << 8 | data[4]; clrs = data[5] - (sraw ? 1 : 0); if (len == 9 && dng_version == 0) { s.ReadByte(); } break; case 0xffc4: // DHT - Define Huffman Table if (info_only) { break; } for (int dpi = 0; dpi < len && data[dpi] < 4;) { int idx = data[dpi]; dpi++; huff[idx] = new HuffmanTree(data, ref dpi); } break; case 0xffda: // SOS - Start of Scan psv = data[1 + data[0] * 2]; bits -= data[3 + data[0] * 2] & 15; break; case 0xffdd: // DRI - Define Restart Interval restart = data[0] << 8 | data[1]; break; // <-- end of dcraw.c ported code (for this switch statement) --> // thumbnail image // for more unhandled tags, see: http://www.impulseadventure.com/photo/jpeg-decoder.html case 0xffd8: // SOI - Start of Image case 0xffd9: // EOI - End of Image case 0xffdb: // DQT - Define Quantization Table break; default: Console.WriteLine("Unhandled jpeg tag: {0}", tag); break; } } while (tag != 0xffda); if (info_only) { // No error //return 1; return; } if (sraw) { huff[3] = huff[2] = huff[1]; huff[1] = huff[0]; } row = new ushort[wide * clrs * 2]; /* * for (int iii = 0; iii < huff.Length; iii++) * { * Console.WriteLine("huff[{0}]", iii); * Decode.DumpTable(huff[iii], 0); * } */ //row = (ushort*) calloc(wide * clrs, 4); //merror(jh->row, "ljpeg_start()"); // TODO: why do we need error handling here? s.ZeroAfterFF = true; }