/// <summary> /// Processes the SOS (Start of scan marker). /// </summary> private void ProcessStartOfScanMarker() { int selectorsCount = this.InputStream.ReadByte(); int componentIndex = -1; for (int i = 0; i < selectorsCount; i++) { componentIndex = -1; int selector = this.InputStream.ReadByte(); for (int j = 0; j < this.Frame.ComponentIds.Length; j++) { byte id = this.Frame.ComponentIds[j]; if (selector == id) { componentIndex = j; } } if (componentIndex < 0) { throw new ImageFormatException("Unknown component selector"); } ref PdfJsFrameComponent component = ref this.Frame.Components[componentIndex]; int tableSpec = this.InputStream.ReadByte(); component.DCHuffmanTableId = tableSpec >> 4; component.ACHuffmanTableId = tableSpec & 15; }
internal void QuantizeAndInverseAllComponents() { for (int i = 0; i < this.components.Components.Length; i++) { PdfJsFrameComponent frameComponent = this.Frame.Components[i]; PdfJsComponent component = this.components.Components[i]; this.QuantizeAndInverseComponentData(component, frameComponent); } }
/// <summary> /// Processes the Start of Frame marker. Specified in section B.2.2. /// </summary> /// <param name="remaining">The remaining bytes in the segment block.</param> /// <param name="frameMarker">The current frame marker.</param> private void ProcessStartOfFrameMarker(int remaining, PdfJsFileMarker frameMarker) { if (this.Frame != null) { throw new ImageFormatException("Multiple SOF markers. Only single frame jpegs supported."); } this.InputStream.Read(this.temp, 0, remaining); this.Frame = new PdfJsFrame { Extended = frameMarker.Marker == PdfJsJpegConstants.Markers.SOF1, Progressive = frameMarker.Marker == PdfJsJpegConstants.Markers.SOF2, Precision = this.temp[0], Scanlines = (short)((this.temp[1] << 8) | this.temp[2]), SamplesPerLine = (short)((this.temp[3] << 8) | this.temp[4]), ComponentCount = this.temp[5] }; int maxH = 0; int maxV = 0; int index = 6; // No need to pool this. They max out at 4 this.Frame.ComponentIds = new byte[this.Frame.ComponentCount]; this.Frame.Components = new PdfJsFrameComponent[this.Frame.ComponentCount]; for (int i = 0; i < this.Frame.Components.Length; i++) { int h = this.temp[index + 1] >> 4; int v = this.temp[index + 1] & 15; if (maxH < h) { maxH = h; } if (maxV < v) { maxV = v; } var component = new PdfJsFrameComponent(this.Frame, this.temp[index], h, v, this.temp[index + 2], i); this.Frame.Components[i] = component; this.Frame.ComponentIds[i] = component.Id; index += 3; } this.Frame.MaxHorizontalFactor = maxH; this.Frame.MaxVerticalFactor = maxV; this.Frame.InitComponents(); }
public void ComponentScalingIsCorrect_1ChannelJpegPdfJs() { using (PdfJsJpegDecoderCore decoder = JpegFixture.ParsePdfJsStream(TestImages.Jpeg.Baseline.Jpeg400)) { Assert.Equal(1, decoder.ComponentCount); Assert.Equal(1, decoder.Components.Length); Size expectedSizeInBlocks = decoder.ImageSizeInPixels.DivideRoundUp(8); Assert.Equal(expectedSizeInBlocks, decoder.ImageSizeInMCU); var uniform1 = new Size(1, 1); PdfJsFrameComponent c0 = decoder.Components[0]; VerifyJpeg.VerifyComponent(c0, expectedSizeInBlocks, uniform1, uniform1); } }
public void PrintComponentDataPdfJs(string imageFile) { var sb = new StringBuilder(); using (PdfJsJpegDecoderCore decoder = JpegFixture.ParsePdfJsStream(imageFile)) { sb.AppendLine(imageFile); sb.AppendLine($"Size:{decoder.ImageSizeInPixels} MCU:{decoder.ImageSizeInMCU}"); PdfJsFrameComponent c0 = decoder.Components[0]; PdfJsFrameComponent c1 = decoder.Components[1]; sb.AppendLine($"Luma: SAMP: {c0.SamplingFactors} BLOCKS: {c0.SizeInBlocks}"); sb.AppendLine($"Chroma: {c1.SamplingFactors} BLOCKS: {c1.SizeInBlocks}"); } this.Output.WriteLine(sb.ToString()); }
public static ComponentData Load(PdfJsFrameComponent c, int index) { var result = new ComponentData( c.WidthInBlocks, c.HeightInBlocks, index ); for (int y = 0; y < result.HeightInBlocks; y++) { for (int x = 0; x < result.WidthInBlocks; x++) { short[] data = c.GetBlockReference(x, y).ToArray(); result.MakeBlock(data, y, x); } } return(result); }
public void ComponentScalingIsCorrect_MultiChannelJpegPdfJs( string imageFile, int componentCount, object expectedLumaFactors, object expectedChromaFactors) { var fLuma = (Size)expectedLumaFactors; var fChroma = (Size)expectedChromaFactors; using (PdfJsJpegDecoderCore decoder = JpegFixture.ParsePdfJsStream(imageFile)) { Assert.Equal(componentCount, decoder.ComponentCount); Assert.Equal(componentCount, decoder.Components.Length); PdfJsFrameComponent c0 = decoder.Components[0]; PdfJsFrameComponent c1 = decoder.Components[1]; PdfJsFrameComponent c2 = decoder.Components[2]; var uniform1 = new Size(1, 1); Size expectedLumaSizeInBlocks = decoder.ImageSizeInMCU.MultiplyBy(fLuma); Size divisor = fLuma.DivideBy(fChroma); Size expectedChromaSizeInBlocks = expectedLumaSizeInBlocks.DivideRoundUp(divisor); VerifyJpeg.VerifyComponent(c0, expectedLumaSizeInBlocks, fLuma, uniform1); VerifyJpeg.VerifyComponent(c1, expectedChromaSizeInBlocks, fChroma, divisor); VerifyJpeg.VerifyComponent(c2, expectedChromaSizeInBlocks, fChroma, divisor); if (componentCount == 4) { PdfJsFrameComponent c3 = decoder.Components[2]; VerifyJpeg.VerifyComponent(c3, expectedLumaSizeInBlocks, fLuma, uniform1); } } }
/// <summary> /// Parses the input stream for file markers /// </summary> /// <param name="metaData">Contains the metadata for an image</param> /// <param name="metadataOnly">Whether to decode metadata only.</param> private void ParseStream(ImageMetaData metaData, bool metadataOnly) { // TODO: metadata only logic // Check for the Start Of Image marker. var fileMarker = new PdfJsFileMarker(this.ReadUint16(), 0); if (fileMarker.Marker != PdfJsJpegConstants.Markers.SOI) { throw new ImageFormatException("Missing SOI marker."); } ushort marker = this.ReadUint16(); fileMarker = new PdfJsFileMarker(marker, (int)this.InputStream.Position - 2); this.quantizationTables = new PdfJsQuantizationTables(); this.dcHuffmanTables = new PdfJsHuffmanTables(); this.acHuffmanTables = new PdfJsHuffmanTables(); while (fileMarker.Marker != PdfJsJpegConstants.Markers.EOI) { // Get the marker length int remaining = this.ReadUint16() - 2; switch (fileMarker.Marker) { case PdfJsJpegConstants.Markers.APP0: this.ProcessApplicationHeaderMarker(remaining); break; case PdfJsJpegConstants.Markers.APP1: this.ProcessApp1Marker(remaining, metaData); break; case PdfJsJpegConstants.Markers.APP2: this.ProcessApp2Marker(remaining, metaData); break; case PdfJsJpegConstants.Markers.APP3: case PdfJsJpegConstants.Markers.APP4: case PdfJsJpegConstants.Markers.APP5: case PdfJsJpegConstants.Markers.APP6: case PdfJsJpegConstants.Markers.APP7: case PdfJsJpegConstants.Markers.APP8: case PdfJsJpegConstants.Markers.APP9: case PdfJsJpegConstants.Markers.APP10: case PdfJsJpegConstants.Markers.APP11: case PdfJsJpegConstants.Markers.APP12: case PdfJsJpegConstants.Markers.APP13: this.InputStream.Skip(remaining); break; case PdfJsJpegConstants.Markers.APP14: this.ProcessApp14Marker(remaining); break; case PdfJsJpegConstants.Markers.APP15: case PdfJsJpegConstants.Markers.COM: this.InputStream.Skip(remaining); break; case PdfJsJpegConstants.Markers.DQT: this.ProcessDefineQuantizationTablesMarker(remaining); break; case PdfJsJpegConstants.Markers.SOF0: case PdfJsJpegConstants.Markers.SOF1: case PdfJsJpegConstants.Markers.SOF2: this.ProcessStartOfFrameMarker(remaining, fileMarker); break; case PdfJsJpegConstants.Markers.DHT: this.ProcessDefineHuffmanTablesMarker(remaining); break; case PdfJsJpegConstants.Markers.DRI: this.ProcessDefineRestartIntervalMarker(remaining); break; case PdfJsJpegConstants.Markers.SOS: this.ProcessStartOfScanMarker(); break; } // Read on. fileMarker = FindNextFileMarker(this.markerBuffer, this.InputStream); } this.ImageWidth = this.Frame.SamplesPerLine; this.ImageHeight = this.Frame.Scanlines; this.components = new PdfJsComponentBlocks { Components = new PdfJsComponent[this.Frame.ComponentCount] }; for (int i = 0; i < this.components.Components.Length; i++) { PdfJsFrameComponent frameComponent = this.Frame.Components[i]; var component = new PdfJsComponent { Scale = new System.Numerics.Vector2( frameComponent.HorizontalSamplingFactor / (float)this.Frame.MaxHorizontalFactor, frameComponent.VerticalSamplingFactor / (float)this.Frame.MaxVerticalFactor), BlocksPerLine = frameComponent.WidthInBlocks, BlocksPerColumn = frameComponent.HeightInBlocks }; // this.QuantizeAndInverseComponentData(ref component, frameComponent); this.components.Components[i] = component; } this.NumberOfComponents = this.components.Components.Length; }