Esempio n. 1
0
            public void LLM_TransformIDCT_CompareToAccurate(int seed)
            {
                float[] sourceArray = Create8x8RoundedRandomFloatData(MinAllowedValue, MaxAllowedValue, seed);

                var srcBlock = Block8x8F.Load(sourceArray);

                // reference
                Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformIDCT(ref srcBlock);

                // testee
                // Part of the IDCT calculations is fused into the quantization step
                // We must multiply input block with adjusted no-quantization matrix
                // before applying IDCT
                // Dequantization using unit matrix - no values are upscaled
                Block8x8F dequantMatrix = CreateBlockFromScalar(1);

                // This step is needed to apply adjusting multipliers to the input block
                FastFloatingPointDCT.AdjustToIDCT(ref dequantMatrix);

                // IDCT implementation tranforms blocks after transposition
                srcBlock.TransposeInplace();
                srcBlock.MultiplyInPlace(ref dequantMatrix);

                // IDCT calculation
                FastFloatingPointDCT.TransformIDCT(ref srcBlock);

                this.CompareBlocks(expected, srcBlock, 1f);
            }
Esempio n. 2
0
                static void RunTest(string serialized)
                {
                    int seed = FeatureTestRunner.Deserialize <int>(serialized);

                    Span <float> src      = Create8x8RoundedRandomFloatData(-200, 200, seed);
                    var          srcBlock = default(Block8x8F);

                    srcBlock.LoadFrom(src);

                    var expectedDest = new float[64];
                    var temp1        = new float[64];
                    var temp2        = default(Block8x8F);

                    // reference
                    ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D_llm(src, expectedDest, temp1);

                    // testee
                    FastFloatingPointDCT.TransformIDCT(ref srcBlock, ref temp2);

                    var actualDest = new float[64];

                    srcBlock.ScaledCopyTo(actualDest);

                    Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
                }
Esempio n. 3
0
            public void LLM_TransformIDCT_CompareToAccurate(int seed)
            {
                float[] sourceArray = Create8x8RoundedRandomFloatData(-1000, 1000, seed);

                var srcBlock = Block8x8F.Load(sourceArray);

                Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformIDCT(ref srcBlock);

                var temp = default(Block8x8F);

                FastFloatingPointDCT.TransformIDCT(ref srcBlock, ref temp);

                this.CompareBlocks(expected, srcBlock, 1f);
            }
Esempio n. 4
0
            public void LLM_TransformIDCT_CompareToNonOptimized(int seed)
            {
                float[] sourceArray = Create8x8RoundedRandomFloatData(-1000, 1000, seed);

                var source = Block8x8F.Load(sourceArray);

                Block8x8F expected = ReferenceImplementations.LLM_FloatingPoint_DCT.TransformIDCT(ref source);

                var temp   = default(Block8x8F);
                var actual = default(Block8x8F);

                FastFloatingPointDCT.TransformIDCT(ref source, ref actual, ref temp);

                this.CompareBlocks(expected, actual, 1f);
            }
Esempio n. 5
0
        /// <summary>
        /// Convert raw spectral DCT data to color data and copy it to the color buffer <see cref="ColorBuffer"/>.
        /// </summary>
        public void CopyBlocksToColorBuffer(int spectralStep)
        {
            Buffer2D <Block8x8> spectralBuffer = this.component.SpectralBlocks;

            float maximumValue = this.frame.MaxColorChannelValue;

            int destAreaStride = this.ColorBuffer.Width;

            int yBlockStart = spectralStep * this.blockRowsPerStep;

            Size subSamplingDivisors = this.component.SubSamplingDivisors;

            Block8x8F dequantTable   = this.rawJpeg.QuantizationTables[this.component.QuantizationTableIndex];
            Block8x8F workspaceBlock = default;

            for (int y = 0; y < this.blockRowsPerStep; y++)
            {
                int yBuffer = y * this.blockAreaSize.Height;

                Span <float>    colorBufferRow = this.ColorBuffer.DangerousGetRowSpan(yBuffer);
                Span <Block8x8> blockRow       = spectralBuffer.DangerousGetRowSpan(yBlockStart + y);

                for (int xBlock = 0; xBlock < spectralBuffer.Width; xBlock++)
                {
                    // Integer to float
                    workspaceBlock.LoadFrom(ref blockRow[xBlock]);

                    // Dequantize
                    workspaceBlock.MultiplyInPlace(ref dequantTable);

                    // Convert from spectral to color
                    FastFloatingPointDCT.TransformIDCT(ref workspaceBlock);

                    // To conform better to libjpeg we actually NEED TO loose precision here.
                    // This is because they store blocks as Int16 between all the operations.
                    // To be "more accurate", we need to emulate this by rounding!
                    workspaceBlock.NormalizeColorsAndRoundInPlace(maximumValue);

                    // Write to color buffer acording to sampling factors
                    int xColorBufferStart = xBlock * this.blockAreaSize.Width;
                    workspaceBlock.ScaledCopyTo(
                        ref colorBufferRow[xColorBufferStart],
                        destAreaStride,
                        subSamplingDivisors.Width,
                        subSamplingDivisors.Height);
                }
            }
        }
Esempio n. 6
0
                static void RunTest(string serialized)
                {
                    int seed = FeatureTestRunner.Deserialize <int>(serialized);

                    Span <float> src      = Create8x8RoundedRandomFloatData(MinAllowedValue, MaxAllowedValue, seed);
                    var          srcBlock = default(Block8x8F);

                    srcBlock.LoadFrom(src);

                    float[] expectedDest = new float[64];
                    float[] temp         = new float[64];

                    // reference
                    ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D_llm(src, expectedDest, temp);

                    // testee
                    // Part of the IDCT calculations is fused into the quantization step
                    // We must multiply input block with adjusted no-quantization matrix
                    // before applying IDCT
                    Block8x8F dequantMatrix = CreateBlockFromScalar(1);

                    // Dequantization using unit matrix - no values are upscaled
                    // as quant matrix is all 1's
                    // This step is needed to apply adjusting multipliers to the input block
                    FastFloatingPointDCT.AdjustToIDCT(ref dequantMatrix);
                    srcBlock.MultiplyInPlace(ref dequantMatrix);

                    // IDCT implementation tranforms blocks after transposition
                    srcBlock.TransposeInplace();

                    // IDCT calculation
                    FastFloatingPointDCT.TransformIDCT(ref srcBlock);

                    float[] actualDest = srcBlock.ToArray();

                    Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
                }
Esempio n. 7
0
        public override void ProcessScan(ref JpegReader reader, JpegScanHeader scanHeader)
        {
            JpegFrameHeader       frameHeader  = _frameHeader;
            JpegBlockOutputWriter?outputWriter = Decoder.GetOutputWriter();

            if (frameHeader.Components is null)
            {
                ThrowInvalidDataException();
            }
            if (scanHeader.Components is null)
            {
                ThrowInvalidDataException();
            }
            if (outputWriter is null)
            {
                ThrowInvalidDataException();
            }

            // Resolve each component
            Span <JpegArithmeticDecodingComponent> components = _components.AsSpan(0, InitDecodeComponents(frameHeader, scanHeader, _components));

            foreach (JpegArithmeticDecodingComponent component in _components)
            {
                component.DcPredictor = 0;
                component.DcContext   = 0;
                component.DcStatistics?.Reset();
                component.AcStatistics?.Reset();
            }

            Reset();

            // Prepare
            int           maxHorizontalSampling = _maxHorizontalSampling;
            int           maxVerticalSampling   = _maxVerticalSampling;
            int           mcusBeforeRestart     = _restartInterval;
            int           mcusPerLine           = _mcusPerLine;
            int           mcusPerColumn         = _mcusPerColumn;
            int           levelShift            = _levelShift;
            JpegBitReader bitReader             = new JpegBitReader(reader.RemainingBytes);

            // DCT Block
            JpegBlock8x8F blockFBuffer  = default;
            JpegBlock8x8F outputFBuffer = default;
            JpegBlock8x8F tempFBuffer   = default;

            JpegBlock8x8 outputBuffer;

            for (int rowMcu = 0; rowMcu < mcusPerColumn; rowMcu++)
            {
                int offsetY = rowMcu * maxVerticalSampling;
                for (int colMcu = 0; colMcu < mcusPerLine; colMcu++)
                {
                    int offsetX = colMcu * maxHorizontalSampling;

                    // Scan an interleaved mcu... process components in order
                    foreach (JpegArithmeticDecodingComponent component in components)
                    {
                        int index = component.ComponentIndex;
                        int h     = component.HorizontalSamplingFactor;
                        int v     = component.VerticalSamplingFactor;
                        int hs    = component.HorizontalSubsamplingFactor;
                        int vs    = component.VerticalSubsamplingFactor;

                        for (int y = 0; y < v; y++)
                        {
                            int blockOffsetY = (offsetY + y) * 8;
                            for (int x = 0; x < h; x++)
                            {
                                // Read MCU
                                outputBuffer = default;
                                ReadBlock(ref bitReader, component, ref outputBuffer);

                                // Dequantization
                                DequantizeBlockAndUnZigZag(component.QuantizationTable, ref outputBuffer, ref blockFBuffer);

                                // IDCT
                                FastFloatingPointDCT.TransformIDCT(ref blockFBuffer, ref outputFBuffer, ref tempFBuffer);

                                // Level shift
                                ShiftDataLevel(ref outputFBuffer, ref outputBuffer, levelShift);

                                // CopyToOutput
                                WriteBlock(outputWriter, ref Unsafe.As <JpegBlock8x8, short>(ref outputBuffer), index, (offsetX + x) * 8, blockOffsetY, hs, vs);
                            }
                        }
                    }

                    // Handle restart
                    if (_restartInterval > 0 && (--mcusBeforeRestart) == 0)
                    {
                        bitReader.AdvanceAlignByte();

                        JpegMarker marker = bitReader.TryReadMarker();
                        if (marker == JpegMarker.EndOfImage)
                        {
                            int bytesConsumedEoi = reader.RemainingByteCount - bitReader.RemainingBits / 8;
                            reader.TryAdvance(bytesConsumedEoi - 2);
                            return;
                        }
                        if (!marker.IsRestartMarker())
                        {
                            throw new InvalidOperationException("Expect restart marker.");
                        }

                        mcusBeforeRestart = _restartInterval;

                        foreach (JpegArithmeticDecodingComponent component in components)
                        {
                            component.DcPredictor = 0;
                            component.DcContext   = 0;
                            component.DcStatistics?.Reset();
                            component.AcStatistics?.Reset();
                        }

                        Reset();
                    }
                }
            }

            bitReader.AdvanceAlignByte();
            int bytesConsumed = reader.RemainingByteCount - bitReader.RemainingBits / 8;

            if (bitReader.TryPeekMarker() != 0)
            {
                if (!bitReader.TryPeekMarker().IsRestartMarker())
                {
                    bytesConsumed -= 2;
                }
            }
            reader.TryAdvance(bytesConsumed);
        }