Beispiel #1
0
        public JpegComponent(MemoryAllocator memoryAllocator, JpegFrame frame, byte id, int horizontalFactor, int verticalFactor, byte quantizationTableIndex, int index)
        {
            this.memoryAllocator = memoryAllocator;
            this.Frame           = frame;
            this.Id = id;

            // Valid sampling factors are 1..2
            if (horizontalFactor == 0 ||
                verticalFactor == 0 ||
                horizontalFactor > 2 ||
                verticalFactor > 2)
            {
                JpegThrowHelper.ThrowBadSampling();
            }

            this.HorizontalSamplingFactor = horizontalFactor;
            this.VerticalSamplingFactor   = verticalFactor;
            this.SamplingFactors          = new Size(this.HorizontalSamplingFactor, this.VerticalSamplingFactor);

            if (quantizationTableIndex > 3)
            {
                JpegThrowHelper.ThrowBadQuantizationTable();
            }

            this.QuantizationTableIndex = quantizationTableIndex;
            this.Index = index;
        }
Beispiel #2
0
        public void Init()
        {
            this.WidthInBlocks = (int)MathF.Ceiling(
                MathF.Ceiling(this.Frame.SamplesPerLine / 8F) * this.HorizontalSamplingFactor / this.Frame.MaxHorizontalFactor);

            this.HeightInBlocks = (int)MathF.Ceiling(
                MathF.Ceiling(this.Frame.Scanlines / 8F) * this.VerticalSamplingFactor / this.Frame.MaxVerticalFactor);

            int blocksPerLineForMcu   = this.Frame.McusPerLine * this.HorizontalSamplingFactor;
            int blocksPerColumnForMcu = this.Frame.McusPerColumn * this.VerticalSamplingFactor;

            this.SizeInBlocks = new Size(blocksPerLineForMcu, blocksPerColumnForMcu);

            JpegComponent c0 = this.Frame.Components[0];

            this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors);

            if (this.SubSamplingDivisors.Width == 0 || this.SubSamplingDivisors.Height == 0)
            {
                JpegThrowHelper.ThrowBadSampling();
            }

            int totalNumberOfBlocks = blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
            int width  = this.WidthInBlocks + 1;
            int height = totalNumberOfBlocks / width;

            this.SpectralBlocks = this.memoryAllocator.Allocate2D <Block8x8>(width, height, AllocationOptions.Clean);
        }
Beispiel #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="HuffmanTable"/> struct.
        /// </summary>
        /// <param name="codeLengths">The code lengths.</param>
        /// <param name="values">The huffman values.</param>
        /// <param name="workspace">The provided spare workspace memory, can be dirty.</param>
        public HuffmanTable(ReadOnlySpan <byte> codeLengths, ReadOnlySpan <byte> values, Span <uint> workspace)
        {
            Unsafe.CopyBlockUnaligned(ref this.Values[0], ref MemoryMarshal.GetReference(values), (uint)values.Length);

            // Generate codes
            uint code = 0;
            int  si   = 1;
            int  p    = 0;

            for (int i = 1; i <= 16; i++)
            {
                int count = codeLengths[i];
                for (int j = 0; j < count; j++)
                {
                    workspace[p++] = code;
                    code++;
                }

                // 'code' is now 1 more than the last code used for codelength 'si'
                // in the valid worst possible case 'code' would have the least
                // significant bit set to 1, e.g. 1111(0) +1 => 1111(1)
                // but it must still fit in 'si' bits since no huffman code can be equal to all 1s
                // if last code is all ones, e.g. 1111(1), then incrementing it by 1 would yield
                // a new code which occupies one extra bit, e.g. 1111(1) +1 => (1)1111(0)
                if (code >= (1 << si))
                {
                    JpegThrowHelper.ThrowInvalidImageContentException("Bad huffman table.");
                }

                code <<= 1;
                si++;
            }

            // Figure F.15: generate decoding tables for bit-sequential decoding
            p = 0;
            for (int j = 1; j <= 16; j++)
            {
                if (codeLengths[j] != 0)
                {
                    this.ValOffset[j] = p - (int)workspace[p];
                    p += codeLengths[j];
                    this.MaxCode[j]   = workspace[p - 1];                       // Maximum code of length l
                    this.MaxCode[j] <<= JpegConstants.Huffman.RegisterSize - j; // Left justify
                    this.MaxCode[j]  |= (1ul << (JpegConstants.Huffman.RegisterSize - j)) - 1;
                }
                else
                {
                    this.MaxCode[j] = 0;
                }
            }

            this.ValOffset[18] = 0;
            this.MaxCode[17]   = ulong.MaxValue; // Ensures huff decode terminates

            // Compute lookahead tables to speed up decoding.
            // First we set all the table entries to JpegConstants.Huffman.SlowBits, indicating "too long";
            // then we iterate through the Huffman codes that are short enough and
            // fill in all the entries that correspond to bit sequences starting
            // with that code.
            ref byte lookupSizeRef = ref this.LookaheadSize[0];
Beispiel #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="JFifMarker"/> struct.
        /// </summary>
        /// <param name="majorVersion">The major version.</param>
        /// <param name="minorVersion">The minor version.</param>
        /// <param name="densityUnits">The units for the density values.</param>
        /// <param name="xDensity">The horizontal pixel density.</param>
        /// <param name="yDensity">The vertical pixel density.</param>
        private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, short xDensity, short yDensity)
        {
            if (xDensity <= 0)
            {
                JpegThrowHelper.ThrowInvalidImageContentException($"X-Density {xDensity} must be greater than 0.");
            }

            if (yDensity <= 0)
            {
                JpegThrowHelper.ThrowInvalidImageContentException($"Y-Density {yDensity} must be greater than 0.");
            }

            this.MajorVersion = majorVersion;
            this.MinorVersion = minorVersion;

            // LibJpeg and co will simply cast and not try to enforce a range.
            this.DensityUnits = (PixelResolutionUnit)densityUnits;
            this.XDensity     = xDensity;
            this.YDensity     = yDensity;
        }
Beispiel #5
0
        /// <summary>
        /// Initializes component for future buffers initialization.
        /// </summary>
        /// <param name="maxSubFactorH">Maximal horizontal subsampling factor among all the components.</param>
        /// <param name="maxSubFactorV">Maximal vertical subsampling factor among all the components.</param>
        public void Init(int maxSubFactorH, int maxSubFactorV)
        {
            this.WidthInBlocks = (int)MathF.Ceiling(
                MathF.Ceiling(this.Frame.PixelWidth / 8F) * this.HorizontalSamplingFactor / maxSubFactorH);

            this.HeightInBlocks = (int)MathF.Ceiling(
                MathF.Ceiling(this.Frame.PixelHeight / 8F) * this.VerticalSamplingFactor / maxSubFactorV);

            int blocksPerLineForMcu   = this.Frame.McusPerLine * this.HorizontalSamplingFactor;
            int blocksPerColumnForMcu = this.Frame.McusPerColumn * this.VerticalSamplingFactor;

            this.SizeInBlocks = new Size(blocksPerLineForMcu, blocksPerColumnForMcu);

            this.SubSamplingDivisors = new Size(maxSubFactorH, maxSubFactorV).DivideBy(this.SamplingFactors);

            if (this.SubSamplingDivisors.Width == 0 || this.SubSamplingDivisors.Height == 0)
            {
                JpegThrowHelper.ThrowBadSampling();
            }
        }