Ejemplo n.º 1
0
        public override unsafe void SuperSampleFitSurface(SurfaceBase source)
        {
            Rectangle dstRoi2 = Rectangle.Intersect(source.Bounds, Bounds);

            int  srcHeight = source.Height;
            int  srcWidth  = source.Width;
            long srcStride = source.Stride / 2;

            for (int dstY = dstRoi2.Top; dstY < dstRoi2.Bottom; ++dstY)
            {
                double srcTop       = (double)(dstY * srcHeight) / (double)height;
                double srcTopFloor  = Math.Floor(srcTop);
                double srcTopWeight = 1 - (srcTop - srcTopFloor);
                int    srcTopInt    = (int)srcTopFloor;

                double srcBottom       = (double)((dstY + 1) * srcHeight) / (double)height;
                double srcBottomFloor  = Math.Floor(srcBottom - 0.00001);
                double srcBottomWeight = srcBottom - srcBottomFloor;
                int    srcBottomInt    = (int)srcBottomFloor;

                ushort *dstPtr = (ushort *)GetPointAddressUnchecked(dstRoi2.Left, dstY);

                for (int dstX = dstRoi2.Left; dstX < dstRoi2.Right; ++dstX)
                {
                    double srcLeft       = (double)(dstX * srcWidth) / (double)width;
                    double srcLeftFloor  = Math.Floor(srcLeft);
                    double srcLeftWeight = 1 - (srcLeft - srcLeftFloor);
                    int    srcLeftInt    = (int)srcLeftFloor;

                    double srcRight       = (double)((dstX + 1) * srcWidth) / (double)width;
                    double srcRightFloor  = Math.Floor(srcRight - 0.00001);
                    double srcRightWeight = srcRight - srcRightFloor;
                    int    srcRightInt    = (int)srcRightFloor;

                    double graySum  = 0;
                    double alphaSum = 0;

                    // left fractional edge
                    ushort *srcLeftPtr = (ushort *)source.GetPointAddressUnchecked(srcLeftInt, srcTopInt + 1);

                    for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY)
                    {
                        const double a = 255.0;
                        graySum   += srcLeftPtr[0] * srcLeftWeight * a;
                        alphaSum  += a * srcLeftWeight;
                        srcLeftPtr = (ushort *)(srcLeftPtr + srcStride);
                    }

                    // right fractional edge
                    ushort *srcRightPtr = (ushort *)source.GetPointAddressUnchecked(srcRightInt, srcTopInt + 1);
                    for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY)
                    {
                        const double a = 255.0;
                        graySum    += srcRightPtr[0] * srcRightWeight * a;
                        alphaSum   += a * srcRightWeight;
                        srcRightPtr = (ushort *)(srcRightPtr + srcStride);
                    }

                    // top fractional edge
                    ushort *srcTopPtr = (ushort *)source.GetPointAddressUnchecked(srcLeftInt + 1, srcTopInt);
                    for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX)
                    {
                        const double a = 255.0;
                        graySum  += srcTopPtr[0] * srcTopWeight * a;
                        alphaSum += a * srcTopWeight;
                        ++srcTopPtr;
                    }

                    // bottom fractional edge
                    ushort *srcBottomPtr = (ushort *)source.GetPointAddressUnchecked(srcLeftInt + 1, srcBottomInt);
                    for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX)
                    {
                        const double a = 255.0;
                        graySum  += srcBottomPtr[0] * srcBottomWeight * a;
                        alphaSum += 255.0 * srcBottomWeight;
                        ++srcBottomPtr;
                    }

                    // center area
                    for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY)
                    {
                        ushort *srcPtr = (ushort *)source.GetPointAddressUnchecked(srcLeftInt + 1, srcY);

                        for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX)
                        {
                            graySum  += (double)srcPtr[0] * 255.0;
                            alphaSum += 255.0;
                            ++srcPtr;
                        }
                    }

                    // four corner pixels
                    ushort       srcTL  = *(ushort *)source.GetPointAddress(srcLeftInt, srcTopInt);
                    const double srcTLA = 255.0;
                    graySum  += srcTL * (srcTopWeight * srcLeftWeight) * srcTLA;
                    alphaSum += srcTLA * (srcTopWeight * srcLeftWeight);

                    ushort       srcTR  = *(ushort *)source.GetPointAddress(srcRightInt, srcTopInt);
                    const double srcTRA = 255.0;
                    graySum  += srcTR * (srcTopWeight * srcRightWeight) * srcTRA;
                    alphaSum += srcTRA * (srcTopWeight * srcRightWeight);

                    ushort       srcBL  = *(ushort *)source.GetPointAddress(srcLeftInt, srcBottomInt);
                    const double srcBLA = 255.0;
                    graySum  += srcBL * (srcBottomWeight * srcLeftWeight) * srcBLA;
                    alphaSum += srcBLA * (srcBottomWeight * srcLeftWeight);

                    ushort       srcBR  = *(ushort *)source.GetPointAddress(srcRightInt, srcBottomInt);
                    const double srcBRA = 255.0;
                    graySum  += srcBR * (srcBottomWeight * srcRightWeight) * srcBRA;
                    alphaSum += srcBRA * (srcBottomWeight * srcRightWeight);

                    double area = (srcRight - srcLeft) * (srcBottom - srcTop);

                    double alpha = alphaSum / area;
                    double gray;

                    if (alpha == 0)
                    {
                        gray = 0;
                    }
                    else
                    {
                        gray = graySum / alphaSum;
                    }

                    // add 0.5 so that rounding goes in the direction we want it to
                    gray += 0.5;

                    dstPtr[0] = (ushort)gray;
                    ++dstPtr;
                }
            }
        }
Ejemplo n.º 2
0
        public override unsafe void SuperSampleFitSurface(SurfaceBase source)
        {
            Rectangle dstRoi2   = Rectangle.Intersect(source.Bounds, Bounds);
            int       srcHeight = source.Height;
            int       srcWidth  = source.Width;
            long      srcStride = source.Stride;

            int height = this.height;
            int width  = this.width;

            for (int dstY = dstRoi2.Top; dstY < dstRoi2.Bottom; ++dstY)
            {
                double srcTop       = (double)(dstY * srcHeight) / (double)height;
                double srcTopFloor  = Math.Floor(srcTop);
                double srcTopWeight = 1 - (srcTop - srcTopFloor);
                int    srcTopInt    = (int)srcTopFloor;

                double srcBottom       = (double)((dstY + 1) * srcHeight) / (double)height;
                double srcBottomFloor  = Math.Floor(srcBottom - 0.00001);
                double srcBottomWeight = srcBottom - srcBottomFloor;
                int    srcBottomInt    = (int)srcBottomFloor;

                ColorBgra16 *dstPtr = (ColorBgra16 *)GetPointAddressUnchecked(dstRoi2.Left, dstY);

                for (int dstX = dstRoi2.Left; dstX < dstRoi2.Right; ++dstX)
                {
                    double srcLeft       = (double)(dstX * srcWidth) / (double)width;
                    double srcLeftFloor  = Math.Floor(srcLeft);
                    double srcLeftWeight = 1 - (srcLeft - srcLeftFloor);
                    int    srcLeftInt    = (int)srcLeftFloor;

                    double srcRight       = (double)((dstX + 1) * srcWidth) / (double)width;
                    double srcRightFloor  = Math.Floor(srcRight - 0.00001);
                    double srcRightWeight = srcRight - srcRightFloor;
                    int    srcRightInt    = (int)srcRightFloor;

                    double blueSum  = 0;
                    double greenSum = 0;
                    double redSum   = 0;
                    double alphaSum = 0;

                    // left fractional edge
                    ColorBgra16 *srcLeftPtr = (ColorBgra16 *)source.GetPointAddressUnchecked(srcLeftInt, srcTopInt + 1);

                    for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY)
                    {
                        double a = srcLeftPtr->A;
                        blueSum   += srcLeftPtr->B * srcLeftWeight * a;
                        greenSum  += srcLeftPtr->G * srcLeftWeight * a;
                        redSum    += srcLeftPtr->R * srcLeftWeight * a;
                        alphaSum  += srcLeftPtr->A * srcLeftWeight;
                        srcLeftPtr = (ColorBgra16 *)((byte *)srcLeftPtr + srcStride);
                    }

                    // right fractional edge
                    ColorBgra16 *srcRightPtr = (ColorBgra16 *)source.GetPointAddressUnchecked(srcRightInt, srcTopInt + 1);
                    for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY)
                    {
                        double a = srcRightPtr->A;
                        blueSum    += srcRightPtr->B * srcRightWeight * a;
                        greenSum   += srcRightPtr->G * srcRightWeight * a;
                        redSum     += srcRightPtr->R * srcRightWeight * a;
                        alphaSum   += srcRightPtr->A * srcRightWeight;
                        srcRightPtr = (ColorBgra16 *)((byte *)srcRightPtr + srcStride);
                    }

                    // top fractional edge
                    ColorBgra16 *srcTopPtr = (ColorBgra16 *)source.GetPointAddressUnchecked(srcLeftInt + 1, srcTopInt);
                    for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX)
                    {
                        double a = srcTopPtr->A;
                        blueSum  += srcTopPtr->B * srcTopWeight * a;
                        greenSum += srcTopPtr->G * srcTopWeight * a;
                        redSum   += srcTopPtr->R * srcTopWeight * a;
                        alphaSum += srcTopPtr->A * srcTopWeight;
                        ++srcTopPtr;
                    }

                    // bottom fractional edge
                    ColorBgra16 *srcBottomPtr = (ColorBgra16 *)source.GetPointAddressUnchecked(srcLeftInt + 1, srcBottomInt);
                    for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX)
                    {
                        double a = srcBottomPtr->A;
                        blueSum  += srcBottomPtr->B * srcBottomWeight * a;
                        greenSum += srcBottomPtr->G * srcBottomWeight * a;
                        redSum   += srcBottomPtr->R * srcBottomWeight * a;
                        alphaSum += srcBottomPtr->A * srcBottomWeight;
                        ++srcBottomPtr;
                    }

                    // center area
                    for (int srcY = srcTopInt + 1; srcY < srcBottomInt; ++srcY)
                    {
                        ColorBgra16 *srcPtr = (ColorBgra16 *)source.GetPointAddressUnchecked(srcLeftInt + 1, srcY);

                        for (int srcX = srcLeftInt + 1; srcX < srcRightInt; ++srcX)
                        {
                            double a = srcPtr->A;
                            blueSum  += (double)srcPtr->B * a;
                            greenSum += (double)srcPtr->G * a;
                            redSum   += (double)srcPtr->R * a;
                            alphaSum += (double)srcPtr->A;
                            ++srcPtr;
                        }
                    }

                    // four corner pixels
                    ColorBgra16 srcTL  = *(ColorBgra16 *)source.GetPointAddress(srcLeftInt, srcTopInt);
                    double      srcTLA = srcTL.A;
                    blueSum  += srcTL.B * (srcTopWeight * srcLeftWeight) * srcTLA;
                    greenSum += srcTL.G * (srcTopWeight * srcLeftWeight) * srcTLA;
                    redSum   += srcTL.R * (srcTopWeight * srcLeftWeight) * srcTLA;
                    alphaSum += srcTL.A * (srcTopWeight * srcLeftWeight);

                    ColorBgra16 srcTR  = *(ColorBgra16 *)source.GetPointAddress(srcRightInt, srcTopInt);
                    double      srcTRA = srcTR.A;
                    blueSum  += srcTR.B * (srcTopWeight * srcRightWeight) * srcTRA;
                    greenSum += srcTR.G * (srcTopWeight * srcRightWeight) * srcTRA;
                    redSum   += srcTR.R * (srcTopWeight * srcRightWeight) * srcTRA;
                    alphaSum += srcTR.A * (srcTopWeight * srcRightWeight);

                    ColorBgra16 srcBL  = *(ColorBgra16 *)source.GetPointAddress(srcLeftInt, srcBottomInt);
                    double      srcBLA = srcBL.A;
                    blueSum  += srcBL.B * (srcBottomWeight * srcLeftWeight) * srcBLA;
                    greenSum += srcBL.G * (srcBottomWeight * srcLeftWeight) * srcBLA;
                    redSum   += srcBL.R * (srcBottomWeight * srcLeftWeight) * srcBLA;
                    alphaSum += srcBL.A * (srcBottomWeight * srcLeftWeight);

                    ColorBgra16 srcBR  = *(ColorBgra16 *)source.GetPointAddress(srcRightInt, srcBottomInt);
                    double      srcBRA = srcBR.A;
                    blueSum  += srcBR.B * (srcBottomWeight * srcRightWeight) * srcBRA;
                    greenSum += srcBR.G * (srcBottomWeight * srcRightWeight) * srcBRA;
                    redSum   += srcBR.R * (srcBottomWeight * srcRightWeight) * srcBRA;
                    alphaSum += srcBR.A * (srcBottomWeight * srcRightWeight);

                    double area = (srcRight - srcLeft) * (srcBottom - srcTop);

                    double alpha = alphaSum / area;
                    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 so that rounding goes in the direction we want it to
                    blue  += 0.5;
                    green += 0.5;
                    red   += 0.5;
                    alpha += 0.5;

                    dstPtr->Bgra = (ulong)blue + ((ulong)green << 16) + ((ulong)red << 32) + ((ulong)alpha << 48);
                    ++dstPtr;
                }
            }
        }