コード例 #1
0
ファイル: ResizeV3.cs プロジェクト: Xamla/graph_system
        public static void Resize(I <Vector3> source, IntRect sourceRect, I <Vector3> destination, ResizeFilterType filterType, CancellationToken cancel = default(CancellationToken))
        {
            if (source == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (destination == null)
            {
                throw new ArgumentNullException("destination");
            }

            sourceRect = sourceRect.Clip(new IntRect(0, 0, source.Width, source.Height));
            if (sourceRect.Width <= 0 || sourceRect.Height <= 0 || source.Channels <= 0)
            {
                throw new ArgumentNullException("Source image must not be empty");
            }

            if (destination.Width <= 0 || destination.Height <= 0 || destination.Channels <= 0)
            {
                return;
            }

            var s = source.Data.Buffer;
            var d = destination.Data.Buffer;

            var contribX = ImageBufferResize.CreateContributors(filterType, source.Width, sourceRect.Left, sourceRect.Right, destination.Width);
            var contribY = ImageBufferResize.CreateContributors(filterType, source.Height, sourceRect.Top, sourceRect.Bottom, destination.Height);

            float filterRadius    = ImageBufferResize.GetFilterRadius(filterType);
            int   ringBufferLines = contribY.Max(x => x.N);
            var   ringBuffer      = new Vector3[destination.Width * ringBufferLines];


            var ranges = destination.Format.ChannelRanges;
            var low    = new Vector3((float)ranges[0].Low, (float)ranges[1].Low, (float)ranges[2].Low);
            var high   = new Vector3((float)ranges[0].High, (float)ranges[1].High, (float)ranges[2].High);

            int sY = sourceRect.Top;
            int dX, j;
            int offset         = 0;
            int positionInRing = sY % ringBufferLines;

            for (int dY = 0; dY < destination.Height; ++dY)
            {
                if ((dY % 128) == 0 && cancel.IsCancellationRequested)
                {
                    break;
                }

                int rowIn, rowOut;
                while (sY < sourceRect.Bottom && sY <= contribY[dY].MaxPixel)
                {
                    rowIn  = sY * source.Width;
                    rowOut = positionInRing * destination.Width;

                    for (dX = 0; dX < destination.Width; ++dX)
                    {
                        var contrib = contribX[dX];
                        var value   = Vector3.Zero;

                        for (j = 0; j < contribX[dX].N; ++j)
                        {
                            float weight = contrib.P[j].Weight;
                            if (weight != 0)
                            {
                                offset = contrib.P[j].Pixel;
                                value  = value + s[rowIn + offset] * weight;
                            }
                        }

                        ringBuffer[rowOut] = value * contrib.Normalize;
                        ++rowOut;
                    }

                    ++sY;
                    positionInRing = (positionInRing + 1) % ringBufferLines;
                }

                // resize lines vertically
                for (int k = 0; k < destination.Width; ++k)
                {
                    var contrib = contribY[dY];
                    var value   = Vector3.Zero;

                    for (j = 0; j < contrib.N; ++j)
                    {
                        float weight = contrib.P[j].Weight;
                        if (weight != 0)
                        {
                            offset = contrib.P[j].Pixel % ringBufferLines;
                            offset = offset * destination.Width + k;
                            value  = value + ringBuffer[offset] * weight;
                        }
                    }

                    value = Vector3.Max(Vector3.Min(value * contrib.Normalize, high), low);
                    d[dY * destination.Width + k] = value;
                }
            }
        }