MJW Posted December 26, 2017 Share Posted December 26, 2017 I'm confused about how GetBilinearSample is supposed to behave on the last pixel in a row or column. The situation is complicated because pixels need to be numbered from the upper-left corners so that fetching a pixel using GetBilinearSample will return the exact pixel when the coordinates have integer values. Pixels with non-integer coordinates are interpolated from the four surrounding pixels. The question is: how are samples handled when X is between Width-1 and Width? There are no rightward pixels to interpolate from. The way I thought it worked, and the way I believe it used to work, is that the last pixel in a row was not interpolated in X; the last row was essentially clamped to provide the rightward pixels. (Which also means the corner pixels are not interpolated at all.) Now, based on what I've seen in some tiling code I wrote, it appears to me that the last row and column fade to transparency. So the rightward row is, in effect, transparent. I can live with either, provided I know what it does, but I think the way I thought it worked is the better of the imperfect options. I think that if an opaque surface has a width of 100, there should be 100 opaque pixels in each row. even when subsampled. Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted December 26, 2017 Share Posted December 26, 2017 The answer is in the code I highly recommend getting comfortable with .NET Reflector in order to answer questions like this. I'm not totally sure what the answer is for your question, but here's the code (via SurfaceBgraExtensions). The way it should work may not be the same as how it actually works in this code -- there were some things I learned about this space after its implementation. internal static unsafe ColorBgra GetBilinearSample<TSurfaceBgra>(ref TSurfaceBgra surface, float x, float y) where TSurfaceBgra : ISurface<ColorBgra> { if (!x.IsFinite() || !y.IsFinite()) { return ColorBgra.Transparent; } byte* scan0 = (byte*)surface.Scan0; int width = surface.Width; int height = surface.Height; int stride = surface.Stride; float u = x; float v = y; if (u > -1 && v > -1 && u < width && v < height) { unchecked { int iu = (int)Math.Floor(u); uint sxfrac = (uint)(256 * (u - (float)iu)); uint sxfracinv = 256 - sxfrac; int iv = (int)Math.Floor(v); uint syfrac = (uint)(256 * (v - (float)iv)); uint syfracinv = 256 - syfrac; uint wul = (uint)(sxfracinv * syfracinv); uint wur = (uint)(sxfrac * syfracinv); uint wll = (uint)(sxfracinv * syfrac); uint wlr = (uint)(sxfrac * syfrac); int sleft = iu; int sright = iu + 1; int stop = iv; int sbottom = iv + 1; ColorBgra* pstop = (ColorBgra*)(scan0 + ((long)stop * stride)); ColorBgra* psbottom = (ColorBgra*)(scan0 + ((long)sbottom * stride)); ColorBgra cul; if (wul > 0 && sleft >= 0 && stop >= 0) { cul = *(pstop + sleft); } else { cul = ColorBgra.Transparent; } ColorBgra cur; if (wur > 0 && sright < width && stop >= 0) { cur = *(pstop + sright); } else { cur = ColorBgra.Transparent; } ColorBgra cll; if (wll > 0 && sleft >= 0 && sbottom < height) { cll = *(psbottom + sleft); } else { cll = ColorBgra.Transparent; } ColorBgra clr; if (wlr > 0 && sright < width && sbottom < height) { clr = *(psbottom + sright); } else { clr = ColorBgra.Transparent; } ColorBgra c = ColorBgra.BlendColors4W16IP(cul, wul, cur, wur, cll, wll, clr, wlr); return c; } } else { return ColorBgra.Transparent; } } Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
MJW Posted December 27, 2017 Author Share Posted December 27, 2017 Thanks, Rick. I actually had looked at the code with ILSpy, but I wasn't sure what it was trying to achieve. I was hoping to learn the guiding principle behind it. In particular, I wondered whether the fading out of the last pixel in each row and column is intended or a bug. Your comment reminded me that once the left, right, top, and bottom interpolation colors are determined, the actual interpolation can be performed with BlendColors4W16IP. So if GetBilinearSample doesn't serve my needs, it isn't difficult to write my own version. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.