public Bitmap Resample(Bitmap image, int width, int height) { ResamplingService resamplingService = new ResamplingService(); resamplingService.Filter = ResamplingFilters.Lanczos3; ushort[][,] input = ResamplingFilter.ConvertBitmapToArray((Bitmap)image); ushort[][,] output = resamplingService.Resample(input, width, height); Bitmap result = (Bitmap)ResamplingFilter.ConvertArrayToBitmap(output); return(result); }
public void Resample(ResamplingFilters filter, int newWidth, int newHeight) { if (Disposed) { return; } ResamplingService resamplingService = new ResamplingService(); resamplingService.Filter = filter; var array = ResamplingFilter.ConvertByteArrayToArray((byte *)this.Bytes.ToPointer(), this.Width, this.Height); var result = resamplingService.Resample(array, newWidth, newHeight); this.InternalResize(newWidth, newHeight); ResamplingFilter.ConvertArrayToByteArray(result, (byte *)this.Bytes.ToPointer()); }
/// <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 + 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 / contrib[i].wsum + 0.5, UInt16.MinValue), UInt16.MaxValue); } if (aborting) { goto End; } this.covered++; } } End :; work = null; return(output); }
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); }