示例#1
0
        /// <summary>
        /// Copies the contents of the given surface to the upper left corner of this surface.
        /// </summary>
        /// <param name="source">The surface to copy pixels from.</param>
        /// <remarks>
        /// The source surface does not need to have the same dimensions as this surface. Clipping
        /// will be handled automatically. No resizing will be done.
        /// </remarks>
        private void CopySurface(MaskSurface source)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("Surface");
            }

            if (stride == source.stride &&
                width == source.width &&
                height == source.height)
            {
                unsafe
                {
                    Memory.Copy(scan0.VoidStar,
                                source.scan0.VoidStar,
                                ((ulong)(height - 1) * (ulong)stride) + (ulong)width);
                }
            }
            else
            {
                int copyWidth  = Math.Min(width, source.width);
                int copyHeight = Math.Min(height, source.height);

                unsafe
                {
                    for (int y = 0; y < copyHeight; ++y)
                    {
                        Memory.Copy(GetRowAddressUnchecked(y), source.GetRowAddressUnchecked(y), (ulong)copyWidth);
                    }
                }
            }
        }
示例#2
0
        /// <summary>
        /// Implements bicubic filtering with NO bounds checking at any pixel.
        /// </summary>
        private unsafe void BicubicFitSurfaceUnchecked(MaskSurface source, Rectangle dstRoi)
        {
            Rectangle roi   = Rectangle.Intersect(dstRoi, Bounds);
            Rectangle roiIn = Rectangle.Intersect(dstRoi, new Rectangle(1, 1, width - 1, height - 1));

            IntPtr  rColCacheIP = Memory.Allocate(4 * (long)roi.Width * (long)sizeof(double), false);
            double *rColCache   = (double *)rColCacheIP.ToPointer();

            // Precompute and then cache the value of R() for each column
            for (int dstX = roi.Left; dstX < roi.Right; ++dstX)
            {
                double srcColumn      = (double)(dstX * (source.width - 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] = 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 * (source.height - 1)) / (double)(height - 1);
                double srcRowFloor = Math.Floor(srcRow);
                double srcRowFrac  = srcRow - srcRowFloor;
                int    srcRowInt   = (int)srcRow;
                byte * dstPtr      = 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] = R(x);
                }

                rColCache = (double *)rColCacheIP.ToPointer();
                byte *srcRowPtr = source.GetRowAddressUnchecked(srcRowInt - 1);

                for (int dstX = roi.Left; dstX < roi.Right; dstX++)
                {
                    double srcColumn      = (double)(dstX * (source.width - 1)) / (double)(width - 1);
                    double srcColumnFloor = Math.Floor(srcColumn);
                    double srcColumnFrac  = srcColumn - srcColumnFloor;
                    int    srcColumnInt   = (int)srcColumn;

                    double graySum     = 0;
                    double alphaSum    = 0;
                    double totalWeight = 0;

                    byte *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 = 255.0;
                        double a1 = 255.0;
                        double a2 = 255.0;
                        double a3 = 255.0;

                        alphaSum    += (a0 * w0) + (a1 * w1) + (a2 * w2) + (a3 * w3);
                        totalWeight += w0 + w1 + w2 + w3;

                        graySum += (a0 * srcPtr[0] * w0) + (a1 * srcPtr[1] * w1) + (a2 * srcPtr[2] * w2) + (a3 * srcPtr[3] * w3);

                        srcPtr = ((byte *)srcPtr + source.stride);
                    }

                    double alpha = alphaSum / totalWeight;

                    double gray;

                    if (alpha == 0)
                    {
                        gray = 0;
                    }
                    else
                    {
                        gray = graySum / alphaSum;
                        // add 0.5 to ensure truncation to uint results in rounding
                        gray += 0.5;
                    }

                    *dstPtr = (byte)gray;
                    ++dstPtr;
                    rColCache += 4;
                } // for (dstX...
            }     // for (dstY...

            Memory.Free(rColCacheIP);
        }