示例#1
0
		// ---------------------------------------------------------------------------------------
		//	CompressImage
		// ---------------------------------------------------------------------------------------
		//
		//	Params
		//		inputSurface	:	Source byte array containing RGBA pixel data
		//		flags			:	Flags for squish compression control
		//
		//	Return	
		//		blockData		:	Array of bytes containing compressed blocks
		//
		// ---------------------------------------------------------------------------------------

		internal static byte[] CompressImage( Surface inputSurface, int squishFlags, ProgressFn progressFn )
		{
			// We need the input to be in a byte array for squish.. so create one.
			byte[]	pixelData	= new byte[ inputSurface.Width * inputSurface.Height * 4 ];

			for ( int y = 0; y < inputSurface.Height; y++ )
			{
				for ( int x = 0; x < inputSurface.Width; x++ )
				{
					ColorBgra	pixelColour = inputSurface.GetPoint( x, y );
					int			pixelOffset	= ( y * inputSurface.Width * 4 ) + ( x * 4 );
						
					pixelData[ pixelOffset + 0 ]	= pixelColour.R;
					pixelData[ pixelOffset + 1 ]	= pixelColour.G;
					pixelData[ pixelOffset + 2 ]	= pixelColour.B;
					pixelData[ pixelOffset + 3 ]	= pixelColour.A;
				}
			}

			// Compute size of compressed block area, and allocate 
			int blockCount = ( ( inputSurface.Width + 3 )/4 ) * ( ( inputSurface.Height + 3 )/4 );
			int blockSize = ( ( squishFlags & ( int )DdsSquish.SquishFlags.kDxt1 ) != 0 ) ? 8 : 16;

			// Allocate room for compressed blocks
			byte[]	blockData		= new byte[ blockCount * blockSize ];
	
			// Invoke squish::CompressImage() with the required parameters
			CallCompressImage( pixelData, inputSurface.Width, inputSurface.Height, blockData, squishFlags, progressFn );
				
			// Return our block data to caller..
			return	blockData;	
		}
示例#2
0
        public unsafe void SuperSampleFitSurface(Surface source)
        {
            Rectangle dstRoi2 = Rectangle.Intersect(source.Bounds, this.Bounds);

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

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

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

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

                    double srcRight       = (double)((dstX + 1) * source.width) / (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
                    ColorBgra *srcLeftPtr = 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 = (ColorBgra *)((byte *)srcLeftPtr + source.stride);
                    }

                    // right fractional edge
                    ColorBgra *srcRightPtr = 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 = (ColorBgra *)((byte *)srcRightPtr + source.stride);
                    }

                    // top fractional edge
                    ColorBgra *srcTopPtr = 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
                    ColorBgra *srcBottomPtr = 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)
                    {
                        ColorBgra *srcPtr = 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
                    ColorBgra srcTL  = source.GetPoint(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);

                    ColorBgra srcTR  = source.GetPoint(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);

                    ColorBgra srcBL  = source.GetPoint(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);

                    ColorBgra srcBR  = source.GetPoint(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 = (uint)blue + ((uint)green << 8) + ((uint)red << 16) + ((uint)alpha << 24);
                    ++dstPtr;
                }
            }
        }
示例#3
0
        /// <summary>
        /// Fits the source surface to this surface using super sampling. If the source surface is less wide
        /// or less tall than this surface (i.e. magnification), bicubic resampling is used instead. If either
        /// the source or destination has a dimension that is only 1 pixel, nearest neighbor is used.
        /// </summary>
        /// <param name="source">The surface to read pixels from.</param>
        /// <param name="dstRoi">The rectangle to clip rendering to.</param>
        /// <remarks>This method was implemented with correctness, not performance, in mind.</remarks>
        public void SuperSamplingFitSurface(Surface source, Rectangle dstRoi)
        {
            if (source.Width == Width && source.Height == Height)
            {
                CopySurface(source);
            }
            else if (source.Width <= Width || source.Height <= Height)
            {
                if (source.width < 2 || source.height < 2 || this.width < 2 || this.height < 2)
                {
                    this.NearestNeighborFitSurface(source, dstRoi);
                }
                else
                {
                    this.BicubicFitSurface(source, dstRoi);
                }
            }
            else unsafe
            {
                Rectangle dstRoi2 = Rectangle.Intersect(dstRoi, this.Bounds);

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

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

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

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

                        double srcRight = (double)((dstX + 1) * source.width) / (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
                        ColorBgra *srcLeftPtr = 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 = (ColorBgra*)((byte*)srcLeftPtr + source.stride);
                        }

                        // right fractional edge
                        ColorBgra *srcRightPtr = 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 = (ColorBgra*)((byte*)srcRightPtr + source.stride);
                        }

                        // top fractional edge
                        ColorBgra *srcTopPtr = 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
                        ColorBgra *srcBottomPtr = 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)
                        {
                            ColorBgra *srcPtr = 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
                        ColorBgra srcTL = source.GetPoint(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);

                        ColorBgra srcTR = source.GetPoint(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);

                        ColorBgra srcBL = source.GetPoint(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);

                        ColorBgra srcBR = source.GetPoint(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 = (uint)blue + ((uint)green << 8) + ((uint)red << 16) + ((uint)alpha << 24);
                        ++dstPtr;
                    }
                }
            }
        }