示例#1
0
        /// <summary>
        /// Provides a default implementation for performing dst = F(dst, src) or F(src) over some rectangle
        /// of interest. May be slightly faster than calling the other multi-parameter Apply method, as less
        /// variables are used in the implementation, thus inducing less register pressure.
        /// </summary>
        /// <param name="dst">The Surface to write pixels to, and from which pixels are read and used as the lhs parameter for calling the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>.</param>
        /// <param name="dstOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the dst Surface.</param>
        /// <param name="src">The Surface to read pixels from for the rhs parameter given to the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>b>.</param></param>
        /// <param name="srcOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the src Surface.</param>
        /// <param name="roiSize">The size of the rectangles-of-interest for all Surfaces.</param>
        public void ApplyBase(Surface dst, Point dstOffset, Surface src, Point srcOffset, Size roiSize)
        {
            // Create bounding rectangles for each Surface
            Rectangle dstRect = new Rectangle(dstOffset, roiSize);

            if (dstRect.Width == 0 || dstRect.Height == 0)
            {
                return;
            }

            Rectangle srcRect = new Rectangle(srcOffset, roiSize);

            if (srcRect.Width == 0 || srcRect.Height == 0)
            {
                return;
            }

            // Clip those rectangles to those Surface's bounding rectangles
            Rectangle dstClip = Rectangle.Intersect(dstRect, dst.Bounds);
            Rectangle srcClip = Rectangle.Intersect(srcRect, src.Bounds);

            // If any of those Rectangles actually got clipped, then throw an exception
            if (dstRect != dstClip)
            {
                throw new ArgumentOutOfRangeException
                      (
                          "roiSize",
                          "Destination roi out of bounds" +
                          ", dst.Size=" + dst.Size.ToString() +
                          ", dst.Bounds=" + dst.Bounds.ToString() +
                          ", dstOffset=" + dstOffset.ToString() +
                          ", src.Size=" + src.Size.ToString() +
                          ", srcOffset=" + srcOffset.ToString() +
                          ", roiSize=" + roiSize.ToString() +
                          ", dstRect=" + dstRect.ToString() +
                          ", dstClip=" + dstClip.ToString() +
                          ", srcRect=" + srcRect.ToString() +
                          ", srcClip=" + srcClip.ToString()
                      );
            }

            if (srcRect != srcClip)
            {
                throw new ArgumentOutOfRangeException("roiSize", "Source roi out of bounds");
            }

            // Cache the width and height properties
            int width  = roiSize.Width;
            int height = roiSize.Height;

            // Do the work.
            unsafe {
                for (int row = 0; row < roiSize.Height; ++row)
                {
                    ColorBgra *dstPtr = dst.GetPointAddress(dstOffset.X, dstOffset.Y + row);
                    ColorBgra *srcPtr = src.GetPointAddress(srcOffset.X, srcOffset.Y + row);
                    Apply(dstPtr, srcPtr, width);
                }
            }
        }
示例#2
0
 private unsafe void ApplyRectangle(Surface surface, Rectangle rect)
 {
     for (int y = rect.Top; y < rect.Bottom; ++y)
     {
         ColorBgra *ptr = surface.GetPointAddress(rect.Left, y);
         Apply(ptr, rect.Width);
     }
 }
示例#3
0
 private unsafe void ApplyRectangle(Surface surface, Rectangle rect)
 {
     for (int y = rect.Top; y < rect.Bottom; ++y)
     {
         ColorBgra *ptr = surface.GetPointAddress(rect.Left, y);
         Apply(ptr, rect.Width);
     }
 }
示例#4
0
 public void Apply(Surface dst, Surface src, Rectangle roi)
 {
     for (int y = roi.Top; y < roi.Bottom; ++y)
     {
         ColorBgra *dstPtr = dst.GetPointAddress(roi.Left, y);
         ColorBgra *srcPtr = src.GetPointAddress(roi.Left, y);
         Apply(dstPtr, srcPtr, roi.Width);
     }
 }
示例#5
0
        /// <summary>
        /// Provides a default implementation for performing dst = F(lhs, rhs) over some rectangle of interest.
        /// </summary>
        /// <param name="dst">The Surface to write pixels to.</param>
        /// <param name="dstOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the dst Surface.</param>
        /// <param name="lhs">The Surface to read pixels from for the lhs parameter given to the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>b>.</param></param>
        /// <param name="lhsOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the lhs Surface.</param>
        /// <param name="rhs">The Surface to read pixels from for the rhs parameter given to the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b></param>
        /// <param name="rhsOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the rhs Surface.</param>
        /// <param name="roiSize">The size of the rectangles-of-interest for all Surfaces.</param>
        public void Apply(Surface dst, Point dstOffset,
                          Surface lhs, Point lhsOffset,
                          Surface rhs, Point rhsOffset,
                          Size roiSize)
        {
            // Bounds checking only enabled in Debug builds.
#if DEBUG
            // Create bounding rectangles for each Surface
            Rectangle dstRect = new Rectangle(dstOffset, roiSize);
            Rectangle lhsRect = new Rectangle(lhsOffset, roiSize);
            Rectangle rhsRect = new Rectangle(rhsOffset, roiSize);

            // Clip those rectangles to those Surface's bounding rectangles
            Rectangle dstClip = Rectangle.Intersect(dstRect, dst.Bounds);
            Rectangle lhsClip = Rectangle.Intersect(lhsRect, lhs.Bounds);
            Rectangle rhsClip = Rectangle.Intersect(rhsRect, rhs.Bounds);

            // If any of those Rectangles actually got clipped, then throw an exception
            if (dstRect != dstClip)
            {
                throw new ArgumentOutOfRangeException("roiSize", "Destination roi out of bounds");
            }

            if (lhsRect != lhsClip)
            {
                throw new ArgumentOutOfRangeException("roiSize", "lhs roi out of bounds");
            }

            if (rhsRect != rhsClip)
            {
                throw new ArgumentOutOfRangeException("roiSize", "rhs roi out of bounds");
            }
#endif

            // Cache the width and height properties
            int width  = roiSize.Width;
            int height = roiSize.Height;

            // Do the work.
            unsafe
            {
                for (int row = 0; row < height; ++row)
                {
                    ColorBgra *dstPtr = dst.GetPointAddress(dstOffset.X, dstOffset.Y + row);
                    ColorBgra *lhsPtr = lhs.GetPointAddress(lhsOffset.X, lhsOffset.Y + row);
                    ColorBgra *rhsPtr = rhs.GetPointAddress(rhsOffset.X, rhsOffset.Y + row);

                    Apply(dstPtr, lhsPtr, rhsPtr, width);
                }
            }
        }
示例#6
0
            public unsafe void DrawScansNearestNeighbor(object cpuNumberObj)
            {
                int   cpuNumber = (int)cpuNumberObj;
                int   inc       = Processor.LogicalCpuCount;
                void *scan0     = src.Scan0.VoidStar;
                int   stride    = src.Stride;

                PointF[] pts = new PointF[1];

                for (int i = cpuNumber; i < this.dstScans.Length; i += inc)
                {
                    Rectangle dstRect = this.dstScans[i];

                    dstRect.Intersect(dst.Bounds);

                    if (dstRect.Width == 0 || dstRect.Height == 0)
                    {
                        continue;
                    }

                    pts[0] = new PointF(dstRect.Left, dstRect.Top);

                    this.inverses[cpuNumber].TransformPoints(pts);

                    pts[0].X -= this.boundsX;
                    pts[0].Y -= this.boundsY;

                    int fp_srcPtRowX = (int)(pts[0].X * fp_MultFactor);
                    int fp_srcPtRowY = (int)(pts[0].Y * fp_MultFactor);

                    for (int dstY = dstRect.Top; dstY < dstRect.Bottom; ++dstY)
                    {
                        int fp_srcPtColX = fp_srcPtRowX;
                        int fp_srcPtColY = fp_srcPtRowY;
                        fp_srcPtRowX += this.fp_dsxddy;
                        fp_srcPtRowY += this.fp_dsyddy;

                        if (dstY >= 0)
                        {
                            // We render the left side, then the right side, then the in-between pixels.
                            // The reason for this is that the left and right sides have the chance that,
                            // due to lack of enough precision, we will dive off the end of the surface
                            // and into memory that we can't actually read from. To solve this, the left
                            // and right sides will clamp the pixel coordinates that they read from,
                            // and then keep track of when they were able to stomp clamping these values.
                            // Then, rendering the middle part of the scanline is able to be completed
                            // without the expensive clamping operation.

                            int        dstX             = dstRect.Left;
                            ColorBgra *dstPtr           = dst.GetPointAddress(dstX, dstY);
                            ColorBgra *dstPtrEnd        = dstPtr + dstRect.Width;
                            int        fp_srcPtColLastX = fp_srcPtColX + (this.fp_dsxddx * (dstRect.Width - 1));
                            int        fp_srcPtColLastY = fp_srcPtColY + (this.fp_dsyddx * (dstRect.Width - 1));

                            // Left side
                            while (dstPtr < dstPtrEnd)
                            {
                                int srcPtColX = (fp_srcPtColX + fp_RoundFactor) >> fp_ShiftFactor;
                                int srcPtColY = (fp_srcPtColY + fp_RoundFactor) >> fp_ShiftFactor;

                                int srcX   = Clamp(srcPtColX, 0, src.Width - 1);
                                int srcY   = Clamp(srcPtColY, 0, src.Height - 1);
                                *   dstPtr = this.src.GetPointUnchecked(srcX, srcY);

                                ++dstPtr;
                                fp_srcPtColX += this.fp_dsxddx;
                                fp_srcPtColY += this.fp_dsyddx;

                                if (srcX == srcPtColX && srcY == srcPtColY)
                                {
                                    break;
                                }
                            }

                            ColorBgra *startFastPtr = dstPtr;
                            dstPtr = dstPtrEnd - 1;

                            // Right side
                            while (dstPtr >= startFastPtr)
                            {
                                int srcPtColX = (fp_srcPtColLastX + fp_RoundFactor) >> fp_ShiftFactor;
                                int srcPtColY = (fp_srcPtColLastY + fp_RoundFactor) >> fp_ShiftFactor;

                                int srcX   = Clamp(srcPtColX, 0, src.Width - 1);
                                int srcY   = Clamp(srcPtColY, 0, src.Height - 1);
                                *   dstPtr = this.src.GetPointUnchecked(srcX, srcY);

                                if (srcX == srcPtColX && srcY == srcPtColY)
                                {
                                    break;
                                }

                                --dstPtr;
                                fp_srcPtColLastX -= this.fp_dsxddx;
                                fp_srcPtColLastY -= this.fp_dsyddx;
                            }

                            ColorBgra *endFastPtr = dstPtr;

                            // Middle
                            while (startFastPtr < endFastPtr)
                            {
                                int srcPtColX = (fp_srcPtColX + fp_RoundFactor) >> fp_ShiftFactor;
                                int srcPtColY = (fp_srcPtColY + fp_RoundFactor) >> fp_ShiftFactor;

                                // This is GetPointUnchecked inlined -- avoid the overhead, especially, of the call to MemoryBlock.VoidStar
                                // which has the potential to throw an exception which is then NOT inlined.
                                startFastPtr->Bgra = (unchecked (srcPtColX + (ColorBgra *)(((byte *)scan0) + (srcPtColY * stride))))->Bgra;

                                ++startFastPtr;
                                fp_srcPtColX += this.fp_dsxddx;
                                fp_srcPtColY += this.fp_dsyddx;
                            }
                        }
                    }
                }
            }
示例#7
0
 public virtual void Apply(Surface dst, Point dstOffset, Surface src, Point srcOffset, int scanLength)
 {
     Apply(dst.GetPointAddress(dstOffset), src.GetPointAddress(srcOffset), scanLength);
 }
示例#8
0
 public void Apply(Surface dst, Surface src, Rectangle roi)
 {
     for (int y = roi.Top; y < roi.Bottom; ++y)
     {
         ColorBgra *dstPtr = dst.GetPointAddress(roi.Left, y);
         ColorBgra *srcPtr = src.GetPointAddress(roi.Left, y);
         Apply(dstPtr, srcPtr, roi.Width);
     }
 }
示例#9
0
        /// <summary>
        /// Provides a default implementation for performing dst = F(lhs, rhs) over some rectangle of interest.
        /// </summary>
        /// <param name="dst">The Surface to write pixels to.</param>
        /// <param name="dstOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the dst Surface.</param>
        /// <param name="lhs">The Surface to read pixels from for the lhs parameter given to the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>b>.</param></param>
        /// <param name="lhsOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the lhs Surface.</param>
        /// <param name="rhs">The Surface to read pixels from for the rhs parameter given to the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b></param>
        /// <param name="rhsOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the rhs Surface.</param>
        /// <param name="roiSize">The size of the rectangles-of-interest for all Surfaces.</param>
        public void Apply(Surface dst, Point dstOffset, 
                          Surface lhs, Point lhsOffset, 
                          Surface rhs, Point rhsOffset, 
                          Size roiSize)
        {
            // Bounds checking only enabled in Debug builds.
            #if DEBUG
            // Create bounding rectangles for each Surface
            Rectangle dstRect = new Rectangle(dstOffset, roiSize);
            Rectangle lhsRect = new Rectangle(lhsOffset, roiSize);
            Rectangle rhsRect = new Rectangle(rhsOffset, roiSize);

            // Clip those rectangles to those Surface's bounding rectangles
            Rectangle dstClip = Rectangle.Intersect(dstRect, dst.Bounds);
            Rectangle lhsClip = Rectangle.Intersect(lhsRect, lhs.Bounds);
            Rectangle rhsClip = Rectangle.Intersect(rhsRect, rhs.Bounds);

            // If any of those Rectangles actually got clipped, then throw an exception
            if (dstRect != dstClip)
            {
                throw new ArgumentOutOfRangeException("roiSize", "Destination roi out of bounds");
            }

            if (lhsRect != lhsClip)
            {
                throw new ArgumentOutOfRangeException("roiSize", "lhs roi out of bounds");
            }

            if (rhsRect != rhsClip)
            {
                throw new ArgumentOutOfRangeException("roiSize", "rhs roi out of bounds");
            }
            #endif

            // Cache the width and height properties
            int width = roiSize.Width;
            int height = roiSize.Height;

            // Do the work.
            unsafe
            {
                for (int row = 0; row < height; ++row)
                {
                    ColorBgra *dstPtr = dst.GetPointAddress(dstOffset.X, dstOffset.Y + row);
                    ColorBgra *lhsPtr = lhs.GetPointAddress(lhsOffset.X, lhsOffset.Y + row);
                    ColorBgra *rhsPtr = rhs.GetPointAddress(rhsOffset.X, rhsOffset.Y + row);

                    Apply(dstPtr, lhsPtr, rhsPtr, width);
                }
            }
        }
示例#10
0
 public virtual void Apply(Surface dst, Point dstOffset, Surface src, Point srcOffset, int scanLength)
 {
     Apply(dst.GetPointAddress(dstOffset), src.GetPointAddress(srcOffset), scanLength);
 }
        public unsafe override void Render(Surface dst, System.Drawing.Point offset)
        {
            if (OwnerList.ScaleFactor < new ScaleFactor(2, 1))
            {
                return;
            }

            int[] d2SLookupX = OwnerList.Dst2SrcLookupX;
            int[] d2SLookupY = OwnerList.Dst2SrcLookupY;
            int[] s2DLookupX = OwnerList.Src2DstLookupX;
            int[] s2DLookupY = OwnerList.Src2DstLookupY;

            ColorBgra[] blackAndWhite = new ColorBgra[2] { ColorBgra.White, ColorBgra.Black };

            // draw horizontal lines
            int sTop = d2SLookupY[offset.Y];
            int sBottom = d2SLookupY[offset.Y + dst.Height];

            for (int srcY = sTop; srcY <= sBottom; ++srcY)
            {
                int dstY = s2DLookupY[srcY];
                int dstRow = dstY - offset.Y;

                if (dst.IsRowVisible(dstRow))
                {
                    ColorBgra *dstRowPtr = dst.GetRowAddress(dstRow);
                    ColorBgra *dstRowEndPtr = dstRowPtr + dst.Width;

                    dstRowPtr += offset.X & 1;

                    while (dstRowPtr < dstRowEndPtr)
                    {
                        *dstRowPtr = ColorBgra.Black;
                        dstRowPtr += 2;
                    }
                }
            }

            // draw vertical lines
            int sLeft = d2SLookupX[offset.X];
            int sRight = d2SLookupX[offset.X + dst.Width];

            for (int srcX = sLeft; srcX <= sRight; ++srcX)
            {
                int dstX = s2DLookupX[srcX];
                int dstCol = dstX - offset.X;

                if (dst.IsColumnVisible(dstX - offset.X))
                {
                    byte *dstColPtr = (byte *)dst.GetPointAddress(dstCol, 0);
                    byte *dstColEndPtr = dstColPtr + dst.Stride * dst.Height;

                    dstColPtr += (offset.Y & 1) * dst.Stride;

                    while (dstColPtr < dstColEndPtr)
                    {
                        *((ColorBgra *)dstColPtr) = ColorBgra.Black;
                        dstColPtr += 2 * dst.Stride;
                    }
                }
            }
        }
示例#12
0
 public override void Apply(Surface dst, Point dstOffset, Surface src, Point srcOffset, int roiLength)
 {
     Apply(dst.GetPointAddress(dstOffset), src.GetPointAddress(srcOffset), roiLength);
 }
示例#13
0
 public void Apply(Surface surface, Scanline scan)
 {
     Apply(surface.GetPointAddress(scan.X, scan.Y), scan.Length);
 }
示例#14
0
        public unsafe override void Render(Surface dst, System.Drawing.Point offset)
        {
            if (OwnerList.ScaleFactor < new ScaleFactor(2, 1))
            {
                return;
            }

            int[] d2SLookupX = OwnerList.Dst2SrcLookupX;
            int[] d2SLookupY = OwnerList.Dst2SrcLookupY;
            int[] s2DLookupX = OwnerList.Src2DstLookupX;
            int[] s2DLookupY = OwnerList.Src2DstLookupY;

            ColorBgra[] blackAndWhite = new ColorBgra[2] {
                ColorBgra.White, ColorBgra.Black
            };

            // draw horizontal lines
            int sTop    = d2SLookupY[offset.Y];
            int sBottom = d2SLookupY[offset.Y + dst.Height];

            for (int srcY = sTop; srcY <= sBottom; ++srcY)
            {
                int dstY   = s2DLookupY[srcY];
                int dstRow = dstY - offset.Y;

                if (dst.IsRowVisible(dstRow))
                {
                    ColorBgra *dstRowPtr    = dst.GetRowAddress(dstRow);
                    ColorBgra *dstRowEndPtr = dstRowPtr + dst.Width;

                    dstRowPtr += offset.X & 1;

                    while (dstRowPtr < dstRowEndPtr)
                    {
                        *dstRowPtr = ColorBgra.Black;
                        dstRowPtr += 2;
                    }
                }
            }

            // draw vertical lines
            int sLeft  = d2SLookupX[offset.X];
            int sRight = d2SLookupX[offset.X + dst.Width];

            for (int srcX = sLeft; srcX <= sRight; ++srcX)
            {
                int dstX   = s2DLookupX[srcX];
                int dstCol = dstX - offset.X;

                if (dst.IsColumnVisible(dstX - offset.X))
                {
                    byte *dstColPtr    = (byte *)dst.GetPointAddress(dstCol, 0);
                    byte *dstColEndPtr = dstColPtr + dst.Stride * dst.Height;

                    dstColPtr += (offset.Y & 1) * dst.Stride;

                    while (dstColPtr < dstColEndPtr)
                    {
                        *((ColorBgra *)dstColPtr) = ColorBgra.Black;
                        dstColPtr += 2 * dst.Stride;
                    }
                }
            }
        }
示例#15
0
        public unsafe void Render(Surface surface, Rectangle[] rois, int startIndex, int length)
        {
            byte startAlpha;
            byte endAlpha;

            if (this.alphaOnly)
            {
                ComputeAlphaOnlyValuesFromColors(this.startColor, this.endColor, out startAlpha, out endAlpha);
            }
            else
            {
                startAlpha = this.startColor.A;
                endAlpha = this.endColor.A;
            }

            for (int ri = startIndex; ri < startIndex + length; ++ri)
            {
                Rectangle rect = rois[ri];

                if (this.startPoint == this.endPoint)
                {
                    // Start and End point are the same ... fill with solid color.
                    for (int y = rect.Top; y < rect.Bottom; ++y)
                    {
                        ColorBgra* pixelPtr = surface.GetPointAddress(rect.Left, y);

                        for (int x = rect.Left; x < rect.Right; ++x)
                        {
                            ColorBgra result;

                            if (this.alphaOnly && this.alphaBlending)
                            {
                                byte resultAlpha = (byte)Utility.FastDivideShortByByte((ushort)(pixelPtr->A * endAlpha), 255);
                                result = *pixelPtr;
                                result.A = resultAlpha;
                            }
                            else if (this.alphaOnly && !this.alphaBlending)
                            {
                                result = *pixelPtr;
                                result.A = endAlpha;
                            }
                            else if (!this.alphaOnly && this.alphaBlending)
                            {
                                result = this.normalBlendOp.Apply(*pixelPtr, this.endColor);
                            }
                            else //if (!this.alphaOnly && !this.alphaBlending)
                            {
                                result = this.endColor;
                            }

                            *pixelPtr = result;
                            ++pixelPtr;
                        }
                    }
                }
                else
                {
                    for (int y = rect.Top; y < rect.Bottom; ++y)
                    {
                        ColorBgra* pixelPtr = surface.GetPointAddress(rect.Left, y);

                        if (this.alphaOnly && this.alphaBlending)
                        {
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                float lerpUnbounded = ComputeUnboundedLerp(x, y);
                                float lerpBounded = BoundLerp(lerpUnbounded);
                                byte lerpByte = (byte)(lerpBounded * 255.0f);
                                byte lerpAlpha = this.lerpAlphas[lerpByte];
                                byte resultAlpha = Utility.FastScaleByteByByte(pixelPtr->A, lerpAlpha);
                                pixelPtr->A = resultAlpha;
                                ++pixelPtr;
                            }
                        }
                        else if (this.alphaOnly && !this.alphaBlending)
                        {
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                float lerpUnbounded = ComputeUnboundedLerp(x, y);
                                float lerpBounded = BoundLerp(lerpUnbounded);
                                byte lerpByte = (byte)(lerpBounded * 255.0f);
                                byte lerpAlpha = this.lerpAlphas[lerpByte];
                                pixelPtr->A = lerpAlpha;
                                ++pixelPtr;
                            }
                        }
                        else if (!this.alphaOnly && (this.alphaBlending && (startAlpha != 255 || endAlpha != 255)))
                        {
                            // If we're doing all color channels, and we're doing alpha blending, and if alpha blending is necessary
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                float lerpUnbounded = ComputeUnboundedLerp(x, y);
                                float lerpBounded = BoundLerp(lerpUnbounded);
                                byte lerpByte = (byte)(lerpBounded * 255.0f);
                                ColorBgra lerpColor = this.lerpColors[lerpByte];
                                ColorBgra result = this.normalBlendOp.Apply(*pixelPtr, lerpColor);
                                *pixelPtr = result;
                                ++pixelPtr;
                            }
                        }
                        else //if (!this.alphaOnly && !this.alphaBlending) // or sC.A == 255 && eC.A == 255
                        {
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                float lerpUnbounded = ComputeUnboundedLerp(x, y);
                                float lerpBounded = BoundLerp(lerpUnbounded);
                                byte lerpByte = (byte)(lerpBounded * 255.0f);
                                ColorBgra lerpColor = this.lerpColors[lerpByte];
                                *pixelPtr = lerpColor;
                                ++pixelPtr;
                            }
                        }
                    }
                }
            }

            AfterRender();
        }
示例#16
0
        public unsafe void Render(Surface surface, Rectangle[] rois, int startIndex, int length)
        {
            byte startAlpha;
            byte endAlpha;

            if (this.alphaOnly)
            {
                ComputeAlphaOnlyValuesFromColors(this.startColor, this.endColor, out startAlpha, out endAlpha);
            }
            else
            {
                startAlpha = this.startColor.A;
                endAlpha   = this.endColor.A;
            }

            for (int ri = startIndex; ri < startIndex + length; ++ri)
            {
                Rectangle rect = rois[ri];

                if (this.startPoint == this.endPoint)
                {
                    // Start and End point are the same ... fill with solid color.
                    for (int y = rect.Top; y < rect.Bottom; ++y)
                    {
                        ColorBgra *pixelPtr = surface.GetPointAddress(rect.Left, y);

                        for (int x = rect.Left; x < rect.Right; ++x)
                        {
                            ColorBgra result;

                            if (this.alphaOnly && this.alphaBlending)
                            {
                                byte resultAlpha = (byte)Utility.FastDivideShortByByte((ushort)(pixelPtr->A * endAlpha), 255);
                                result   = *pixelPtr;
                                result.A = resultAlpha;
                            }
                            else if (this.alphaOnly && !this.alphaBlending)
                            {
                                result   = *pixelPtr;
                                result.A = endAlpha;
                            }
                            else if (!this.alphaOnly && this.alphaBlending)
                            {
                                result = this.normalBlendOp.Apply(*pixelPtr, this.endColor);
                            }
                            else //if (!this.alphaOnly && !this.alphaBlending)
                            {
                                result = this.endColor;
                            }

                            *pixelPtr = result;
                            ++pixelPtr;
                        }
                    }
                }
                else
                {
                    for (int y = rect.Top; y < rect.Bottom; ++y)
                    {
                        ColorBgra *pixelPtr = surface.GetPointAddress(rect.Left, y);

                        if (this.alphaOnly && this.alphaBlending)
                        {
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                float lerpUnbounded = ComputeUnboundedLerp(x, y);
                                float lerpBounded   = BoundLerp(lerpUnbounded);
                                byte  lerpByte      = (byte)(lerpBounded * 255.0f);
                                byte  lerpAlpha     = this.lerpAlphas[lerpByte];
                                byte  resultAlpha   = (byte)Utility.FastScaleByteByByte(pixelPtr->A, lerpAlpha);
                                pixelPtr->A = resultAlpha;
                                ++pixelPtr;
                            }
                        }
                        else if (this.alphaOnly && !this.alphaBlending)
                        {
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                float lerpUnbounded = ComputeUnboundedLerp(x, y);
                                float lerpBounded   = BoundLerp(lerpUnbounded);
                                byte  lerpByte      = (byte)(lerpBounded * 255.0f);
                                byte  lerpAlpha     = this.lerpAlphas[lerpByte];
                                pixelPtr->A = lerpAlpha;
                                ++pixelPtr;
                            }
                        }
                        else if (!this.alphaOnly && (this.alphaBlending && (startAlpha != 255 || endAlpha != 255)))
                        {
                            // If we're doing all color channels, and we're doing alpha blending, and if alpha blending is necessary
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                float     lerpUnbounded = ComputeUnboundedLerp(x, y);
                                float     lerpBounded   = BoundLerp(lerpUnbounded);
                                byte      lerpByte      = (byte)(lerpBounded * 255.0f);
                                ColorBgra lerpColor     = this.lerpColors[lerpByte];
                                ColorBgra result        = this.normalBlendOp.Apply(*pixelPtr, lerpColor);
                                *         pixelPtr      = result;
                                ++pixelPtr;
                            }
                        }
                        else //if (!this.alphaOnly && !this.alphaBlending) // or sC.A == 255 && eC.A == 255
                        {
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                float     lerpUnbounded = ComputeUnboundedLerp(x, y);
                                float     lerpBounded   = BoundLerp(lerpUnbounded);
                                byte      lerpByte      = (byte)(lerpBounded * 255.0f);
                                ColorBgra lerpColor     = this.lerpColors[lerpByte];
                                *         pixelPtr      = lerpColor;
                                ++pixelPtr;
                            }
                        }
                    }
                }
            }

            AfterRender();
        }
示例#17
0
 public void Apply(Surface surface, Scanline scan)
 {
     Apply(surface.GetPointAddress(scan.X, scan.Y), scan.Length);
 }
示例#18
0
        /// <summary>
        /// Provides a default implementation for performing dst = F(dst, src) or F(src) over some rectangle 
        /// of interest. May be slightly faster than calling the other multi-parameter Apply method, as less 
        /// variables are used in the implementation, thus inducing less register pressure.
        /// </summary>
        /// <param name="dst">The Surface to write pixels to, and from which pixels are read and used as the lhs parameter for calling the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>.</param>
        /// <param name="dstOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the dst Surface.</param>
        /// <param name="src">The Surface to read pixels from for the rhs parameter given to the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>b>.</param></param>
        /// <param name="srcOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the src Surface.</param>
        /// <param name="roiSize">The size of the rectangles-of-interest for all Surfaces.</param>
        public void ApplyBase(Surface dst, Point dstOffset, Surface src, Point srcOffset, Size roiSize)
        {
            // Create bounding rectangles for each Surface
            Rectangle dstRect = new Rectangle(dstOffset, roiSize);

            if (dstRect.Width == 0 || dstRect.Height == 0)
            {
                return;
            }

            Rectangle srcRect = new Rectangle(srcOffset, roiSize);

            if (srcRect.Width == 0 || srcRect.Height == 0)
            {
                return;
            }

            // Clip those rectangles to those Surface's bounding rectangles
            Rectangle dstClip = Rectangle.Intersect(dstRect, dst.Bounds);
            Rectangle srcClip = Rectangle.Intersect(srcRect, src.Bounds);

            // If any of those Rectangles actually got clipped, then throw an exception
            if (dstRect != dstClip)
            {
                throw new ArgumentOutOfRangeException
                (
                    "roiSize",
                    "Destination roi out of bounds" +
                    ", dst.Size=" + dst.Size.ToString() +
                    ", dst.Bounds=" + dst.Bounds.ToString() +
                    ", dstOffset=" + dstOffset.ToString() +
                    ", src.Size=" + src.Size.ToString() +
                    ", srcOffset=" + srcOffset.ToString() +
                    ", roiSize=" + roiSize.ToString() +
                    ", dstRect=" + dstRect.ToString() +
                    ", dstClip=" + dstClip.ToString() +
                    ", srcRect=" + srcRect.ToString() +
                    ", srcClip=" + srcClip.ToString()
                );
            }

            if (srcRect != srcClip)
            {
                throw new ArgumentOutOfRangeException("roiSize", "Source roi out of bounds");
            }

            // Cache the width and height properties
            int width = roiSize.Width;
            int height = roiSize.Height;

            // Do the work.
            unsafe
            {
                for (int row = 0; row < roiSize.Height; ++row)
                {
                    ColorBgra *dstPtr = dst.GetPointAddress(dstOffset.X, dstOffset.Y + row);
                    ColorBgra *srcPtr = src.GetPointAddress(srcOffset.X, srcOffset.Y + row);
                    Apply(dstPtr, srcPtr, width);
                }
            }
        }
示例#19
0
 public override void Apply(Surface dst, Point dstOffset, Surface src, Point srcOffset, int roiLength)
 {
     Apply(dst.GetPointAddress(dstOffset), src.GetPointAddress(srcOffset), roiLength);
 }