public void ComponentAllocation_Can_Create_Using_Object()
        {
            // Arrange
            var subscription = Chargify.GetSubscriptionList().FirstOrDefault(s => s.Value.State == SubscriptionState.Active).Value;
            var component    = Chargify.GetComponentsForSubscription(subscription.SubscriptionID).FirstOrDefault(c => c.Value.Kind == "quantity_based_component" || c.Value.Kind == "on_off_component").Value;

            var allocation = new ComponentAllocation()
            {
                Quantity        = 1,
                Memo            = Guid.NewGuid().ToString(),
                UpgradeScheme   = ComponentUpgradeProrationScheme.Prorate_Delay_Capture,
                DowngradeScheme = ComponentDowngradeProrationScheme.No_Prorate
            };

            // Act
            var result = Chargify.CreateComponentAllocation(subscription.SubscriptionID, component.ComponentID, allocation);

            // Assert
            Assert.IsNotNull(result);
            //Assert.IsInstanceOfType(result, typeof(IComponentAllocation));
            Assert.AreEqual(allocation.Quantity, result.Quantity, "The quantities don't match");
            Assert.AreEqual(allocation.Memo, result.Memo, "The memo text differs");
            Assert.AreEqual(allocation.UpgradeScheme, result.UpgradeScheme, "The upgrade scheme received isn't the same as submitted");
            Assert.AreEqual(allocation.DowngradeScheme, result.DowngradeScheme, "The downgrade scheme received isn't the same as submitted");
        }
        public void Allocate(JpegFrameHeader frameHeader)
        {
            if (!(_bufferHandle is null))
            {
                throw new InvalidOperationException();
            }

            // Compute maximum sampling factor
            int maxHorizontalSampling = 1;
            int maxVerticalSampling   = 1;

            foreach (JpegFrameComponentSpecificationParameters currentFrameComponent in frameHeader.Components !)
            {
                maxHorizontalSampling = Math.Max(maxHorizontalSampling, currentFrameComponent.HorizontalSamplingFactor);
                maxVerticalSampling   = Math.Max(maxVerticalSampling, currentFrameComponent.VerticalSamplingFactor);
            }

            int horizontalBlockCount = (frameHeader.SamplesPerLine + 7) / 8;
            int verticalBlockCount   = (frameHeader.NumberOfLines + 7) / 8;

            ComponentAllocation[] componentAllocations = _components = new ComponentAllocation[frameHeader.NumberOfComponents];
            int index = 0;

            foreach (JpegFrameComponentSpecificationParameters component in frameHeader.Components)
            {
                int horizontalSubsamplingFactor = maxHorizontalSampling / component.HorizontalSamplingFactor;
                int verticalSubsamplingFactor   = maxVerticalSampling / component.VerticalSamplingFactor;

                int horizontalComponentBlockCount = (horizontalBlockCount + horizontalSubsamplingFactor - 1) / horizontalSubsamplingFactor;
                int verticalComponentBlockCount   = (verticalBlockCount + verticalSubsamplingFactor - 1) / verticalSubsamplingFactor;

                componentAllocations[index++] = new ComponentAllocation
                {
                    HorizontalComponentBlock    = horizontalComponentBlockCount,
                    VerticalComponentBlock      = verticalComponentBlockCount,
                    HorizontalSubsamplingFactor = horizontalSubsamplingFactor,
                    VerticalSubsamplingFactor   = verticalSubsamplingFactor,
                };
            }

            // allocate an additional block to act as a dummy buffer.
            index = 1;
            for (int i = 0; i < componentAllocations.Length; i++)
            {
                componentAllocations[i].ComponentBlockOffset = index;
                index += componentAllocations[i].HorizontalComponentBlock * componentAllocations[i].VerticalComponentBlock;
            }

            int length = index * Unsafe.SizeOf <JpegBlock8x8>();
            IMemoryOwner <byte> bufferHandle = _bufferHandle = _memoryPool.Rent(length);

            bufferHandle.Memory.Span.Slice(0, length).Clear();
        }
        public ref JpegBlock8x8 GetBlockReference(int componentIndex, int blockX, int blockY)
        {
            ComponentAllocation[]? components = _components;
            if (components is null)
            {
                throw new InvalidOperationException();
            }
            Debug.Assert(_bufferHandle != null);
            if ((uint)componentIndex >= (uint)components.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(componentIndex));
            }
            ComponentAllocation component = components[componentIndex];

            ref JpegBlock8x8 blockRef = ref Unsafe.As <byte, JpegBlock8x8>(ref MemoryMarshal.GetReference(_bufferHandle !.Memory.Span));
        private void FlushCore(int componentIndex, int y, int writeHeight)
        {
            ComponentAllocation[]? components = _components;
            if (components is null)
            {
                return;
            }

            Unsafe.SkipInit(out JpegBlock8x8 block);
            JpegBlockOutputWriter?outputWriter = _writer;

            Debug.Assert(!(outputWriter is null));

            ComponentAllocation component = components[componentIndex];
            int width = component.Width;

            ref short componentSampleRef = ref Unsafe.As <byte, short>(ref MemoryMarshal.GetReference(_bufferHandle !.Memory.Span));
        public void Allocate(JpegFrameHeader frameHeader)
        {
            // Compute maximum sampling factor
            int maxHorizontalSampling = 1;
            int maxVerticalSampling   = 1;

            foreach (JpegFrameComponentSpecificationParameters currentFrameComponent in frameHeader.Components !)
            {
                maxHorizontalSampling = Math.Max(maxHorizontalSampling, currentFrameComponent.HorizontalSamplingFactor);
                maxVerticalSampling   = Math.Max(maxVerticalSampling, currentFrameComponent.VerticalSamplingFactor);
            }

            ComponentAllocation[] componentAllocations = _components = new ComponentAllocation[frameHeader.NumberOfComponents];
            int index = 0;

            foreach (JpegFrameComponentSpecificationParameters component in frameHeader.Components)
            {
                int horizontalSubsamplingFactor = maxHorizontalSampling / component.HorizontalSamplingFactor;
                int verticalSubsamplingFactor   = maxVerticalSampling / component.VerticalSamplingFactor;

                int width  = (frameHeader.SamplesPerLine + horizontalSubsamplingFactor - 1) / horizontalSubsamplingFactor;
                int height = (frameHeader.NumberOfLines + verticalSubsamplingFactor - 1) / verticalSubsamplingFactor;

                componentAllocations[index++] = new ComponentAllocation
                {
                    Width  = width,
                    Height = height,
                    HorizontalSubsamplingFactor = horizontalSubsamplingFactor,
                    VerticalSubsamplingFactor   = verticalSubsamplingFactor,
                };
            }

            index = 0;
            for (int i = 0; i < componentAllocations.Length; i++)
            {
                componentAllocations[i].ComponentSampleOffset = index;
                index += componentAllocations[i].Width * 16;
            }

            int length = index * Unsafe.SizeOf <short>();
            IMemoryOwner <byte> bufferHandle = _bufferHandle = _memoryPool.Rent(length);

            bufferHandle.Memory.Span.Slice(0, length).Clear();
        }
        public Span <short> GetScanlineSpan(int componentIndex, int y)
        {
            ComponentAllocation[]? components = _components;
            if (components is null)
            {
                throw new InvalidOperationException();
            }
            Debug.Assert(_bufferHandle != null);
            if ((uint)componentIndex >= (uint)components.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(componentIndex));
            }
            ComponentAllocation component = components[componentIndex];

            if ((uint)y >= (uint)component.Height)
            {
                throw new ArgumentOutOfRangeException(nameof(y));
            }

            Span <short> bufferSpan = MemoryMarshal.Cast <byte, short>(_bufferHandle !.Memory.Span);

            return(bufferSpan.Slice(component.ComponentSampleOffset).Slice(component.Width * (y & 0b1111), component.Width));
        }
        public void ComponentAllocation_Can_Create_Using_Object()
        {
            // Arrange
            var subscription = Chargify.GetSubscriptionList().FirstOrDefault(s => s.Value.State == ChargifyNET.SubscriptionState.Active).Value;
            var component = Chargify.GetComponentsForSubscription(subscription.SubscriptionID).FirstOrDefault(c => c.Value.Kind == "quantity_based_component" || c.Value.Kind == "on_off_component").Value;

            var allocation = new ComponentAllocation() {
                Quantity = 1,
                Memo = Guid.NewGuid().ToString(),
                UpgradeScheme = ComponentUpgradeProrationScheme.Prorate_Delay_Capture,
                DowngradeScheme = ComponentDowngradeProrationScheme.No_Prorate
            };

            // Act
            var result = Chargify.CreateComponentAllocation(subscription.SubscriptionID, component.ComponentID, allocation);

            // Assert
            Assert.IsNotNull(result);
            //Assert.IsInstanceOfType(result, typeof(IComponentAllocation));
            Assert.AreEqual(allocation.Quantity, result.Quantity, "The quantities don't match");
            Assert.AreEqual(allocation.Memo, result.Memo, "The memo text differs");
            Assert.AreEqual(allocation.UpgradeScheme, result.UpgradeScheme, "The upgrade scheme received isn't the same as submitted");
            Assert.AreEqual(allocation.DowngradeScheme, result.DowngradeScheme, "The downgrade scheme received isn't the same as submitted");
        }