/// <summary> /// Fits the source surface to this surface using bilinear interpolation. /// </summary> /// <param name="source">The surface to read pixels from.</param> /// <param name="dstRoi">The rectangle to clip rendering to.</param> /// <remarks>This method was implemented with correctness, not performance, in mind.</remarks> public void BilinearFitSurface(Surface source, Rectangle dstRoi) { if (dstRoi.Width < 2 || dstRoi.Height < 2 || this.width < 2 || this.height < 2) { SuperSamplingFitSurface(source, dstRoi); } else { unsafe { Rectangle roi = Rectangle.Intersect(dstRoi, this.Bounds); for (int dstY = roi.Top; dstY < roi.Bottom; ++dstY) { ColorBgra *dstRowPtr = this.GetRowAddressUnchecked(dstY); float srcRow = (float)(dstY * (source.height - 1)) / (float)(height - 1); for (int dstX = roi.Left; dstX < roi.Right; dstX++) { float srcColumn = (float)(dstX * (source.width - 1)) / (float)(width - 1); *dstRowPtr = source.GetBilinearSample(srcColumn, srcRow); ++dstRowPtr; } } } } }
void Render(Surface dst, Surface src, Rectangle rect) { Rectangle selection = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt(); long CenterX = (long)((1.0 + Amount3.First) * ((selection.Right - selection.Left) / 2) + selection.Left); long CenterY = (long)((1.0 + Amount3.Second) * ((selection.Bottom - selection.Top) / 2) + selection.Top); double rfrac = Math.Log(Amount2 / Amount1); double alpha = Math.Atan2(rfrac, Math.PI * 2); double f = Math.Cos(alpha); Complex ialpha = Complex.FromRealImaginary(0, alpha); Complex beta = f * ialpha.Exponential(); Complex zin; Complex ztemp1; Complex ztemp2; Complex zout; float from_x; float from_y; float rotatedX; float rotatedY; double angle = Amount6 * Math.PI / 180.0; double cos = Math.Cos(angle); double sin = Math.Sin(angle); ColorBgra result; for (int y = rect.Top; y < rect.Bottom; ++y) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; ++x) { zout = Complex.FromRealImaginary(x - CenterX, CenterY - y); result = ColorBgra.Zero; // see algorithm description here : http://www.josleys.com/articles/printgallery.htm // inverse step 3 and inverse step 2 ==> output after step 1 ztemp1 = MyNaturalLogarithm(zout) / beta; for (int layer = 0; layer < 3 && result.A < 255; layer++) { // convert to a point with real part inside [0 , log (r1/r2)] // combine with data in [log (r1/r2), 2 * log (r1/r2)] if not opaque // maybe even go to the part after that etc... double rtemp = 0; if (Amount4) { rtemp = ztemp1.Real % rfrac + (2 - layer) * rfrac; } else { rtemp = ztemp1.Real % rfrac + layer * rfrac; } ztemp2 = Complex.FromRealImaginary(rtemp, ztemp1.Imag * Amount5); // inverse step 1 zin = Amount1 * ztemp2.Exponential(); from_x = (float)(zin.Real + CenterX); from_y = (float)(CenterY - zin.Imag); rotatedX = (float)((from_x - CenterX) * cos - (from_y - CenterY) * sin + CenterX); rotatedY = (float)((from_y - CenterY) * cos - (from_x - CenterX) * -1.0 * sin + CenterY); result = AddColor(result, src.GetBilinearSample(rotatedX, rotatedY)); } dst[x, y] = result; } } }