public void AddComponent(byte id, byte factorHorizontal, byte factorVertical, byte quantizationID, byte colorMode) { JpegComponent item = new JpegComponent(this, id, factorHorizontal, factorVertical, quantizationID, colorMode); components.Add(item); maxH = components.Max((JpegComponent x) => x.factorH); maxV = components.Max((JpegComponent x) => x.factorV); }
public void DecodeScanBaseline(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { for (int i = 0; i < numberOfComponents; i++) { JpegComponent componentById = Scan.GetComponentById(componentSelector[i]); componentById.Decode = componentById.DecodeBaseline; } DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); }
public void AddComponent(byte id, byte factorHorizontal, byte factorVertical, byte quantizationID, byte colorMode) { JpegComponent item = new JpegComponent(this, id, factorHorizontal, factorVertical, quantizationID, colorMode); this.components.Add(item); this.maxH = this.components.Max<JpegComponent, byte>(delegate (JpegComponent x) { return x.factorH; }); this.maxV = this.components.Max<JpegComponent, byte>(delegate (JpegComponent x) { return x.factorV; }); }
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); }
//private void DecodeScan(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) //{ // jpegReader.eob_run = 0; // int idx = 0; // int num2 = 0; // int i = 0; // int j = 0; // int num5 = 0; // long position = jpegReader.BaseStream.Position; // while (true) // { // JpegComponent componentById; // int num9; // if ((this.ProgressUpdateMethod != null) && (jpegReader.BaseStream.Position >= (position + JpegDecoder.ProgressUpdateByteInterval))) // { // position = jpegReader.BaseStream.Position; // this.ProgressUpdateMethod(position); // } // try // { // if (numberOfComponents == 1) // { // componentById = this.Scan.GetComponentById(componentSelector[0]); // componentById.SetBlock(idx); // componentById.DecodeMCU(jpegReader, i, j); // int num7 = this.mcus_per_row(componentById); // int num8 = (int) Math.Ceiling(((double) this.Width) / ((double) (8 * componentById.factorH))); // i++; // num5++; // if (i == componentById.factorH) // { // i = 0; // idx++; // } // if ((num5 % num7) == 0) // { // num5 = 0; // j++; // if (j == componentById.factorV) // { // if (i != 0) // { // idx++; // i = 0; // } // j = 0; // } // else // { // idx -= num8; // if (i != 0) // { // idx++; // i = 0; // } // } // } // } // else // { // num9 = 0; // while (num9 < numberOfComponents) // { // componentById = this.Scan.GetComponentById(componentSelector[num9]); // componentById.SetBlock(num2); // for (int k = 0; k < componentById.factorV; k++) // { // for (int m = 0; m < componentById.factorH; m++) // { // componentById.DecodeMCU(jpegReader, m, k); // } // } // num9++; // } // idx++; // num2++; // } // } // catch (JPEGMarkerFoundException exception) // { // marker = exception.Marker; // if (((((marker != 0xd0) && (marker != 0xd1)) && ((marker != 210) && (marker != 0xd3))) && (((marker != 0xd4) && (marker != 0xd5)) && (marker != 0xd6))) && (marker != 0xd7)) // { // return; // } // for (num9 = 0; num9 < numberOfComponents; num9++) // { // componentById = this.Scan.GetComponentById(componentSelector[num9]); // if (num9 > 1) // { // componentById.padMCU(num2, resetInterval - idx); // } // componentById.resetInterval(); // } // num2 += resetInterval - idx; // idx = 0; // } // } //} //public void DecodeScanBaseline(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) //{ // for (int i = 0; i < numberOfComponents; i++) // { // JpegComponent componentById = this.Scan.GetComponentById(componentSelector[i]); // componentById.Decode = new JpegComponent.DecodeFunction(componentById.DecodeBaseline); // } // this.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 num = (byte)(successiveApproximation >> 4); byte num2 = (byte)(successiveApproximation & 15); if ((startSpectralSelection > endSpectralSelection) || (endSpectralSelection > 0x3f)) { throw new Exception("Bad spectral selection."); } bool flag = startSpectralSelection == 0; bool flag2 = num != 0; if (flag) { if (endSpectralSelection != 0) { throw new Exception("Bad spectral selection for DC only scan."); } } else if (numberOfComponents > 1) { throw new Exception("Too many components for AC scan!"); } for (int i = 0; i < numberOfComponents; i++) { JpegComponent componentById = this.Scan.GetComponentById(componentSelector[i]); componentById.successiveLow = num2; if (flag) { if (flag2) { componentById.Decode = new JpegComponent.DecodeFunction(componentById.DecodeDCRefine); } else { componentById.Decode = new JpegComponent.DecodeFunction(componentById.DecodeDCFirst); } } else { componentById.spectralStart = startSpectralSelection; componentById.spectralEnd = endSpectralSelection; if (flag2) { componentById.Decode = new JpegComponent.DecodeFunction(componentById.DecodeACRefine); } else { componentById.Decode = new JpegComponent.DecodeFunction(componentById.DecodeACFirst); } } } // this.DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); }
public void AddComponent(byte id, byte factorHorizontal, byte factorVertical, byte quantizationID, byte colorMode) { JpegComponent component = new JpegComponent(this, id, factorHorizontal, factorVertical, quantizationID, colorMode); components.Add(component); // Defined in Annex A maxH = components.Max(x => x.factorH); maxV = components.Max(x => x.factorV); }
public void AddComponent(byte id, byte factorHorizontal, byte factorVertical, byte quantizationID, byte colorMode) { JpegComponent item = new JpegComponent(this, id, factorHorizontal, factorVertical, quantizationID, colorMode); this.components.Add(item); this.maxH = this.components.Max <JpegComponent, byte>(delegate(JpegComponent x) { return(x.factorH); }); this.maxV = this.components.Max <JpegComponent, byte>(delegate(JpegComponent x) { return(x.factorV); }); }
public void AddComponent(byte id, byte factorHorizontal, byte factorVertical, byte quantizationID, byte colorMode) { JpegComponent component = new JpegComponent( this, id, factorHorizontal, factorVertical, quantizationID, colorMode); components.Add(component); // Defined in Annex A maxH = components.Max(x => x.factorH); maxV = components.Max(x => x.factorV); }
public void DecodeScanProgressive(byte successiveApproximation, byte startSpectralSelection, byte endSpectralSelection, byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { byte b = (byte)(successiveApproximation >> 4); byte successiveLow = (byte)(successiveApproximation & 0xF); if (startSpectralSelection > endSpectralSelection || endSpectralSelection > 63) { throw new Exception("Bad spectral selection."); } bool flag = startSpectralSelection == 0; bool flag2 = b != 0; if (flag) { if (endSpectralSelection != 0) { throw new Exception("Bad spectral selection for DC only scan."); } } else if (numberOfComponents > 1) { throw new Exception("Too many components for AC scan!"); } for (int i = 0; i < numberOfComponents; i++) { JpegComponent componentById = Scan.GetComponentById(componentSelector[i]); componentById.successiveLow = successiveLow; if (flag) { if (flag2) { componentById.Decode = componentById.DecodeDCRefine; } else { componentById.Decode = componentById.DecodeDCFirst; } continue; } componentById.spectralStart = startSpectralSelection; componentById.spectralEnd = endSpectralSelection; if (flag2) { componentById.Decode = componentById.DecodeACRefine; } else { componentById.Decode = componentById.DecodeACFirst; } } DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); }
public void setHuffmanTables(byte componentID, JpegHuffmanTable ACTable, JpegHuffmanTable DCTable) { JpegComponent comp = Scan.GetComponentById(componentID); if (DCTable != null) { comp.setDCTable(DCTable); } if (ACTable != null) { comp.setACTable(ACTable); } }
public DecodedJpeg Decode() { // The frames in this jpeg are loaded into a list. There is // usually just one frame except in heirarchial progression where // there are multiple frames. JPEGFrame frame = null; // The restart interval defines how many MCU's we should have // between the 8-modulo restart marker. The restart markers allow // us to tell whether or not our decoding process is working // correctly, also if there is corruption in the image we can // recover with these restart intervals. (See RSTm DRI). int resetInterval = 0; bool haveMarker = false; bool foundJFIF = false; List <JpegHeader> headers = new List <JpegHeader>(); // Loop through until there are no more markers to read in, at // that point everything is loaded into the jpegFrames array and // can be processed. while (true) { #region Switch over marker types switch (marker) { case JPEGMarker.APP0: // APP1 is used for EXIF data case JPEGMarker.APP1: // Seldomly, APP2 gets used for extended EXIF, too case JPEGMarker.APP2: case JPEGMarker.APP3: case JPEGMarker.APP4: case JPEGMarker.APP5: case JPEGMarker.APP6: case JPEGMarker.APP7: case JPEGMarker.APP8: case JPEGMarker.APP9: case JPEGMarker.APP10: case JPEGMarker.APP11: case JPEGMarker.APP12: case JPEGMarker.APP13: case JPEGMarker.APP14: case JPEGMarker.APP15: // COM: Comment case JPEGMarker.COM: // Debug.WriteLine(string.Format("Extracting Header, Type={0:X}", marker)); JpegHeader header = ExtractHeader(); #region Check explicitly for Exif Data if (header.Marker == JPEGMarker.APP1 && header.Data.Length >= 6) { byte[] d = header.Data; if (d[0] == 'E' && d[1] == 'x' && d[2] == 'i' && d[3] == 'f' && d[4] == 0 && d[5] == 0) { // Exif. Do something? } } #endregion #region Check for Adobe header if (header.Data.Length >= 5 && header.Marker == JPEGMarker.APP14) { string asText = UTF8Encoding.UTF8.GetString(header.Data, 0, 5); if (asText == "Adobe") { // ADOBE HEADER. Do anything? } } #endregion headers.Add(header); if (!foundJFIF && marker == JPEGMarker.APP0) { foundJFIF = TryParseJFIF(header.Data); if (foundJFIF) // Found JFIF... do JFIF extension follow? { header.IsJFIF = true; marker = jpegReader.GetNextMarker(); // Yes, they do. if (marker == JPEGMarker.APP0) { header = ExtractHeader(); headers.Add(header); } else // No. Delay processing this one. { haveMarker = true; } } } break; case JPEGMarker.SOF0: case JPEGMarker.SOF2: // SOFn Start of Frame Marker, Baseline DCT - This is the start // of the frame header that defines certain variables that will // be carried out through the rest of the encoding. Multiple // frames are used in a hierarchical system, however most JPEG's // only contain a single frame. // Progressive or baseline? progressive = marker == JPEGMarker.SOF2; jpegFrames.Add(new JPEGFrame()); frame = (JPEGFrame)jpegFrames[jpegFrames.Count - 1]; frame.ProgressUpdateMethod = new Action <long>(UpdateStreamProgress); // Skip the frame length. jpegReader.ReadShort(); // Bits percision, either 8 or 12. frame.setPrecision(jpegReader.ReadByte()); // Scan lines (height) frame.ScanLines = jpegReader.ReadShort(); // Scan samples per line (width) frame.SamplesPerLine = jpegReader.ReadShort(); // Number of Color Components (channels). frame.ComponentCount = jpegReader.ReadByte(); DecodeProgress.Height = frame.Height; DecodeProgress.Width = frame.Width; DecodeProgress.SizeReady = true; if (DecodeProgressChanged != null) { DecodeProgressChanged(this, DecodeProgress); } // Add all of the necessary components to the frame. for (int i = 0; i < frame.ComponentCount; i++) { byte compId = jpegReader.ReadByte(); byte sampleFactors = jpegReader.ReadByte(); byte qTableId = jpegReader.ReadByte(); byte sampleHFactor = (byte)(sampleFactors >> 4); byte sampleVFactor = (byte)(sampleFactors & 0x0f); frame.AddComponent(compId, sampleHFactor, sampleVFactor, qTableId); } break; case JPEGMarker.DHT: // DHT non-SOF Marker - Huffman Table is required for decoding // the JPEG stream, when we receive a marker we load in first // the table length (16 bits), the table class (4 bits), table // identifier (4 bits), then we load in 16 bytes and each byte // represents the count of bytes to load in for each of the 16 // bytes. We load this into an array to use later and move on 4 // huffman tables can only be used in an image. int huffmanLength = (jpegReader.ReadShort() - 2); // Keep looping until we are out of length. int index = huffmanLength; // Multiple tables may be defined within a DHT marker. This // will keep reading until there are no tables left, most // of the time there are just one tables. while (index > 0) { // Read the identifier information and class // information about the Huffman table, then read the // 16 byte codelength in and read in the Huffman values // and put it into table info. byte huffmanInfo = jpegReader.ReadByte(); byte tableClass = (byte)(huffmanInfo >> 4); byte huffmanIndex = (byte)(huffmanInfo & 0x0f); short[] codeLength = new short[16]; for (int i = 0; i < codeLength.Length; i++) { codeLength[i] = jpegReader.ReadByte(); } int huffmanValueLen = 0; for (int i = 0; i < 16; i++) { huffmanValueLen += codeLength[i]; } index -= (huffmanValueLen + 17); short[] huffmanVal = new short[huffmanValueLen]; for (int i = 0; i < huffmanVal.Length; i++) { huffmanVal[i] = jpegReader.ReadByte(); } // Assign DC Huffman Table. if (tableClass == HuffmanTable.JPEG_DC_TABLE) { dcTables[(int)huffmanIndex] = new JpegHuffmanTable(codeLength, huffmanVal); } // Assign AC Huffman Table. else if (tableClass == HuffmanTable.JPEG_AC_TABLE) { acTables[(int)huffmanIndex] = new JpegHuffmanTable(codeLength, huffmanVal); } } break; case JPEGMarker.DQT: // DQT non-SOF Marker - This defines the quantization // coeffecients, this allows us to figure out the quality of // compression and unencode the data. The data is loaded and // then stored in to an array. short quantizationLength = (short)(jpegReader.ReadShort() - 2); for (int j = 0; j < quantizationLength / 65; j++) { byte quantSpecs = jpegReader.ReadByte(); int[] quantData = new int[64]; if ((byte)(quantSpecs >> 4) == 0) // Precision 8 bit. { for (int i = 0; i < 64; i++) { quantData[i] = jpegReader.ReadByte(); } } else if ((byte)(quantSpecs >> 4) == 1) // Precision 16 bit. { for (int i = 0; i < 64; i++) { quantData[i] = jpegReader.ReadShort(); } } qTables[(int)(quantSpecs & 0x0f)] = new JpegQuantizationTable(quantData); } break; case JPEGMarker.SOS: Debug.WriteLine("Start of Scan (SOS)"); // SOS non-SOF Marker - Start Of Scan Marker, this is where the // actual data is stored in a interlaced or non-interlaced with // from 1-4 components of color data, if three components most // likely a YCrCb model, this is a fairly complex process. // Read in the scan length. //ushort scanLen = jpegReader.ReadShort(); // Number of components in the scan. byte numberOfComponents = jpegReader.ReadByte(); byte[] componentSelector = new byte[numberOfComponents]; for (int i = 0; i < numberOfComponents; i++) { // Component ID, packed byte containing the Id for the // AC table and DC table. byte componentID = jpegReader.ReadByte(); byte tableInfo = jpegReader.ReadByte(); int DC = (tableInfo >> 4) & 0x0f; int AC = (tableInfo) & 0x0f; frame.setHuffmanTables(componentID, acTables[(byte)AC], dcTables[(byte)DC]); componentSelector[i] = componentID; } byte startSpectralSelection = jpegReader.ReadByte(); byte endSpectralSelection = jpegReader.ReadByte(); byte successiveApproximation = jpegReader.ReadByte(); #region Baseline JPEG Scan Decoding if (!progressive) { frame.DecodeScanBaseline(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); haveMarker = true; // use resultant marker for the next switch(..) } #endregion #region Progressive JPEG Scan Decoding if (progressive) { frame.DecodeScanProgressive( successiveApproximation, startSpectralSelection, endSpectralSelection, numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker); haveMarker = true; // use resultant marker for the next switch(..) } #endregion break; case JPEGMarker.DRI: jpegReader.BaseStream.Seek(2, System.IO.SeekOrigin.Current); resetInterval = jpegReader.ReadShort(); break; // Defines the number of lines. (Not usually present) case JPEGMarker.DNL: frame.ScanLines = jpegReader.ReadShort(); break; // End of Image. Finish the decode. case JPEGMarker.EOI: if (jpegFrames.Count == 0) { throw new NotSupportedException("No JPEG frames could be located."); } else if (jpegFrames.Count == 1) { // Only one frame, JPEG Non-Heirarchial Frame. byte[][,] raster = Image.CreateRaster(frame.Width, frame.Height, frame.ComponentCount); IList <JpegComponent> components = frame.Scan.Components; int totalSteps = components.Count * 3; // Three steps per loop int stepsFinished = 0; for (int i = 0; i < components.Count; i++) { JpegComponent comp = components[i]; comp.QuantizationTable = qTables[comp.quant_id].Table; // 1. Quantize comp.quantizeData(); UpdateProgress(++stepsFinished, totalSteps); // 2. Run iDCT (expensive) comp.idctData(); UpdateProgress(++stepsFinished, totalSteps); // 3. Scale the image and write the data to the raster. comp.writeDataScaled(raster, i, BlockUpsamplingMode); UpdateProgress(++stepsFinished, totalSteps); // Ensure garbage collection. comp = null; GC.Collect(); } // Grayscale Color Image (1 Component). if (frame.ComponentCount == 1) { ColorModel cm = new ColorModel() { ColorSpace = ColorSpace.Gray, Opaque = true }; image = new Image(cm, raster); } // YCbCr Color Image (3 Components). else if (frame.ComponentCount == 3) { ColorModel cm = new ColorModel() { ColorSpace = ColorSpace.YCbCr, Opaque = true }; image = new Image(cm, raster); } // Possibly CMYK or RGBA ? else { throw new NotSupportedException("Unsupported Color Mode: 4 Component Color Mode found."); } // If needed, convert centimeters to inches. Func <double, double> conv = x => Units == UnitType.Inches ? x : x / 2.54; image.DensityX = conv(XDensity); image.DensityY = conv(YDensity); //height = frame.Height; //width = frame.Width; } else { // JPEG Heirarchial Frame throw new NotSupportedException("Unsupported Codec Type: Hierarchial JPEG"); } break; // Only SOF0 (baseline) and SOF2 (progressive) are supported by FJCore case JPEGMarker.SOF1: case JPEGMarker.SOF3: case JPEGMarker.SOF5: case JPEGMarker.SOF6: case JPEGMarker.SOF7: case JPEGMarker.SOF9: case JPEGMarker.SOF10: case JPEGMarker.SOF11: case JPEGMarker.SOF13: case JPEGMarker.SOF14: case JPEGMarker.SOF15: throw new NotSupportedException("Unsupported codec type."); default: break; // ignore } #endregion switch over markers if (haveMarker) { haveMarker = false; } else { try { marker = jpegReader.GetNextMarker(); } catch (System.IO.EndOfStreamException) { break; /* done reading the file */ } } } DecodedJpeg result = new DecodedJpeg(image, headers); return(result); }
public int mcus_per_row(JpegComponent c) { return(((Width * c.factorH + (Scan.MaxH - 1)) / Scan.MaxH + 7) / 8); }
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. } } } }
private int mcus_per_row(JpegComponent c) { return(((((Width * c.factorH) + (Scan.MaxH - 1)) / Scan.MaxH) + 7) / 8); }
public void DecodeScan(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker) { jpegReader.eob_run = 0; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; long position = jpegReader.BaseStream.Position; while (true) { if (ProgressUpdateMethod != null && jpegReader.BaseStream.Position >= position + JpegDecoder.ProgressUpdateByteInterval) { position = jpegReader.BaseStream.Position; ProgressUpdateMethod(position); } try { if (numberOfComponents == 1) { JpegComponent componentById = Scan.GetComponentById(componentSelector[0]); componentById.SetBlock(num); componentById.DecodeMCU(jpegReader, num3, num4); int num6 = mcus_per_row(componentById); int num7 = (int)Math.Ceiling((double)(int)Width / (double)(8 * componentById.factorH)); num3++; num5++; if (num3 == componentById.factorH) { num3 = 0; num++; } if (num5 % num6 == 0) { num5 = 0; num4++; if (num4 == componentById.factorV) { if (num3 != 0) { num++; num3 = 0; } num4 = 0; } else { num -= num7; if (num3 != 0) { num++; num3 = 0; } } } } else { for (int i = 0; i < numberOfComponents; i++) { JpegComponent componentById2 = Scan.GetComponentById(componentSelector[i]); componentById2.SetBlock(num2); for (int j = 0; j < componentById2.factorV; j++) { for (int k = 0; k < componentById2.factorH; k++) { componentById2.DecodeMCU(jpegReader, k, j); } } } num++; num2++; } } catch (JPEGMarkerFoundException ex) { marker = ex.Marker; if (marker != 208 && marker != 209 && marker != 210 && marker != 211 && marker != 212 && marker != 213 && marker != 214 && marker != 215) { return; } for (int l = 0; l < numberOfComponents; l++) { JpegComponent componentById3 = Scan.GetComponentById(componentSelector[l]); if (l > 1) { componentById3.padMCU(num2, resetInterval - num); } componentById3.resetInterval(); } num2 += resetInterval - num; num = 0; } } }
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); }
private int mcus_per_row(JpegComponent c) { return (((( Width * c.factorH ) + ( Scan.MaxH - 1)) / Scan.MaxH) + 7) / 8; }
public DecodedJpeg Decode() { JPEGFrame jPEGFrame = null; int resetInterval = 0; bool flag = false; bool flag2 = false; List <JpegHeader> list = new List <JpegHeader>(); while (true) { if (DecodeProgress.Abort) { return(null); } switch (marker) { case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 254: { JpegHeader jpegHeader = ExtractHeader(); if (jpegHeader.Marker == 225 && jpegHeader.Data.Length >= 6) { byte[] data = jpegHeader.Data; if (data[0] == 69 && data[1] == 120 && data[2] == 105 && data[3] == 102 && data[4] == 0) { _ = data[5]; } } if (jpegHeader.Data.Length >= 5 && jpegHeader.Marker == 238) { _ = (Encoding.UTF8.GetString(jpegHeader.Data, 0, 5) == "Adobe"); } list.Add(jpegHeader); if (flag2 || marker != 224) { break; } flag2 = TryParseJFIF(jpegHeader.Data); if (flag2) { jpegHeader.IsJFIF = true; marker = jpegReader.GetNextMarker(); if (marker == 224) { jpegHeader = ExtractHeader(); list.Add(jpegHeader); } else { flag = true; } } break; } case 192: case 194: { progressive = (marker == 194); jpegFrames.Add(new JPEGFrame()); jPEGFrame = jpegFrames[jpegFrames.Count - 1]; jPEGFrame.ProgressUpdateMethod = UpdateStreamProgress; jpegReader.ReadShort(); jPEGFrame.setPrecision(jpegReader.ReadByte()); jPEGFrame.ScanLines = jpegReader.ReadShort(); jPEGFrame.SamplesPerLine = jpegReader.ReadShort(); jPEGFrame.ComponentCount = jpegReader.ReadByte(); DecodeProgress.Height = jPEGFrame.Height; DecodeProgress.Width = jPEGFrame.Width; DecodeProgress.SizeReady = true; if (this.DecodeProgressChanged != null) { this.DecodeProgressChanged(this, DecodeProgress); if (DecodeProgress.Abort) { return(null); } } for (int m = 0; m < jPEGFrame.ComponentCount; m++) { byte componentID = jpegReader.ReadByte(); byte num5 = jpegReader.ReadByte(); byte quantizationTableID = jpegReader.ReadByte(); byte sampleHFactor = (byte)(num5 >> 4); byte sampleVFactor = (byte)(num5 & 0xF); jPEGFrame.AddComponent(componentID, sampleHFactor, sampleVFactor, quantizationTableID); } break; } case 196: { int num2 = jpegReader.ReadShort() - 2; while (num2 > 0) { byte num3 = jpegReader.ReadByte(); byte b = (byte)(num3 >> 4); byte b2 = (byte)(num3 & 0xF); short[] array = new short[16]; for (int j = 0; j < array.Length; j++) { array[j] = jpegReader.ReadByte(); } int num4 = 0; for (int k = 0; k < 16; k++) { num4 += array[k]; } num2 -= num4 + 17; short[] array2 = new short[num4]; for (int l = 0; l < array2.Length; l++) { array2[l] = jpegReader.ReadByte(); } if (b == HuffmanTable.JPEG_DC_TABLE) { dcTables[b2] = new JpegHuffmanTable(array, array2); } else if (b == HuffmanTable.JPEG_AC_TABLE) { acTables[b2] = new JpegHuffmanTable(array, array2); } } break; } case 219: { short num9 = (short)(jpegReader.ReadShort() - 2); for (int num10 = 0; num10 < num9 / 65; num10++) { byte b5 = jpegReader.ReadByte(); int[] array4 = new int[64]; if ((byte)(b5 >> 4) == 0) { for (int num11 = 0; num11 < 64; num11++) { array4[num11] = jpegReader.ReadByte(); } } else if ((byte)(b5 >> 4) == 1) { for (int num12 = 0; num12 < 64; num12++) { array4[num12] = jpegReader.ReadShort(); } } qTables[b5 & 0xF] = new JpegQuantizationTable(array4); } break; } case 218: { jpegReader.ReadShort(); byte b3 = jpegReader.ReadByte(); byte[] array3 = new byte[b3]; for (int n = 0; n < b3; n++) { byte b4 = jpegReader.ReadByte(); byte num6 = jpegReader.ReadByte(); int num7 = (num6 >> 4) & 0xF; int num8 = num6 & 0xF; jPEGFrame.setHuffmanTables(b4, acTables[(byte)num8], dcTables[(byte)num7]); array3[n] = b4; } byte startSpectralSelection = jpegReader.ReadByte(); byte endSpectralSelection = jpegReader.ReadByte(); byte successiveApproximation = jpegReader.ReadByte(); if (!progressive) { jPEGFrame.DecodeScanBaseline(b3, array3, resetInterval, jpegReader, ref marker); flag = true; } if (progressive) { jPEGFrame.DecodeScanProgressive(successiveApproximation, startSpectralSelection, endSpectralSelection, b3, array3, resetInterval, jpegReader, ref marker); flag = true; } break; } case 221: jpegReader.BaseStream.Seek(2L, SeekOrigin.Current); resetInterval = jpegReader.ReadShort(); break; case 220: jPEGFrame.ScanLines = jpegReader.ReadShort(); break; case 217: { if (jpegFrames.Count == 0) { throw new NotSupportedException("No JPEG frames could be located."); } if (jpegFrames.Count > 1) { jPEGFrame = jpegFrames.OrderByDescending((JPEGFrame f) => f.Width * f.Height).FirstOrDefault(); } byte[][,] raster = Image.CreateRaster(jPEGFrame.Width, jPEGFrame.Height, jPEGFrame.ComponentCount); IList <JpegComponent> components = jPEGFrame.Scan.Components; int stepsTotal = components.Count * 3; int num = 0; for (int i = 0; i < components.Count; i++) { JpegComponent jpegComponent = components[i]; jpegComponent.QuantizationTable = qTables[jpegComponent.quant_id].Table; jpegComponent.quantizeData(); UpdateProgress(++num, stepsTotal); jpegComponent.idctData(); UpdateProgress(++num, stepsTotal); jpegComponent.writeDataScaled(raster, i, BlockUpsamplingMode); UpdateProgress(++num, stepsTotal); jpegComponent = null; GC.Collect(); } ColorModel colorModel; if (jPEGFrame.ComponentCount == 1) { colorModel = default(ColorModel); colorModel.colorspace = ColorSpace.Gray; colorModel.Opaque = true; ColorModel cm = colorModel; image = new Image(cm, raster); } else { if (jPEGFrame.ComponentCount != 3) { throw new NotSupportedException("Unsupported Color Mode: 4 Component Color Mode found."); } colorModel = default(ColorModel); colorModel.colorspace = ColorSpace.YCbCr; colorModel.Opaque = true; ColorModel cm2 = colorModel; image = new Image(cm2, raster); } Func <double, double> func = (double x) => (Units != UnitType.Inches) ? (x / 2.54) : x; image.DensityX = func((int)XDensity); image.DensityY = func((int)YDensity); break; } case 193: case 195: case 197: case 198: case 199: case 201: case 202: case 203: case 205: case 206: case 207: throw new NotSupportedException("Unsupported codec type."); } if (flag) { flag = false; } else { try { marker = jpegReader.GetNextMarker(); } catch (EndOfStreamException) { break; } } } return(new DecodedJpeg(image, list)); }