Ejemplo n.º 1
0
        public static ResamplingFilter Create(ResamplingFilters filter)
        {
            ResamplingFilter resamplingFilter = null;

            switch (filter)
            {
            case ResamplingFilters.Box:
                resamplingFilter = new BoxFilter();
                break;

            case ResamplingFilters.Triangle:
                resamplingFilter = new TriangleFilter();
                break;

            case ResamplingFilters.Hermite:
                resamplingFilter = new HermiteFilter();
                break;

            case ResamplingFilters.Bell:
                resamplingFilter = new BellFilter();
                break;

            case ResamplingFilters.CubicBSpline:
                resamplingFilter = new CubicBSplineFilter();
                break;

            case ResamplingFilters.Lanczos3:
                resamplingFilter = new Lanczos3Filter();
                break;

            case ResamplingFilters.Mitchell:
                resamplingFilter = new MitchellFilter();
                break;

            case ResamplingFilters.Cosine:
                resamplingFilter = new CosineFilter();
                break;

            case ResamplingFilters.CatmullRom:
                resamplingFilter = new CatmullRomFilter();
                break;

            case ResamplingFilters.Quadratic:
                resamplingFilter = new QuadraticFilter();
                break;

            case ResamplingFilters.QuadraticBSpline:
                resamplingFilter = new QuadraticBSplineFilter();
                break;

            case ResamplingFilters.CubicConvolution:
                resamplingFilter = new CubicConvolutionFilter();
                break;

            case ResamplingFilters.Lanczos8:
                resamplingFilter = new Lanczos8Filter();
                break;
            }

            return(resamplingFilter);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Resamples input array to a new array using current resampling filter.
        /// </summary>
        /// <param name="input">Input array.</param>
        /// <param name="nWidth">Width of the output array.</param>
        /// <param name="nHeight">Height of the output array.</param>
        /// <returns>Output array.</returns>
        public ushort[][,] Resample(ushort[][,] input, int nWidth, int nHeight)
        {
            if (input == null || input.Length == 0 || nWidth <= 1 || nHeight <= 1)
            {
                return(null);
            }

            ResamplingFilter filter = ResamplingFilter.Create(this.filter);

            int width  = input[0].GetLength(0);
            int height = input[0].GetLength(1);
            int planes = input.Length;

            this.covered = 0;
            this.total   = (nWidth + height);

            // create bitmaps
            ushort[][,] work   = new ushort[planes][, ];
            ushort[][,] output = new ushort[planes][, ];
            int c = 0;

            for (c = 0; c < planes; c++)
            {
                work[c]   = new ushort[nWidth, height];
                output[c] = new ushort[nWidth, nHeight];
            }

            double xScale = ((double)nWidth / width);
            double yScale = ((double)nHeight / height);

            ContributorEntry[] contrib = new ContributorEntry[nWidth];

            double wdth = 0, center = 0, weight = 0, intensity = 0;
            int    left = 0, right = 0, i = 0, j = 0, k = 0;

            // horizontal downsampling
            if (xScale < 1.0)
            {
                // scales from bigger to smaller width
                wdth = (filter.defaultFilterRadius / xScale);

                for (i = 0; i < nWidth; i++)
                {
                    contrib[i].n    = 0;
                    contrib[i].p    = new Contributor[(int)Math.Floor(2 * wdth + 1)];
                    contrib[i].wsum = 0;
                    center          = ((i + 0.5) / xScale);
                    left            = (int)(center - wdth);
                    right           = (int)(center + wdth);

                    for (j = left; j <= right; j++)
                    {
                        weight = filter.GetValue((center - j - 0.5) * xScale);

                        if ((weight == 0) || (j < 0) || (j >= width))
                        {
                            continue;
                        }

                        contrib[i].p[contrib[i].n].pixel  = j;
                        contrib[i].p[contrib[i].n].weight = weight;
                        contrib[i].wsum += weight;
                        contrib[i].n++;
                    }

                    if (aborting)
                    {
                        goto End;
                    }
                }
            }
            else
            {
                // horizontal upsampling
                // scales from smaller to bigger width
                for (i = 0; i < nWidth; i++)
                {
                    contrib[i].n    = 0;
                    contrib[i].p    = new Contributor[(int)Math.Floor(2 * filter.defaultFilterRadius + 1)];
                    contrib[i].wsum = 0;
                    center          = ((i + 0.5) / xScale);
                    left            = (int)Math.Floor(center - filter.defaultFilterRadius);
                    right           = (int)Math.Ceiling(center + filter.defaultFilterRadius);

                    for (j = left; j <= right; j++)
                    {
                        weight = filter.GetValue(center - j - 0.5);

                        if ((weight == 0) || (j < 0) || (j >= width))
                        {
                            continue;
                        }

                        contrib[i].p[contrib[i].n].pixel  = j;
                        contrib[i].p[contrib[i].n].weight = weight;
                        contrib[i].wsum += weight;
                        contrib[i].n++;
                    }

                    if (aborting)
                    {
                        goto End;
                    }
                }
            }

            // filter horizontally from input to work
            for (c = 0; c < planes; c++)
            {
                for (k = 0; k < height; k++)
                {
                    for (i = 0; i < nWidth; i++)
                    {
                        intensity = 0;

                        for (j = 0; j < contrib[i].n; j++)
                        {
                            weight = contrib[i].p[j].weight;

                            if (weight == 0)
                            {
                                continue;
                            }

                            intensity += (input[c][contrib[i].p[j].pixel, k] * weight);
                        }

                        //work[c][i, k] = (ushort)Math.Min(Math.Max(intensity / contrib[i].wsum, UInt16.MinValue), UInt16.MaxValue);
                        work[c][i, k] = (ushort)Math.Min(Math.Max(intensity / contrib[i].wsum + 0.5, UInt16.MinValue), UInt16.MaxValue);
                    }

                    if (aborting)
                    {
                        goto End;
                    }

                    this.covered++;
                }
            }

            // pre-calculate filter contributions for a column
            contrib = new ContributorEntry[nHeight];

            // vertical downsampling
            if (yScale < 1.0)
            {
                // scales from bigger to smaller height
                wdth = (filter.defaultFilterRadius / yScale);

                for (i = 0; i < nHeight; i++)
                {
                    contrib[i].n    = 0;
                    contrib[i].p    = new Contributor[(int)Math.Floor(2 * wdth + 1)];
                    contrib[i].wsum = 0;
                    center          = ((i + 0.5) / yScale);
                    left            = (int)(center - wdth);
                    right           = (int)(center + wdth);

                    for (j = left; j <= right; j++)
                    {
                        weight = filter.GetValue((center - j - 0.5) * yScale);

                        if ((weight == 0) || (j < 0) || (j >= height))
                        {
                            continue;
                        }

                        contrib[i].p[contrib[i].n].pixel  = j;
                        contrib[i].p[contrib[i].n].weight = weight;
                        contrib[i].wsum += weight;
                        contrib[i].n++;
                    }

                    if (aborting)
                    {
                        goto End;
                    }
                }
            }
            else
            {
                // vertical upsampling
                // scales from smaller to bigger height
                for (i = 0; i < nHeight; i++)
                {
                    contrib[i].n    = 0;
                    contrib[i].p    = new Contributor[(int)Math.Floor(2 * filter.defaultFilterRadius + 1)];
                    contrib[i].wsum = 0;
                    center          = ((i + 0.5) / yScale);
                    left            = (int)(center - filter.defaultFilterRadius);
                    right           = (int)(center + filter.defaultFilterRadius);

                    for (j = left; j <= right; j++)
                    {
                        weight = filter.GetValue(center - j - 0.5);

                        if ((weight == 0) || (j < 0) || (j >= height))
                        {
                            continue;
                        }

                        contrib[i].p[contrib[i].n].pixel  = j;
                        contrib[i].p[contrib[i].n].weight = weight;
                        contrib[i].wsum += weight;
                        contrib[i].n++;
                    }

                    if (aborting)
                    {
                        goto End;
                    }
                }
            }

            // filter vertically from work to output
            for (c = 0; c < planes; c++)
            {
                for (k = 0; k < nWidth; k++)
                {
                    for (i = 0; i < nHeight; i++)
                    {
                        intensity = 0;

                        for (j = 0; j < contrib[i].n; j++)
                        {
                            weight = contrib[i].p[j].weight;

                            if (weight == 0)
                            {
                                continue;
                            }

                            intensity += (work[c][k, contrib[i].p[j].pixel] * weight);
                        }

                        //output[c][k, i] = (ushort)Math.Min(Math.Max(intensity, UInt16.MinValue), UInt16.MaxValue);
                        output[c][k, i] = (ushort)Math.Min(Math.Max(intensity / contrib[i].wsum + 0.5, UInt16.MinValue), UInt16.MaxValue);
                    }

                    if (aborting)
                    {
                        goto End;
                    }

                    this.covered++;
                }
            }

            End :;

            work = null;

            return(output);
        }