private void Dispose(bool disposing) { if (!disposed) { disposed = true; if (disposing) { } if (valid && parentBlock == null) { if (length >= largeBlockThreshold) { ImageSurfaceMemory.FreeLarge(new IntPtr(voidStar), (ulong)length); } else { ImageSurfaceMemory.Free(new IntPtr(voidStar)); } } parentBlock = null; voidStar = null; valid = false; } }
protected override unsafe void FitSurfaceImpl(SurfaceBase source) { float lastRowIndex = height - 1; float lastColumnIndex = width - 1; IntPtr srcColCachePtr = IntPtr.Zero; try { srcColCachePtr = ImageSurfaceMemory.Allocate((ulong)width * sizeof(float)); float *srcColCache = (float *)srcColCachePtr; // Precompute the source column indexes. for (int x = 0; x < width; x++) { float u = x / lastColumnIndex; srcColCache[x] = (u * source.Width) - 0.5f; } for (int y = 0; y < height; y++) { ColorBgr8 *destRow = (ColorBgr8 *)GetRowAddressUnchecked(y); float v = y / lastRowIndex; float srcY = (v * source.Height) - 0.5f; int yint = (int)srcY; float yfract = srcY - (float)Math.Floor(srcY); for (int x = 0; x < width; x++) { float srcX = srcColCache[x]; int xint = (int)srcX; float xfract = srcX - (float)Math.Floor(srcX); // 1st row ColorBgr8 p00 = *(ColorBgr8 *)source.GetPointAddressClamped(xint - 1, yint - 1); ColorBgr8 p10 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 0, yint - 1); ColorBgr8 p20 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 1, yint - 1); ColorBgr8 p30 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 2, yint - 1); // 2nd row ColorBgr8 p01 = *(ColorBgr8 *)source.GetPointAddressClamped(xint - 1, yint + 0); ColorBgr8 p11 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 0, yint + 0); ColorBgr8 p21 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 1, yint + 0); ColorBgr8 p31 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 2, yint + 0); // 3rd row ColorBgr8 p02 = *(ColorBgr8 *)source.GetPointAddressClamped(xint - 1, yint + 1); ColorBgr8 p12 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 0, yint + 1); ColorBgr8 p22 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 1, yint + 1); ColorBgr8 p32 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 2, yint + 1); // 4th row ColorBgr8 p03 = *(ColorBgr8 *)source.GetPointAddressClamped(xint - 1, yint + 2); ColorBgr8 p13 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 0, yint + 2); ColorBgr8 p23 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 1, yint + 2); ColorBgr8 p33 = *(ColorBgr8 *)source.GetPointAddressClamped(xint + 2, yint + 2); float blue0 = BicubicUtil.CubicHermite(p00.B, p10.B, p20.B, p30.B, xfract); float blue1 = BicubicUtil.CubicHermite(p01.B, p11.B, p21.B, p31.B, xfract); float blue2 = BicubicUtil.CubicHermite(p02.B, p12.B, p22.B, p32.B, xfract); float blue3 = BicubicUtil.CubicHermite(p03.B, p13.B, p23.B, p33.B, xfract); float blue = BicubicUtil.CubicHermite(blue0, blue1, blue2, blue3, yfract); float green0 = BicubicUtil.CubicHermite(p00.G, p10.G, p20.G, p30.G, xfract); float green1 = BicubicUtil.CubicHermite(p01.G, p11.G, p21.G, p31.G, xfract); float green2 = BicubicUtil.CubicHermite(p02.G, p12.G, p22.G, p32.G, xfract); float green3 = BicubicUtil.CubicHermite(p03.G, p13.G, p23.G, p33.G, xfract); float green = BicubicUtil.CubicHermite(green0, green1, green2, green3, yfract); float red0 = BicubicUtil.CubicHermite(p00.R, p10.R, p20.R, p30.R, xfract); float red1 = BicubicUtil.CubicHermite(p01.R, p11.R, p21.R, p31.R, xfract); float red2 = BicubicUtil.CubicHermite(p02.R, p12.R, p22.R, p32.R, xfract); float red3 = BicubicUtil.CubicHermite(p03.R, p13.R, p23.R, p33.R, xfract); float red = BicubicUtil.CubicHermite(red0, red1, red2, red3, yfract); destRow->B = (byte)FloatUtil.Clamp(blue, 0, 255); destRow->G = (byte)FloatUtil.Clamp(green, 0, 255); destRow->R = (byte)FloatUtil.Clamp(red, 0, 255); destRow++; } } } finally { if (srcColCachePtr != IntPtr.Zero) { ImageSurfaceMemory.Free(srcColCachePtr); srcColCachePtr = IntPtr.Zero; } } }
protected override unsafe void BicubicFitSurfaceChecked(SurfaceBase source, Rectangle dstRoi) { Rectangle roi = Rectangle.Intersect(dstRoi, Bounds); IntPtr rColCacheIP = ImageSurfaceMemory.Allocate(4 * (ulong)roi.Width * (ulong)sizeof(double)); double *rColCache = (double *)rColCacheIP.ToPointer(); int srcWidth = source.Width; int srcHeight = source.Height; long srcStride = source.Stride; // Precompute and then cache the value of R() for each column for (int dstX = roi.Left; dstX < roi.Right; ++dstX) { double srcColumn = (double)(dstX * (srcWidth - 1)) / (double)(width - 1); double srcColumnFloor = Math.Floor(srcColumn); double srcColumnFrac = srcColumn - srcColumnFloor; for (int m = -1; m <= 2; ++m) { int index = (m + 1) + ((dstX - roi.Left) * 4); double x = m - srcColumnFrac; rColCache[index] = BicubicUtil.R(x); } } // Set this up so we can cache the R()'s for every row double *rRowCache = stackalloc double[4]; for (int dstY = roi.Top; dstY < roi.Bottom; ++dstY) { double srcRow = (double)(dstY * (srcHeight - 1)) / (double)(height - 1); double srcRowFloor = (double)Math.Floor(srcRow); double srcRowFrac = srcRow - srcRowFloor; int srcRowInt = (int)srcRow; ColorBgra16 *dstPtr = (ColorBgra16 *)GetPointAddressUnchecked(roi.Left, dstY); // Compute the R() values for this row for (int n = -1; n <= 2; ++n) { double x = srcRowFrac - n; rRowCache[n + 1] = BicubicUtil.R(x); } // See Perf Note below //int nFirst = Math.Max(-srcRowInt, -1); //int nLast = Math.Min(source.height - srcRowInt - 1, 2); for (int dstX = roi.Left; dstX < roi.Right; dstX++) { double srcColumn = (double)(dstX * (srcWidth - 1)) / (double)(width - 1); double srcColumnFloor = Math.Floor(srcColumn); int srcColumnInt = (int)srcColumn; double blueSum = 0; double greenSum = 0; double redSum = 0; double alphaSum = 0; double totalWeight = 0; // See Perf Note below //int mFirst = Math.Max(-srcColumnInt, -1); //int mLast = Math.Min(source.width - srcColumnInt - 1, 2); ColorBgra16 *srcPtr = (ColorBgra16 *)source.GetPointAddressUnchecked(srcColumnInt - 1, srcRowInt - 1); for (int n = -1; n <= 2; ++n) { int srcY = srcRowInt + n; for (int m = -1; m <= 2; ++m) { // Perf Note: It actually benchmarks faster on my system to do // a bounds check for every (m,n) than it is to limit the loop // to nFirst-Last and mFirst-mLast. // I'm leaving the code above, albeit commented out, so that // benchmarking between these two can still be performed. if (source.IsVisible(srcColumnInt + m, srcY)) { double w0 = rColCache[(m + 1) + (4 * (dstX - roi.Left))]; double w1 = rRowCache[n + 1]; double w = w0 * w1; blueSum += srcPtr->B * w * srcPtr->A; greenSum += srcPtr->G * w * srcPtr->A; redSum += srcPtr->R * w * srcPtr->A; alphaSum += srcPtr->A * w; totalWeight += w; } ++srcPtr; } srcPtr = (ColorBgra16 *)((byte *)(srcPtr - 4) + srcStride); } double alpha = alphaSum / totalWeight; double blue; double green; double red; if (alpha == 0) { blue = 0; green = 0; red = 0; } else { blue = blueSum / alphaSum; green = greenSum / alphaSum; red = redSum / alphaSum; // add 0.5 to ensure truncation to ulong results in rounding alpha += 0.5; blue += 0.5; green += 0.5; red += 0.5; } dstPtr->Bgra = (ulong)blue + ((ulong)green << 16) + ((ulong)red << 32) + ((ulong)alpha << 48); ++dstPtr; } // for (dstX... } // for (dstY... ImageSurfaceMemory.Free(rColCacheIP); }
protected override unsafe void BicubicFitSurfaceUnchecked(SurfaceBase source, Rectangle dstRoi) { Rectangle roi = Rectangle.Intersect(dstRoi, Bounds); IntPtr rColCacheIP = ImageSurfaceMemory.Allocate(4 * (ulong)roi.Width * (ulong)sizeof(double)); double *rColCache = (double *)rColCacheIP.ToPointer(); int srcWidth = source.Width; int srcHeight = source.Height; long srcStride = source.Stride; // Precompute and then cache the value of R() for each column for (int dstX = roi.Left; dstX < roi.Right; ++dstX) { double srcColumn = (double)(dstX * (srcWidth - 1)) / (double)(width - 1); double srcColumnFloor = Math.Floor(srcColumn); double srcColumnFrac = srcColumn - srcColumnFloor; for (int m = -1; m <= 2; ++m) { int index = (m + 1) + ((dstX - roi.Left) * 4); double x = m - srcColumnFrac; rColCache[index] = BicubicUtil.R(x); } } // Set this up so we can cache the R()'s for every row double *rRowCache = stackalloc double[4]; for (int dstY = roi.Top; dstY < roi.Bottom; ++dstY) { double srcRow = (double)(dstY * (srcHeight - 1)) / (double)(height - 1); double srcRowFloor = Math.Floor(srcRow); double srcRowFrac = srcRow - srcRowFloor; int srcRowInt = (int)srcRow; ColorBgra16 *dstPtr = (ColorBgra16 *)GetPointAddressUnchecked(roi.Left, dstY); // Compute the R() values for this row for (int n = -1; n <= 2; ++n) { double x = srcRowFrac - n; rRowCache[n + 1] = BicubicUtil.R(x); } rColCache = (double *)rColCacheIP.ToPointer(); ColorBgra16 *srcRowPtr = (ColorBgra16 *)source.GetRowAddressUnchecked(srcRowInt - 1); for (int dstX = roi.Left; dstX < roi.Right; dstX++) { double srcColumn = (double)(dstX * (srcWidth - 1)) / (double)(width - 1); double srcColumnFloor = Math.Floor(srcColumn); int srcColumnInt = (int)srcColumn; double blueSum = 0; double greenSum = 0; double redSum = 0; double alphaSum = 0; double totalWeight = 0; ColorBgra16 *srcPtr = srcRowPtr + srcColumnInt - 1; for (int n = 0; n <= 3; ++n) { double w0 = rColCache[0] * rRowCache[n]; double w1 = rColCache[1] * rRowCache[n]; double w2 = rColCache[2] * rRowCache[n]; double w3 = rColCache[3] * rRowCache[n]; double a0 = srcPtr[0].A; double a1 = srcPtr[1].A; double a2 = srcPtr[2].A; double a3 = srcPtr[3].A; alphaSum += (a0 * w0) + (a1 * w1) + (a2 * w2) + (a3 * w3); totalWeight += w0 + w1 + w2 + w3; blueSum += (a0 * srcPtr[0].B * w0) + (a1 * srcPtr[1].B * w1) + (a2 * srcPtr[2].B * w2) + (a3 * srcPtr[3].B * w3); greenSum += (a0 * srcPtr[0].G * w0) + (a1 * srcPtr[1].G * w1) + (a2 * srcPtr[2].G * w2) + (a3 * srcPtr[3].G * w3); redSum += (a0 * srcPtr[0].R * w0) + (a1 * srcPtr[1].R * w1) + (a2 * srcPtr[2].R * w2) + (a3 * srcPtr[3].R * w3); srcPtr = (ColorBgra16 *)((byte *)srcPtr + srcStride); } double alpha = alphaSum / totalWeight; double blue; double green; double red; if (alpha == 0) { blue = 0; green = 0; red = 0; } else { blue = blueSum / alphaSum; green = greenSum / alphaSum; red = redSum / alphaSum; // add 0.5 to ensure truncation to ulong results in rounding alpha += 0.5; blue += 0.5; green += 0.5; red += 0.5; } dstPtr->Bgra = (ulong)blue + ((ulong)green << 16) + ((ulong)red << 32) + ((ulong)alpha << 48); ++dstPtr; rColCache += 4; } // for (dstX... } // for (dstY... ImageSurfaceMemory.Free(rColCacheIP); }
protected override unsafe void FitSurfaceImpl(SurfaceBase source) { float lastRowIndex = height - 1; float lastColumnIndex = width - 1; IntPtr srcColCachePtr = IntPtr.Zero; try { srcColCachePtr = ImageSurfaceMemory.Allocate((ulong)width * sizeof(float)); float *srcColCache = (float *)srcColCachePtr; // Precompute the source column indexes. for (int x = 0; x < width; x++) { float u = x / lastColumnIndex; srcColCache[x] = (u * source.Width) - 0.5f; } for (int y = 0; y < height; y++) { ushort *destRow = (ushort *)GetRowAddressUnchecked(y); float v = y / lastRowIndex; float srcY = (v * source.Height) - 0.5f; int yint = (int)srcY; float yfract = srcY - (float)Math.Floor(srcY); for (int x = 0; x < width; x++) { float srcX = srcColCache[x]; int xint = (int)srcX; float xfract = srcX - (float)Math.Floor(srcX); // 1st row ushort p00 = *(ushort *)source.GetPointAddressClamped(xint - 1, yint - 1); ushort p10 = *(ushort *)source.GetPointAddressClamped(xint + 0, yint - 1); ushort p20 = *(ushort *)source.GetPointAddressClamped(xint + 1, yint - 1); ushort p30 = *(ushort *)source.GetPointAddressClamped(xint + 2, yint - 1); // 2nd row ushort p01 = *(ushort *)source.GetPointAddressClamped(xint - 1, yint + 0); ushort p11 = *(ushort *)source.GetPointAddressClamped(xint + 0, yint + 0); ushort p21 = *(ushort *)source.GetPointAddressClamped(xint + 1, yint + 0); ushort p31 = *(ushort *)source.GetPointAddressClamped(xint + 2, yint + 0); // 3rd row ushort p02 = *(ushort *)source.GetPointAddressClamped(xint - 1, yint + 1); ushort p12 = *(ushort *)source.GetPointAddressClamped(xint + 0, yint + 1); ushort p22 = *(ushort *)source.GetPointAddressClamped(xint + 1, yint + 1); ushort p32 = *(ushort *)source.GetPointAddressClamped(xint + 2, yint + 1); // 4th row ushort p03 = *(ushort *)source.GetPointAddressClamped(xint - 1, yint + 2); ushort p13 = *(ushort *)source.GetPointAddressClamped(xint + 0, yint + 2); ushort p23 = *(ushort *)source.GetPointAddressClamped(xint + 1, yint + 2); ushort p33 = *(ushort *)source.GetPointAddressClamped(xint + 2, yint + 2); float gray0 = BicubicUtil.CubicHermite(p00, p10, p20, p30, xfract); float gray1 = BicubicUtil.CubicHermite(p01, p11, p21, p31, xfract); float gray2 = BicubicUtil.CubicHermite(p02, p12, p22, p32, xfract); float gray3 = BicubicUtil.CubicHermite(p03, p13, p23, p33, xfract); float gray = BicubicUtil.CubicHermite(gray0, gray1, gray2, gray3, yfract); *destRow = (ushort)FloatUtil.Clamp(gray, 0, 32768); destRow++; } } } finally { if (srcColCachePtr != IntPtr.Zero) { ImageSurfaceMemory.Free(srcColCachePtr); srcColCachePtr = IntPtr.Zero; } } }
protected override unsafe void FitSurfaceImpl(SurfaceBase source) { float lastRowIndex = height - 1; float lastColumnIndex = width - 1; IntPtr srcColCachePtr = IntPtr.Zero; try { srcColCachePtr = ImageSurfaceMemory.Allocate((ulong)width * sizeof(float)); float *srcColCache = (float *)srcColCachePtr; // Precompute the source column indexes. for (int x = 0; x < width; x++) { float u = x / lastColumnIndex; srcColCache[x] = (u * source.Width) - 0.5f; } for (int y = 0; y < height; y++) { ColorCmyk8 *destRow = (ColorCmyk8 *)GetRowAddressUnchecked(y); float v = y / lastRowIndex; float srcY = (v * source.Height) - 0.5f; int yint = (int)srcY; float yfract = srcY - (float)Math.Floor(srcY); for (int x = 0; x < width; x++) { float srcX = srcColCache[x]; int xint = (int)srcX; float xfract = srcX - (float)Math.Floor(srcX); // 1st row ColorCmyk8 p00 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint - 1, yint - 1); ColorCmyk8 p10 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 0, yint - 1); ColorCmyk8 p20 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 1, yint - 1); ColorCmyk8 p30 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 2, yint - 1); // 2nd row ColorCmyk8 p01 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint - 1, yint + 0); ColorCmyk8 p11 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 0, yint + 0); ColorCmyk8 p21 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 1, yint + 0); ColorCmyk8 p31 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 2, yint + 0); // 3rd row ColorCmyk8 p02 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint - 1, yint + 1); ColorCmyk8 p12 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 0, yint + 1); ColorCmyk8 p22 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 1, yint + 1); ColorCmyk8 p32 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 2, yint + 1); // 4th row ColorCmyk8 p03 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint - 1, yint + 2); ColorCmyk8 p13 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 0, yint + 2); ColorCmyk8 p23 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 1, yint + 2); ColorCmyk8 p33 = *(ColorCmyk8 *)source.GetPointAddressClamped(xint + 2, yint + 2); float cyan0 = BicubicUtil.CubicHermite(p00.C, p10.C, p20.C, p30.C, xfract); float cyan1 = BicubicUtil.CubicHermite(p01.C, p11.C, p21.C, p31.C, xfract); float cyan2 = BicubicUtil.CubicHermite(p02.C, p12.C, p22.C, p32.C, xfract); float cyan3 = BicubicUtil.CubicHermite(p03.C, p13.C, p23.C, p33.C, xfract); float cyan = BicubicUtil.CubicHermite(cyan0, cyan1, cyan2, cyan3, yfract); float magenta0 = BicubicUtil.CubicHermite(p00.M, p10.M, p20.M, p30.M, xfract); float magenta1 = BicubicUtil.CubicHermite(p01.M, p11.M, p21.M, p31.M, xfract); float magenta2 = BicubicUtil.CubicHermite(p02.M, p12.M, p22.M, p32.M, xfract); float magenta3 = BicubicUtil.CubicHermite(p03.M, p13.M, p23.M, p33.M, xfract); float magenta = BicubicUtil.CubicHermite(magenta0, magenta1, magenta2, magenta3, yfract); float yellow0 = BicubicUtil.CubicHermite(p00.Y, p10.Y, p20.Y, p30.Y, xfract); float yellow1 = BicubicUtil.CubicHermite(p01.Y, p11.Y, p21.Y, p31.Y, xfract); float yellow2 = BicubicUtil.CubicHermite(p02.Y, p12.Y, p22.Y, p32.Y, xfract); float yellow3 = BicubicUtil.CubicHermite(p03.Y, p13.Y, p23.Y, p33.Y, xfract); float yellow = BicubicUtil.CubicHermite(yellow0, yellow1, yellow2, yellow3, yfract); float black0 = BicubicUtil.CubicHermite(p00.K, p10.K, p20.K, p30.K, xfract); float black1 = BicubicUtil.CubicHermite(p01.K, p11.K, p21.K, p31.K, xfract); float black2 = BicubicUtil.CubicHermite(p02.K, p12.K, p22.K, p32.K, xfract); float black3 = BicubicUtil.CubicHermite(p03.K, p13.K, p23.K, p33.K, xfract); float black = BicubicUtil.CubicHermite(black0, black1, black2, black3, yfract); destRow->C = (byte)FloatUtil.Clamp(cyan, 0, 255); destRow->M = (byte)FloatUtil.Clamp(magenta, 0, 255); destRow->Y = (byte)FloatUtil.Clamp(yellow, 0, 255); destRow->K = (byte)FloatUtil.Clamp(black, 0, 255); destRow++; } } } finally { if (srcColCachePtr != IntPtr.Zero) { ImageSurfaceMemory.Free(srcColCachePtr); srcColCachePtr = IntPtr.Zero; } } }