public static SpectralData LoadFromImageSharpDecoder(PdfJsJpegDecoderCore decoder) { PdfJsFrameComponent[] srcComponents = decoder.Frame.Components; LibJpegTools.ComponentData[] destComponents = srcComponents.Select(LibJpegTools.ComponentData.Load).ToArray(); return(new SpectralData(destComponents)); }
public void PostProcess <TPixel>(TestImageProvider <TPixel> provider) where TPixel : struct, IPixel <TPixel> { string imageFile = provider.SourceFileOrDescription; using (PdfJsJpegDecoderCore decoder = JpegFixture.ParsePdfJsStream(imageFile)) using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryManager, decoder)) using (var image = new Image <Rgba32>(decoder.ImageWidth, decoder.ImageHeight)) { pp.PostProcess(image.Frames.RootFrame); image.DebugSave(provider); ImagingTestCaseUtility testUtil = provider.Utility; testUtil.TestGroupName = nameof(JpegDecoderTests); testUtil.TestName = JpegDecoderTests.DecodeBaselineJpegOutputName; using (Image <TPixel> referenceImage = provider.GetReferenceOutputImage <TPixel>(appendPixelTypeToFileName: false)) { ImageSimilarityReport report = ImageComparer.Exact.CompareImagesOrFrames(referenceImage, image); this.Output.WriteLine($"*** {imageFile} ***"); this.Output.WriteLine($"Difference: {report.DifferencePercentageString}"); // ReSharper disable once PossibleInvalidOperationException Assert.True(report.TotalNormalizedDifference.Value < 0.005f); } } }
/// <inheritdoc/> public IImageInfo Identify(Configuration configuration, Stream stream) { Guard.NotNull(stream, "stream"); using (var decoder = new PdfJsJpegDecoderCore(configuration, this)) { return(decoder.Identify(stream)); } }
public void ColorSpace_IsDeducedCorrectlyPdfJs(string imageFile, object expectedColorSpaceValue) { var expecteColorSpace = (JpegColorSpace)expectedColorSpaceValue; using (PdfJsJpegDecoderCore decoder = JpegFixture.ParsePdfJsStream(imageFile)) { Assert.Equal(expecteColorSpace, decoder.ColorSpace); } }
/// <inheritdoc/> public Image <TPixel> Decode <TPixel>(Configuration configuration, Stream stream) where TPixel : struct, IPixel <TPixel> { Guard.NotNull(stream, nameof(stream)); using (var decoder = new PdfJsJpegDecoderCore(configuration, this)) { return(decoder.Decode <TPixel>(stream)); } }
internal static PdfJsJpegDecoderCore ParsePdfJsStream(string testFileName, bool metaDataOnly = false) { byte[] bytes = TestFile.Create(testFileName).Bytes; using (var ms = new MemoryStream(bytes)) { var decoder = new PdfJsJpegDecoderCore(Configuration.Default, new JpegDecoder()); decoder.ParseStream(ms, metaDataOnly); return(decoder); } }
public void ParseStream_BasicPropertiesAreCorrect1_PdfJs() { byte[] bytes = TestFile.Create(TestImages.Jpeg.Progressive.Progress).Bytes; using (var ms = new MemoryStream(bytes)) { var decoder = new PdfJsJpegDecoderCore(Configuration.Default, new JpegDecoder()); decoder.ParseStream(ms); VerifyJpeg.VerifyComponentSizes3(decoder.Frame.Components, 43, 61, 22, 31, 22, 31); } }
public void ParseStreamPdfJs() { using (var memoryStream = new MemoryStream(this.jpegBytes)) { var decoder = new PdfJsJpegDecoderCore(Configuration.Default, new JpegDecoder() { IgnoreMetadata = true }); decoder.ParseStream(memoryStream); decoder.Dispose(); } }
public void ParseStream_BasicPropertiesAreCorrect1_PdfJs() { byte[] bytes = TestFile.Create(TestImages.Jpeg.Progressive.Progress).Bytes; using (var ms = new MemoryStream(bytes)) { var decoder = new PdfJsJpegDecoderCore(Configuration.Default, new JpegDecoder()); decoder.ParseStream(ms); // I don't know why these numbers are different. All I know is that the decoder works // and spectral data is exactly correct also. // VerifyJpeg.VerifyComponentSizes3(decoder.Frame.Components, 43, 61, 22, 31, 22, 31); VerifyJpeg.VerifyComponentSizes3(decoder.Frame.Components, 44, 62, 22, 31, 22, 31); } }
public void PdfJsDecoder_ParseStream_SaveSpectralResult <TPixel>(TestImageProvider <TPixel> provider) where TPixel : struct, IPixel <TPixel> { PdfJsJpegDecoderCore decoder = new PdfJsJpegDecoderCore(Configuration.Default, new JpegDecoder()); byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes; using (var ms = new MemoryStream(sourceBytes)) { decoder.ParseStream(ms); var data = LibJpegTools.SpectralData.LoadFromImageSharpDecoder(decoder); VerifyJpeg.SaveSpectralImage(provider, data); } }
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 void DoProcessorStep <TPixel>(TestImageProvider <TPixel> provider) where TPixel : struct, IPixel <TPixel> { string imageFile = provider.SourceFileOrDescription; using (PdfJsJpegDecoderCore decoder = JpegFixture.ParsePdfJsStream(imageFile)) using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryManager, decoder)) using (var imageFrame = new ImageFrame <Rgba32>(Configuration.Default, decoder.ImageWidth, decoder.ImageHeight)) { pp.DoPostProcessorStep(imageFrame); JpegComponentPostProcessor[] cp = pp.ComponentProcessors; SaveBuffer(cp[0], provider); SaveBuffer(cp[1], provider); SaveBuffer(cp[2], provider); } }
public void VerifySpectralCorrectness_PdfJs <TPixel>(TestImageProvider <TPixel> provider) where TPixel : struct, IPixel <TPixel> { if (!TestEnvironment.IsWindows) { return; } PdfJsJpegDecoderCore decoder = new PdfJsJpegDecoderCore(Configuration.Default, new JpegDecoder()); byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes; using (var ms = new MemoryStream(sourceBytes)) { decoder.ParseStream(ms); var imageSharpData = LibJpegTools.SpectralData.LoadFromImageSharpDecoder(decoder); this.VerifySpectralCorrectness <TPixel>(provider, imageSharpData); } }
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> /// Decodes the spectral scan /// </summary> /// <param name="frame">The image frame</param> /// <param name="stream">The input stream</param> /// <param name="dcHuffmanTables">The DC Huffman tables</param> /// <param name="acHuffmanTables">The AC Huffman tables</param> /// <param name="components">The scan components</param> /// <param name="componentIndex">The component index within the array</param> /// <param name="componentsLength">The length of the components. Different to the array length</param> /// <param name="resetInterval">The reset interval</param> /// <param name="spectralStart">The spectral selection start</param> /// <param name="spectralEnd">The spectral selection end</param> /// <param name="successivePrev">The successive approximation bit high end</param> /// <param name="successive">The successive approximation bit low end</param> public void DecodeScan( PdfJsFrame frame, Stream stream, PdfJsHuffmanTables dcHuffmanTables, PdfJsHuffmanTables acHuffmanTables, PdfJsFrameComponent[] components, int componentIndex, int componentsLength, ushort resetInterval, int spectralStart, int spectralEnd, int successivePrev, int successive) { this.markerBuffer = new byte[2]; this.compIndex = componentIndex; this.specStart = spectralStart; this.specEnd = spectralEnd; this.successiveState = successive; this.endOfStreamReached = false; this.unexpectedMarkerReached = false; bool progressive = frame.Progressive; int mcusPerLine = frame.McusPerLine; int mcu = 0; int mcuExpected; if (componentsLength == 1) { mcuExpected = components[this.compIndex].WidthInBlocks * components[this.compIndex].HeightInBlocks; } else { mcuExpected = mcusPerLine * frame.McusPerColumn; } PdfJsFileMarker fileMarker; while (mcu < mcuExpected) { // Reset interval stuff int mcuToRead = resetInterval != 0 ? Math.Min(mcuExpected - mcu, resetInterval) : mcuExpected; for (int i = 0; i < components.Length; i++) { PdfJsFrameComponent c = components[i]; c.Pred = 0; } this.eobrun = 0; if (!progressive) { this.DecodeScanBaseline(dcHuffmanTables, acHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream); } else { if (this.specStart == 0) { if (successivePrev == 0) { this.DecodeScanDCFirst(dcHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream); } else { this.DecodeScanDCSuccessive(components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream); } } else { if (successivePrev == 0) { this.DecodeScanACFirst(acHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream); } else { this.DecodeScanACSuccessive(acHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream); } } } // Find marker this.bitsCount = 0; this.accumulator = 0; this.bitsUnRead = 0; fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream); // Some bad images seem to pad Scan blocks with e.g. zero bytes, skip past // those to attempt to find a valid marker (fixes issue4090.pdf) in original code. if (fileMarker.Invalid) { #if DEBUG Debug.WriteLine($"DecodeScan - Unexpected MCU data at {stream.Position}, next marker is: {fileMarker.Marker:X}"); #endif } ushort marker = fileMarker.Marker; // RSTn - We've already read the bytes and altered the position so no need to skip if (marker >= PdfJsJpegConstants.Markers.RST0 && marker <= PdfJsJpegConstants.Markers.RST7) { continue; } if (!fileMarker.Invalid) { // We've found a valid marker. // Rewind the stream to the position of the marker and break stream.Position = fileMarker.Position; break; } } fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream); // Some images include more Scan blocks than expected, skip past those and // attempt to find the next valid marker (fixes issue8182.pdf) in original code. if (fileMarker.Invalid) { #if DEBUG Debug.WriteLine($"DecodeScan - Unexpected MCU data at {stream.Position}, next marker is: {fileMarker.Marker:X}"); #endif } else { // We've found a valid marker. // Rewind the stream to the position of the marker stream.Position = fileMarker.Position; } }
/// <summary> /// Decodes the spectral scan /// </summary> /// <param name="frame">The image frame</param> /// <param name="stream">The input stream</param> /// <param name="dcHuffmanTables">The DC Huffman tables</param> /// <param name="acHuffmanTables">The AC Huffman tables</param> /// <param name="components">The scan components</param> /// <param name="componentIndex">The component index within the array</param> /// <param name="componentsLength">The length of the components. Different to the array length</param> /// <param name="resetInterval">The reset interval</param> /// <param name="spectralStart">The spectral selection start</param> /// <param name="spectralEnd">The spectral selection end</param> /// <param name="successivePrev">The successive approximation bit high end</param> /// <param name="successive">The successive approximation bit low end</param> public void DecodeScan( PdfJsFrame frame, DoubleBufferedStreamReader stream, PdfJsHuffmanTables dcHuffmanTables, PdfJsHuffmanTables acHuffmanTables, PdfJsFrameComponent[] components, int componentIndex, int componentsLength, ushort resetInterval, int spectralStart, int spectralEnd, int successivePrev, int successive) { this.dctZigZag = ZigZag.CreateUnzigTable(); this.markerBuffer = new byte[2]; this.compIndex = componentIndex; this.specStart = spectralStart; this.specEnd = spectralEnd; this.successiveState = successive; this.endOfStreamReached = false; this.unexpectedMarkerReached = false; bool progressive = frame.Progressive; this.mcusPerLine = frame.McusPerLine; this.mcu = 0; int mcuExpected; if (componentsLength == 1) { mcuExpected = components[this.compIndex].WidthInBlocks * components[this.compIndex].HeightInBlocks; } else { mcuExpected = this.mcusPerLine * frame.McusPerColumn; } while (this.mcu < mcuExpected) { // Reset interval stuff this.mcuToRead = resetInterval != 0 ? Math.Min(mcuExpected - this.mcu, resetInterval) : mcuExpected; for (int i = 0; i < components.Length; i++) { PdfJsFrameComponent c = components[i]; c.Pred = 0; } this.eobrun = 0; if (!progressive) { this.DecodeScanBaseline(dcHuffmanTables, acHuffmanTables, components, componentsLength, stream); } else { bool isAc = this.specStart != 0; bool isFirst = successivePrev == 0; PdfJsHuffmanTables huffmanTables = isAc ? acHuffmanTables : dcHuffmanTables; this.DecodeScanProgressive(huffmanTables, isAc, isFirst, components, componentsLength, stream); } // Reset // TODO: I do not understand why these values are reset? We should surely be tracking the bits across mcu's? this.bitsCount = 0; this.bitsData = 0; this.unexpectedMarkerReached = false; // Some images include more scan blocks than expected, skip past those and // attempt to find the next valid marker PdfJsFileMarker fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream); byte marker = fileMarker.Marker; // RSTn - We've already read the bytes and altered the position so no need to skip if (marker >= PdfJsJpegConstants.Markers.RST0 && marker <= PdfJsJpegConstants.Markers.RST7) { continue; } if (!fileMarker.Invalid) { // We've found a valid marker. // Rewind the stream to the position of the marker and break stream.Position = fileMarker.Position; break; } #if DEBUG Debug.WriteLine($"DecodeScan - Unexpected MCU data at {stream.Position}, next marker is: {fileMarker.Marker:X}"); #endif } }