public JpegDecoder(Stream input) { jpegReader = new JPEGBinaryReader(input); if (jpegReader.GetNextMarker() != JPEGMarker.SOI) throw new Exception("Failed to find SOI marker."); }
public void DecodeScanBaseline(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { // Set the decode function for all the components for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) { JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]); comp.Decode = comp.DecodeBaseline; } DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); }
public void DecodeScanProgressive(byte successiveApproximation, byte startSpectralSelection, byte endSpectralSelection, byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { byte successiveHigh = (byte)(successiveApproximation >> 4); byte successiveLow = (byte)(successiveApproximation & 0x0f); if ((startSpectralSelection > endSpectralSelection) || (endSpectralSelection > 63)) throw new Exception("Bad spectral selection."); bool dcOnly = startSpectralSelection == 0; bool refinementScan = (successiveHigh != 0); if (dcOnly) // DC scan { if (endSpectralSelection != 0) throw new Exception("Bad spectral selection for DC only scan."); } else // AC scan { if (numberOfComponents > 1) throw new Exception("Too many components for AC scan!"); } // Set the decode function for all the components // TODO: set this for the scan and let the component figure it out for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) { JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]); comp.successiveLow = successiveLow; if (dcOnly) { if (refinementScan) // DC refine comp.Decode = comp.DecodeDCRefine; else // DC first comp.Decode = comp.DecodeDCFirst; } else { comp.spectralStart = startSpectralSelection; comp.spectralEnd = endSpectralSelection; if (refinementScan) // AC refine comp.Decode = comp.DecodeACRefine; else // AC first comp.Decode = comp.DecodeACFirst; } } DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); }
/// <summary>Figure F.16 - Reads the huffman code bit-by-bit.</summary> public int Decode(JPEGBinaryReader JPEGStream) { int i = 0; short code = (short)JPEGStream.ReadBits(1); while (code > maxcode[i]) { i++; code <<= 1; code |= (short)JPEGStream.ReadBits(1); } int val = huffval[code + (valptr[i])]; if (val < 0) { val = 256 + val; } return(val); }
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 DecodeACRefine(JPEGBinaryReader stream, float[] dest) { int p1 = 1 << successiveLow; int m1 = (-1) << successiveLow; int k = spectralStart; if (stream.eob_run == 0) for (; k <= spectralEnd; k++) { #region Decode and check S int s = ACTable.Decode(stream); int r = s >> 4; s &= 15; if (s != 0) { if (s != 1) throw new Exception("Decode Error"); if (stream.ReadBits(1) == 1) s = p1; else s = m1; } else { if (r != 15) { stream.eob_run = 1 << r; if (r > 0) stream.eob_run += stream.ReadBits(r); break; } } // if (s != 0) #endregion // Apply the update do { if (dest[k] != 0) { if (stream.ReadBits(1) == 1) { if (((int)dest[k] & p1) == 0) { if (dest[k] >= 0) dest[k] += p1; else dest[k] += m1; } } } else { if (--r < 0) break; } k++; } while (k <= spectralEnd); if( (s != 0) && k < 64) { dest[k] = s; } } // for k = start ... end if (stream.eob_run > 0) { for (; k <= spectralEnd; k++) { if (dest[k] != 0) { if (stream.ReadBits(1) == 1) { if (((int)dest[k] & p1) == 0) { if (dest[k] >= 0) dest[k] += p1; else dest[k] += m1; } } } } stream.eob_run--; } }
private void DecodeScan(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { //TODO: not necessary jpegReader.eob_run = 0; int mcuIndex = 0; int mcuTotalIndex = 0; // This loops through until a MarkerTagFound exception is // found, if the marker tag is a RST (Restart Marker) it // simply skips it and moves on this system does not handle // corrupt data streams very well, it could be improved by // handling misplaced restart markers. int h = 0, v = 0; int x = 0; long lastPosition = jpegReader.BaseStream.Position; //TODO: replace this with a loop which knows how much data to expect while (true) { #region Inform caller of decode progress if (ProgressUpdateMethod != null) { if (jpegReader.BaseStream.Position >= lastPosition + JpegDecoder.ProgressUpdateByteInterval) { lastPosition = jpegReader.BaseStream.Position; ProgressUpdateMethod(lastPosition); } } #endregion try { // Loop though capturing MCU, instruct each // component to read in its necessary count, for // scaling factors the components automatically // read in how much they need // Sec A.2.2 from CCITT Rec. T.81 (1992 E) bool interleaved = !(numberOfComponents == 1); if (!interleaved) { JpegComponent comp = Scan.GetComponentById(componentSelector[0]); comp.SetBlock(mcuIndex); comp.DecodeMCU(jpegReader, h, v); int mcus_per_line = mcus_per_row(comp); int blocks_per_line = (int) Math.Ceiling((double)this.Width / (8 * comp.factorH)); // TODO: Explain the non-interleaved scan ------ h++; x++; if (h == comp.factorH) { h = 0; mcuIndex++; } if( (x % mcus_per_line) == 0) { x = 0; v++; if (v == comp.factorV) { if (h != 0) { mcuIndex++; h = 0; } v = 0; } else { mcuIndex -= blocks_per_line; // we were mid-block if (h != 0) { mcuIndex++; h = 0; } } } // ----------------------------------------------- } else // Components are interleaved { for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) { JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]); comp.SetBlock(mcuTotalIndex); for (int j = 0; j < comp.factorV; j++) for (int i = 0; i < comp.factorH; i++) { comp.DecodeMCU(jpegReader, i, j); } } mcuIndex++; mcuTotalIndex++; } } // We've found a marker, see if the marker is a restart // marker or just the next marker in the stream. If // it's the next marker in the stream break out of the // while loop, if it's just a restart marker skip it catch (JPEGMarkerFoundException ex) { marker = ex.Marker; // Handle JPEG Restart Markers, this is where the // count of MCU's per interval is compared with // the count actually obtained, if it's short then // pad on some MCU's ONLY for components that are // greater than one. Also restart the DC prediction // to zero. if (marker == JPEGMarker.RST0 || marker == JPEGMarker.RST1 || marker == JPEGMarker.RST2 || marker == JPEGMarker.RST3 || marker == JPEGMarker.RST4 || marker == JPEGMarker.RST5 || marker == JPEGMarker.RST6 || marker == JPEGMarker.RST7) { for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) { JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]); if (compIndex > 1) comp.padMCU(mcuTotalIndex, resetInterval - mcuIndex); comp.resetInterval(); } mcuTotalIndex += (resetInterval - mcuIndex); mcuIndex = 0; } else { break; // We're at the end of our scan, exit out. } } } }
/// <summary> /// Generated from text on F-23, F.13 - Huffman decoded of AC coefficients /// on ISO DIS 10918-1. Requirements and Guidelines. /// </summary> internal void decode_ac_coefficients(JPEGBinaryReader JPEGStream, float[] zz) { for (int k = 1; k < 64; k++) { int s = ACTable.Decode(JPEGStream); int r = s >> 4; s &= 15; if (s != 0) { k += r; r = (int)JPEGStream.ReadBits(s); s = (int)HuffmanTable.Extend(r, s); zz[k] = s; } else { if (r != 15) { //throw new JPEGMarkerFoundException(); return; } k += 15; } } }
/// <summary> /// Generated from text on F-22, F.2.2.1 - Huffman decoding of DC /// coefficients on ISO DIS 10918-1. Requirements and Guidelines. /// </summary> /// <param name="JPEGStream">Stream that contains huffman bits</param> /// <returns>DC coefficient</returns> public float decode_dc_coefficient(JPEGBinaryReader JPEGStream) { int t = DCTable.Decode(JPEGStream); float diff = JPEGStream.ReadBits(t); diff = HuffmanTable.Extend((int)diff, t); diff = (previousDC + diff); previousDC = diff; return diff; }
public void DecodeMCU(JPEGBinaryReader jpegReader, int i, int j) { Decode(jpegReader, scanMCUs[i,j]); }
public void DecodeDCRefine(JPEGBinaryReader stream, float[] dest) { if (stream.ReadBits(1) == 1) { dest[0] = (int)dest[0] | (1 << 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 DecodeMCU(JPEGBinaryReader jpegReader, int i, int j) { Decode(jpegReader, scanMCUs[i, j]); }
public void DecodeACRefine(JPEGBinaryReader stream, float[] dest) { int p1 = 1 << successiveLow; int m1 = (-1) << successiveLow; int k = spectralStart; if (stream.eob_run == 0) { for (; k <= spectralEnd; k++) { #region Decode and check S int s = ACTable.Decode(stream); int r = s >> 4; s &= 15; if (s != 0) { if (s != 1) { throw new Exception("Decode Error"); } if (stream.ReadBits(1) == 1) { s = p1; } else { s = m1; } } else { if (r != 15) { stream.eob_run = 1 << r; if (r > 0) { stream.eob_run += stream.ReadBits(r); } break; } } // if (s != 0) #endregion // Apply the update do { if (dest[k] != 0) { if (stream.ReadBits(1) == 1) { if (((int)dest[k] & p1) == 0) { if (dest[k] >= 0) { dest[k] += p1; } else { dest[k] += m1; } } } } else { if (--r < 0) { break; } } k++; } while (k <= spectralEnd); if ((s != 0) && k < 64) { dest[k] = s; } } // for k = start ... end } if (stream.eob_run > 0) { for (; k <= spectralEnd; k++) { if (dest[k] != 0) { if (stream.ReadBits(1) == 1) { if (((int)dest[k] & p1) == 0) { if (dest[k] >= 0) { dest[k] += p1; } else { dest[k] += m1; } } } } } stream.eob_run--; } }
private void DecodeScan(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { //TODO: not necessary jpegReader.eob_run = 0; int mcuIndex = 0; int mcuTotalIndex = 0; // This loops through until a MarkerTagFound exception is // found, if the marker tag is a RST (Restart Marker) it // simply skips it and moves on this system does not handle // corrupt data streams very well, it could be improved by // handling misplaced restart markers. int h = 0, v = 0; int x = 0; long lastPosition = jpegReader.BaseStream.Position; //TODO: replace this with a loop which knows how much data to expect while (true) { #region Inform caller of decode progress if (ProgressUpdateMethod != null) { if (jpegReader.BaseStream.Position >= lastPosition + JpegDecoder.ProgressUpdateByteInterval) { lastPosition = jpegReader.BaseStream.Position; ProgressUpdateMethod(lastPosition); } } #endregion try { // Loop though capturing MCU, instruct each // component to read in its necessary count, for // scaling factors the components automatically // read in how much they need // Sec A.2.2 from CCITT Rec. T.81 (1992 E) bool interleaved = !(numberOfComponents == 1); if (!interleaved) { JpegComponent comp = Scan.GetComponentById(componentSelector[0]); comp.SetBlock(mcuIndex); comp.DecodeMCU(jpegReader, h, v); int mcus_per_line = mcus_per_row(comp); int blocks_per_line = (int)Math.Ceiling((double)this.Width / (8 * comp.factorH)); // TODO: Explain the non-interleaved scan ------ h++; x++; if (h == comp.factorH) { h = 0; mcuIndex++; } if ((x % mcus_per_line) == 0) { x = 0; v++; if (v == comp.factorV) { if (h != 0) { mcuIndex++; h = 0; } v = 0; } else { mcuIndex -= blocks_per_line; // we were mid-block if (h != 0) { mcuIndex++; h = 0; } } } // ----------------------------------------------- } else // Components are interleaved { for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) { JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]); comp.SetBlock(mcuTotalIndex); for (int j = 0; j < comp.factorV; j++) { for (int i = 0; i < comp.factorH; i++) { comp.DecodeMCU(jpegReader, i, j); } } } mcuIndex++; mcuTotalIndex++; } } // We've found a marker, see if the marker is a restart // marker or just the next marker in the stream. If // it's the next marker in the stream break out of the // while loop, if it's just a restart marker skip it catch (JPEGMarkerFoundException ex) { marker = ex.Marker; // Handle JPEG Restart Markers, this is where the // count of MCU's per interval is compared with // the count actually obtained, if it's short then // pad on some MCU's ONLY for components that are // greater than one. Also restart the DC prediction // to zero. if (marker == JPEGMarker.RST0 || marker == JPEGMarker.RST1 || marker == JPEGMarker.RST2 || marker == JPEGMarker.RST3 || marker == JPEGMarker.RST4 || marker == JPEGMarker.RST5 || marker == JPEGMarker.RST6 || marker == JPEGMarker.RST7) { for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) { JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]); if (compIndex > 1) { comp.padMCU(mcuTotalIndex, resetInterval - mcuIndex); } comp.resetInterval(); } mcuTotalIndex += (resetInterval - mcuIndex); mcuIndex = 0; } else { break; // We're at the end of our scan, exit out. } } } }
public void DecodeScanBaseline(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { // Set the decode function for all the components for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) { JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]); comp.Decode = comp.DecodeBaseline; } DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); }
public void DecodeScanProgressive(byte successiveApproximation, byte startSpectralSelection, byte endSpectralSelection, byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { byte successiveHigh = (byte)(successiveApproximation >> 4); byte successiveLow = (byte)(successiveApproximation & 0x0f); if ((startSpectralSelection > endSpectralSelection) || (endSpectralSelection > 63)) { throw new Exception("Bad spectral selection."); } bool dcOnly = startSpectralSelection == 0; bool refinementScan = (successiveHigh != 0); if (dcOnly) // DC scan { if (endSpectralSelection != 0) { throw new Exception("Bad spectral selection for DC only scan."); } } else // AC scan { if (numberOfComponents > 1) { throw new Exception("Too many components for AC scan!"); } } // Set the decode function for all the components // TODO: set this for the scan and let the component figure it out for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) { JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]); comp.successiveLow = successiveLow; if (dcOnly) { if (refinementScan) // DC refine { comp.Decode = comp.DecodeDCRefine; } else // DC first { comp.Decode = comp.DecodeDCFirst; } } else { comp.spectralStart = startSpectralSelection; comp.spectralEnd = endSpectralSelection; if (refinementScan) // AC refine { comp.Decode = comp.DecodeACRefine; } else // AC first { comp.Decode = comp.DecodeACFirst; } } } DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); }
/// <summary>Figure F.16 - Reads the huffman code bit-by-bit.</summary> public int Decode(JPEGBinaryReader JPEGStream) { int i = 0; short code = (short)JPEGStream.ReadBits(1); while (code > maxcode[i]) { i++; code <<= 1; code |= (short)JPEGStream.ReadBits(1); } int val = huffval[code + (valptr[i])]; if (val < 0) val = 256 + val; return val; }
public void DecodeBaseline(JPEGBinaryReader stream, float[] dest) { float dc = decode_dc_coefficient(stream); decode_ac_coefficients(stream, dest); dest[0] = dc; }