public void DecodeDCFirst(JPEGBinaryReader stream, float[] dest) { int num = DCTable.Decode(stream); num = HuffmanTable.Extend(stream.ReadBits(num), num); num = (int)previousDC + num; previousDC = num; dest[0] = num << successiveLow; }
public void DecodeDCFirst(JPEGBinaryReader stream, float[] dest) { //float[] datablock = new float[64]; int s = DCTable.Decode(stream); int r = stream.ReadBits(s); s = HuffmanTable.Extend(r, s); s = (int)previousDC + s; previousDC = s; dest[0] = s << successiveLow; }
public void DecodeACFirst(JPEGBinaryReader stream, float[] zz) { if (stream.eob_run > 0) { stream.eob_run--; return; } for (int k = spectralStart; k <= spectralEnd; k++) { int s = ACTable.Decode(stream); int r = s >> 4; s &= 15; if (s != 0) { k += r; r = (int)stream.ReadBits(s); s = (int)HuffmanTable.Extend(r, s); zz[k] = s << successiveLow; } else { if (r != 15) { stream.eob_run = 1 << r; if (r != 0) { stream.eob_run += stream.ReadBits(r); } stream.eob_run--; break; } k += 15; } } }
public void DecodeACFirst(JPEGBinaryReader stream, float[] zz) { if (stream.eob_run > 0) { stream.eob_run--; return; } int num = spectralStart; int num3; while (true) { if (num > spectralEnd) { return; } int num2 = ACTable.Decode(stream); num3 = num2 >> 4; num2 &= 0xF; if (num2 != 0) { num += num3; num3 = stream.ReadBits(num2); num2 = HuffmanTable.Extend(num3, num2); zz[num] = num2 << successiveLow; } else { if (num3 != 15) { break; } num += 15; } num++; } stream.eob_run = 1 << num3; if (num3 != 0) { stream.eob_run += stream.ReadBits(num3); } stream.eob_run--; }
unsafe void DecodeScanLeft4Comps() { uint COMPS = 4; // First line HuffmanTable dctbl1 = huff[frame.ComponentInfo[0].dcTblNo]; HuffmanTable dctbl2 = huff[frame.ComponentInfo[1].dcTblNo]; HuffmanTable dctbl3 = huff[frame.ComponentInfo[2].dcTblNo]; HuffmanTable dctbl4 = huff[frame.ComponentInfo[3].dcTblNo]; if (CanonDoubleHeight) { frame.height *= 2; raw.raw.dim = new Point2D(frame.width * 2, frame.height); raw.Init(false); } fixed(ushort *d = raw.raw.rawView) { //TODO remove this hack byte *draw = (byte *)d; //Prepare slices (for CR2) Int32 slices = slicesW.Count * (int)(frame.height - skipY); long[] offset = new long[(slices + 1)]; UInt32 t_y = 0; UInt32 t_x = 0; UInt32 t_s = 0; UInt32 slice = 0; for (slice = 0; slice < slices; slice++) { offset[slice] = ((t_x + offX) * raw.Bpp + ((offY + t_y) * raw.pitch)) | (t_s << 28); Debug.Assert((offset[slice] & 0x0fffffff) < raw.pitch * raw.raw.dim.height); t_y++; if (t_y == (frame.height - skipY)) { t_y = 0; t_x += slicesW[(int)t_s++]; } } // We check the final position. If bad slice sizes are given we risk writing outside the image if ((offset[slices - 1] & 0x0fffffff) >= raw.pitch * raw.raw.dim.height) { throw new RawDecoderException("decodeScanLeft: Last slice out of bounds"); } offset[slices] = offset[slices - 1]; // Extra offset to avoid branch in loop. uint[] slice_width = new uint[slices]; // This is divided by comps, since comps pixels are processed at the time for (Int32 i = 0; i < slicesW.Count; i++) { slice_width[i] = slicesW[i] / COMPS; } if (skipX != 0) { slice_width[slicesW.Count - 1] -= skipX; } // First pixels are obviously not predicted int p1; int p2; int p3; int p4; UInt16 *dest = (UInt16 *)&draw[offset[0] & 0x0fffffff]; UInt16 *predict = dest; p1 = (1 << (int)(frame.precision - Pt - 1)) + dctbl1.Decode(); *dest++ = (ushort)p1; p2 = (1 << (int)(frame.precision - Pt - 1)) + dctbl2.Decode(); *dest++ = (ushort)p2; p3 = (1 << (int)(frame.precision - Pt - 1)) + dctbl3.Decode(); *dest++ = (ushort)p3; p4 = (1 << (int)(frame.precision - Pt - 1)) + dctbl4.Decode(); *dest++ = (ushort)p4; slice = 1; UInt32 pixInSlice = slice_width[0] - 1; UInt32 cw = frame.width - skipX; UInt32 x = 1; // Skip first pixels on first line. if (CanonDoubleHeight) { skipY = frame.height >> 1; } for (UInt32 y = 0; y < (frame.height - skipY); y++) { for (; x < cw; x++) { p1 += dctbl1.Decode(); *dest++ = (UInt16)p1; p2 += dctbl2.Decode(); *dest++ = (UInt16)p2; p3 += dctbl3.Decode(); *dest++ = (UInt16)p3; p4 += dctbl4.Decode(); *dest++ = (UInt16)p4; if (0 == --pixInSlice) { // Next slice if (slice > slices) { throw new RawDecoderException("decodeScanLeft: Ran out of slices"); } long o = offset[slice++]; dest = (UInt16 *)&draw[o & 0x0fffffff]; // Adjust destination for next pixel if ((o & 0x0fffffff) > raw.pitch * raw.raw.dim.height) { throw new RawDecoderException("decodeScanLeft: Offset out of bounds"); } pixInSlice = slice_width[o >> 28]; } } if (skipX != 0) { for (UInt32 i = 0; i < skipX; i++) { dctbl1.Decode(); dctbl2.Decode(); dctbl3.Decode(); dctbl4.Decode(); } } p1 = predict[0]; // Predictors for next row p2 = predict[1]; p3 = predict[2]; // Predictors for next row p4 = predict[3]; predict = dest; // Adjust destination for next prediction x = 0; } } }
unsafe void DecodeScanLeft2Comps() { uint COMPS = 2; Debug.Assert(slicesW.Count < 16); // We only have 4 bits for slice number. Debug.Assert(!(slicesW.Count > 1 && skipX != 0)); // Check if this is a valid state fixed(ushort *draw = raw.raw.rawView) { // First line HuffmanTable dctbl1 = huff[frame.ComponentInfo[0].dcTblNo]; HuffmanTable dctbl2 = huff[frame.ComponentInfo[1].dcTblNo]; //Prepare slices (for CR2) Int32 slices = slicesW.Count * (int)(frame.height - skipY); long[] offset = new long[(slices + 1)]; UInt32 t_y = 0; UInt32 t_x = 0; UInt32 t_s = 0; UInt32 slice = 0; UInt32 cw = frame.width - skipX; for (slice = 0; slice < slices; slice++) { offset[slice] = (t_x + offX + ((offY + t_y) * raw.raw.dim.width)) | (t_s << 28); Debug.Assert((offset[slice] & 0x0fffffff) < raw.raw.dim.width * raw.raw.dim.height); t_y++; if (t_y == (frame.height - skipY)) { t_y = 0; t_x += slicesW[(int)t_s++]; } } // We check the final position. If bad slice sizes are given we risk writing outside the image if ((offset[slices - 1] & 0x0fffffff) >= raw.raw.dim.width * raw.raw.dim.height) { throw new RawDecoderException("decodeScanLeft: Last slice out of bounds"); } offset[slices] = offset[slices - 1]; // Extra offset to avoid branch in loop. uint[] slice_width = new uint[slices]; // This is divided by comps, since comps pixels are processed at the time for (Int32 i = 0; i < slicesW.Count; i++) { slice_width[i] = slicesW[i] / COMPS; } if (skipX != 0) { slice_width[slicesW.Count - 1] -= skipX; } // First pixels are obviously not predicted int p1; int p2; UInt16 *dest = &draw[offset[0] & 0x0fffffff]; UInt16 *predict = dest; p1 = (1 << (int)(frame.precision - Pt - 1)) + dctbl1.Decode(); *dest++ = (ushort)p1; p2 = (1 << (int)(frame.precision - Pt - 1)) + dctbl2.Decode(); *dest++ = (ushort)p2; slice = 1; // Always points to next slice UInt32 pixInSlice = slice_width[0] - 1; // Skip first pixel int x = 1; // Skip first pixels on first line. for (int y = 0; y < (frame.height - skipY); y++) { for (; x < cw; x++) { p1 += dctbl1.Decode(); *dest++ = (ushort)p1; // Debug.Assert(p1 >= 0 && p1 < 65536); p2 += dctbl2.Decode(); *dest++ = (ushort)p2; // Debug.Assert(p2 >= 0 && p2 < 65536); if (0 == --pixInSlice) { // Next slice if (slice > slices) { throw new RawDecoderException("decodeScanLeft: Ran out of slices"); } long o = offset[slice++]; dest = (UInt16 *)&draw[o & 0x0fffffff]; // Adjust destination for next pixel if ((o & 0x0fffffff) > raw.pitch * raw.raw.dim.height) { throw new RawDecoderException("decodeScanLeft: Offset out of bounds"); } pixInSlice = slice_width[o >> 28]; } } if (skipX != 0) { for (UInt32 i = 0; i < skipX; i++) { dctbl1.Decode(); dctbl2.Decode(); } } p1 = predict[0]; // Predictors for next row p2 = predict[1]; predict = dest; // Adjust destination for next prediction x = 0; } } }
unsafe void DecodeScanLeft4_2_2() { int COMPS = 3; Debug.Assert(slicesW.Count < 16); // We only have 4 bits for slice number. Debug.Assert(!(slicesW.Count > 1 && skipX != 0)); // Check if this is a valid state Debug.Assert(frame.ComponentInfo[0].superH == 2); // Check if this is a valid state Debug.Assert(frame.ComponentInfo[0].superV == 1); // Check if this is a valid state Debug.Assert(frame.ComponentInfo[1].superH == 1); // Check if this is a valid state Debug.Assert(frame.ComponentInfo[1].superV == 1); // Check if this is a valid state Debug.Assert(frame.ComponentInfo[2].superH == 1); // Check if this is a valid state Debug.Assert(frame.ComponentInfo[2].superV == 1); // Check if this is a valid state Debug.Assert(frame.numComponents == COMPS); Debug.Assert(skipX == 0); HuffmanTable dctbl1 = huff[frame.ComponentInfo[0].dcTblNo]; HuffmanTable dctbl2 = huff[frame.ComponentInfo[1].dcTblNo]; HuffmanTable dctbl3 = huff[frame.ComponentInfo[2].dcTblNo]; raw.metadata.Subsampling.width = 2; raw.metadata.Subsampling.height = 1; UInt16 *predict; // Prediction pointer fixed(ushort *d = raw.raw.rawView) { //TODO remove this hack byte *draw = (byte *)d; //Prepare slices (for CR2) Int32 slices = slicesW.Count * (int)(frame.height - skipY); long[] offset = new long[(slices + 1)]; UInt32 t_y = 0; UInt32 t_x = 0; UInt32 t_s = 0; UInt32 slice = 0; uint[] slice_width = new uint[slices]; // This is divided by comps, since comps pixels are processed at the time for (int i = 0; i < slicesW.Count; i++) { slice_width[i] = slicesW[i] / 2; } for (slice = 0; slice < slices; slice++) { offset[slice] = ((t_x + offX) * raw.Bpp + ((offY + t_y) * raw.pitch)) | (t_s << 28); Debug.Assert((offset[slice] & 0x0fffffff) < raw.pitch * raw.raw.dim.height); t_y++; if (t_y >= (frame.height - skipY)) { t_y = 0; t_x += slice_width[t_s++]; } } if ((offset[slices - 1] & 0x0fffffff) >= raw.pitch * raw.raw.dim.height) { throw new RawDecoderException("decodeScanLeft: Last slice out of bounds"); } offset[slices] = offset[slices - 1]; // Extra offset to avoid branch in loop. if (skipX != 0) { slice_width[slicesW.Count - 1] -= skipX; } // Predictors for components UInt16 *dest = (UInt16 *)&draw[offset[0] & 0x0fffffff]; // Always points to next slice slice = 1; UInt32 pixInSlice = slice_width[0]; // Initialize predictors and decode one group. UInt32 x = 0; int p1; int p2; int p3; // First pixel is not predicted, all other are. p1 = (1 << (int)(frame.precision - Pt - 1)) + dctbl1.Decode(); *dest = (ushort)p1; p1 = p1 + dctbl1.Decode(); dest[COMPS] = (ushort)p1; predict = dest; p2 = (1 << (int)(frame.precision - Pt - 1)) + dctbl2.Decode(); dest[1] = (ushort)p2; p3 = (1 << (int)(frame.precision - Pt - 1)) + dctbl3.Decode(); dest[2] = (ushort)p3; // Skip to next dest += COMPS * 2; x = 2; pixInSlice -= 2; UInt32 cw = frame.width - skipX; for (int y = 0; y < (frame.height - skipY); y++) { for (; x < cw; x += 2) { if (0 == pixInSlice) { // Next slice if (slice > slices) { throw new RawDecoderException("decodeScanLeft: Ran out of slices"); } long o = offset[slice++]; dest = (UInt16 *)&draw[o & 0x0fffffff]; // Adjust destination for next pixel if ((o & 0x0fffffff) > raw.pitch * raw.raw.dim.height) { throw new RawDecoderException("decodeScanLeft: Offset out of bounds"); } pixInSlice = slice_width[o >> 28]; // If new are at the start of a new line, also update predictors. if (x == 0) { predict = dest; } } p1 += dctbl1.Decode(); *dest = (ushort)p1; p1 += dctbl1.Decode(); dest[COMPS] = (ushort)p1; p2 = p2 + dctbl2.Decode(); dest[1] = (ushort)p2; p3 = p3 + dctbl3.Decode(); dest[2] = (ushort)p3; dest += COMPS * 2; pixInSlice -= 2; } // Update predictors p1 = predict[0]; p2 = predict[1]; p3 = predict[2]; predict = dest; x = 0; } } }