/// <summary>Figure F.16 - Reads the huffman code bit-by-bit.</summary> public JpegReadStatusInt Decode(JpegBinaryReader jpegStream) { int i = 0; var readState = jpegStream.ReadBits(1); if (readState.Status != Status.Success) { return(readState); } short code = (short)readState.Result; while (code > maxcode[i]) { i++; code <<= 1; readState = jpegStream.ReadBits(1); if (readState.Status != Status.Success) { return(readState); } code |= (short)readState.Result; } readState.Result = huffval[code + (valptr[i])]; if (readState.Result < 0) { readState.Result = 256 + readState.Result; } readState.Status = Status.Success; return(readState); }
public JpegReadStatusInt DecodeACFirst(JpegBinaryReader stream, float[] zz) { if (stream.eobRun > 0) { stream.eobRun--; return(JpegReadStatusInt.GetSuccess()); } for (int k = spectralStart; k <= spectralEnd; k++) { var status = ACTable.Decode(stream); if (status.Status != Status.Success) { return(status); } int s = status.Result; int r = s >> 4; s &= 15; if (s != 0) { k += r; status = stream.ReadBits(s); if (status.Status != Status.Success) { return(status); } r = status.Result; s = HuffmanTable.Extend(r, s); zz[k] = s << successiveLow; } else { if (r != 15) { stream.eobRun = 1 << r; if (r != 0) { status = stream.ReadBits(r); if (status.Status != Status.Success) { return(status); } stream.eobRun += status.Result; } stream.eobRun--; break; } k += 15; } } return(JpegReadStatusInt.GetSuccess()); }
public JpegDecoder(Stream input) { jpegReader = new JpegBinaryReader(input); JpegReadStatusByte status; marker = (status = jpegReader.GetNextMarker()).Result; if (status.Status != Status.MarkerFound || status.Result != JpegMarker.SOI) { throw new Exception("Failed to find SOI marker."); } }
public JpegReadStatusInt DecodeDCRefine(JpegBinaryReader stream, float[] dest) { var status = stream.ReadBits(1); if (status.Status != Status.Success) { return(status); } if (status.Result == 1) { dest[0] = (int)dest[0] | (1 << successiveLow); } return(JpegReadStatusInt.GetSuccess()); }
public JpegReadStatusInt DecodeBaseline(JpegBinaryReader stream, float[] dest) { float dc; var status = decode_dc_coefficient(stream, out dc); if (status.Status != Status.Success) { return(status); } status = decode_ac_coefficients(stream, dest); if (status.Status == Status.Success) { dest[0] = dc; } return(status); }
/// <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> /// <param name="diff">The DC coefficient</param> /// <returns>The result of the read</returns> public JpegReadStatusInt decode_dc_coefficient(JpegBinaryReader jpegStream, out float diff) { diff = 0; var status = DCTable.Decode(jpegStream); if (status.Status != Status.Success) { return(status); } int t = status.Result; status = jpegStream.ReadBits(t); if (status.Status != Status.Success) { return(status); } diff = HuffmanTable.Extend(status.Result, t); diff = (previousDC + diff); previousDC = diff; return(status); }
public void Decode(byte[][][] rasterOutput) { // This assumes that the stream contains only a single frame. var jpegReader = new JpegBinaryReader(input); JpegFrame frame = context.JpegFrame; // Not relevant byte marker = JpegMarker.XFF; const int resetInterval = 255; frame.DecodeScan(FrameDefaults.NumberOfComponents, FrameDefaults.CompId, resetInterval, jpegReader, ref marker); // Only one frame, JPEG Non-Hierarchical Frame. // byte[][,] raster = Image.CreateRasterBuffer(frame.Width, frame.Height, frame.ComponentCount); IList <JpegComponent> components = frame.Scan.Components; // parse.Stop(); for (int i = 0; i < components.Count; i++) { JpegComponent comp = components[i]; // 1. Quantize // comp.QuantizationTable = qTables[comp.quant_id].Table; // Only the AAN needs this. The quantization step is built into the other IDCT implementations if (JpegConstants.SelectedIdct != IdctImplementation.AAN) { comp.QuantizeData(); } // 2. Run iDCT (expensive) // idct.Start(); comp.IdctData(); // idct.Stop(); // 3. Scale the image and write the data to the raster. comp.WriteDataScaled(rasterOutput, i, BlockUpsamplingMode); } }
/// <summary> /// Generated from text on F-23, F.13 - Huffman decoded of AC coefficients /// on ISO DIS 10918-1. Requirements and Guidelines. /// </summary> internal JpegReadStatusInt decode_ac_coefficients(JpegBinaryReader jpegStream, float[] zz) { var status = new JpegReadStatusInt(); for (int k = 1; k < 64; k++) { status = ACTable.Decode(jpegStream); if (status.Status != Status.Success) { return(status); } int s = status.Result; int r = s >> 4; s &= 15; if (s != 0) { k += r; status = jpegStream.ReadBits(s); if (status.Status != Status.Success) { return(status); } s = HuffmanTable.Extend(status.Result, s); zz[k] = s; } else { if (r != 15) { //throw new JPEGMarkerFoundException(); return(status); } k += 15; } } return(status); }
public JpegReadStatusInt DecodeDCFirst(JpegBinaryReader stream, float[] dest) { var status = DCTable.Decode(stream); if (status.Status != Status.Success) { return(status); // We reached the end of the stream. } int s = status.Result; status = stream.ReadBits(s); if (status.Status != Status.Success) { return(status); } int r = status.Result; s = HuffmanTable.Extend(r, s); s = (int)previousDC + s; previousDC = s; dest[0] = s << successiveLow; return(status); }
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 bool DecodeScanProgressive(byte successiveApproximation, byte startSpectralSelection, byte endSpectralSelection, byte numberOfComponents, byte[] componentSelector, int resetInterval, JpegBinaryReader jpegReader, ref byte marker) { var successiveHigh = (byte)(successiveApproximation >> 4); var 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); return(true); }
public void DecodeScan(byte numberOfComponents, byte[] componentSelector, int resetInterval, JpegBinaryReader jpegReader, ref byte marker) { //TODO: not necessary jpegReader.eobRun = 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; foreach (JpegComponent component in Scan.Components) { component.Reset(); } //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 // 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) { #region Non-Interleaved (less common) JpegComponent comp = Scan.GetComponentById(componentSelector[0]); comp.SetBlock(mcuIndex); var status = comp.DecodeMCU(jpegReader, h, v); if (status.Status == Status.EOF) { return; } int mcusPerLine = mcus_per_row(comp); var blocksPerLine = (int)Math.Ceiling((double)Width / (8 * comp.factorH)); // TODO: Explain the non-interleaved scan ------ h++; x++; if (h == comp.factorH) { h = 0; mcuIndex++; } if ((x % mcusPerLine) == 0) { x = 0; v++; if (v == comp.factorV) { if (h != 0) { mcuIndex++; h = 0; } v = 0; } else { mcuIndex -= blocksPerLine; // we were mid-block if (h != 0) { mcuIndex++; h = 0; } } } // ----------------------------------------------- #endregion } else // Components are interleaved { #region Interleaved (more common) 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++) { // Decode the MCU var status = comp.DecodeMCU(jpegReader, i, j); if (status.Status == Status.EOF) { return; } if (status.Status == Status.MarkerFound) { // 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 marker = (byte)status.Result; // 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 compIndex2 = 0; compIndex2 < numberOfComponents; compIndex2++) { JpegComponent comp2 = Scan.GetComponentById(componentSelector[compIndex]); if (compIndex2 > 1) { comp2.padMCU(mcuTotalIndex, resetInterval - mcuIndex); } comp2.resetInterval(); } mcuTotalIndex += (resetInterval - mcuIndex); mcuIndex = 0; } else { return; // We're at the end of our scan, exit out. } } } } } mcuIndex++; mcuTotalIndex++; #endregion } } }
public JpegReadStatusInt DecodeMCU(JpegBinaryReader jpegReader, int i, int j) { return(Decode(jpegReader, scanMCUs[i][j])); }
public JpegReadStatusInt DecodeACRefine(JpegBinaryReader stream, float[] dest) { int p1 = 1 << successiveLow; int m1 = (-1) << successiveLow; int k = spectralStart; if (stream.eobRun == 0) { for (; k <= spectralEnd; k++) { #region Decode and check S var status = ACTable.Decode(stream); if (status.Status != Status.Success) { return(status); } int s = status.Result; int r = s >> 4; s &= 15; if (s != 0) { if (s != 1) { throw new Exception("Decode Error"); } status = stream.ReadBits(1); if (status.Status != Status.Success) { return(status); } s = status.Result == 1 ? p1 : m1; } else { if (r != 15) { stream.eobRun = 1 << r; if (r > 0) { status = stream.ReadBits(r); if (status.Status != Status.Success) { return(status); } stream.eobRun += status.Result; } break; } } // if (s != 0) #endregion // Apply the update do { if (dest[k] != 0) { status = stream.ReadBits(1); if (status.Status != Status.Success) { return(status); } if (status.Result == 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.eobRun > 0) { for (; k <= spectralEnd; k++) { if (dest[k] != 0) { var status = stream.ReadBits(1); if (status.Status != Status.Success) { return(status); } if (status.Result == 1) { if (((int)dest[k] & p1) == 0) { if (dest[k] >= 0) { dest[k] += p1; } else { dest[k] += m1; } } } } } stream.eobRun--; } return(JpegReadStatusInt.GetSuccess()); }