/// <summary> /// Compresses an image /// </summary> /// <param name="inputSurface">Source byte array containing RGBA pixel data</param> /// <param name="squishFlags">Flags for squish compression control</param> /// <param name="progressFn">Array of bytes containing compressed blocks</param> /// <returns>Byte array of compressed image data.</returns> internal static byte[] CompressImage(Bitmap Image, int Flags, ProgressFn Progress) { // We need the input to be in a byte array for squish.. so create one. byte[] pixelData = new byte[Image.Width * Image.Height * 4]; //Rectangle rect = new Rectangle(0, 0, Image.Width, Image.Height); //BitmapData bmpData = Image.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); for (int y = 0; y < Image.Height; y++) { for (int x = 0; x < Image.Width; x++) { int pixelOffset = (y * Image.Width * 4) + (x * 4); pixelData[pixelOffset + 0] = Image.GetPixel(x, y).R; pixelData[pixelOffset + 1] = Image.GetPixel(x, y).G; pixelData[pixelOffset + 2] = Image.GetPixel(x, y).B; pixelData[pixelOffset + 3] = Image.GetPixel(x, y).A; } } // Compute size of compressed block area, and allocate int blockCount = ((Image.Width + 3) / 4) * ((Image.Height + 3) / 4); int blockSize = ((Flags & (int)SquishFlags.Dxt1) != 0) ? 8 : 16; // Allocate room for compressed blocks byte[] blockData = new byte[blockCount * blockSize]; // Invoke squish::CompressImage() with the required parameters CallCompressImage(pixelData, Image.Width, Image.Height, blockData, Flags); // Return our block data to caller.. return(blockData); }
// --------------------------------------------------------------------------------------- // 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); }
internal static byte[] CompressImage(Surface inputSurface, int squishFlags, ProgressFn progressFn) { byte[] rgba = new byte[(inputSurface.Width * inputSurface.Height) * 4]; for (int i = 0; i < inputSurface.Height; i++) { for (int j = 0; j < inputSurface.Width; j++) { ColorBgra point = inputSurface.GetPoint(j, i); int index = ((i * inputSurface.Width) * 4) + (j * 4); rgba[index] = point.R; rgba[index + 1] = point.G; rgba[index + 2] = point.B; rgba[index + 3] = point.A; } } int num = ((inputSurface.Width + 3) / 4) * ((inputSurface.Height + 3) / 4); int num2 = ((squishFlags & 1) != 0) ? 8 : 0x10; byte[] blocks = new byte[num * num2]; CallCompressImage(rgba, inputSurface.Width, inputSurface.Height, blocks, squishFlags, progressFn); return(blocks); }
private static unsafe void CallDecompressImage(byte[] rgba, int width, int height, byte[] blocks, int flags, ProgressFn progressFn) { fixed(byte *numRef = rgba) { fixed(byte *numRef2 = blocks) { if (Processor.Architecture == ProcessorArchitecture.X64) { SquishInterfaceX64.SquishDecompressImage(numRef, width, height, numRef2, flags, progressFn); } else { SquishInterfaceX86.SquishDecompressImage(numRef, width, height, numRef2, flags, progressFn); } } } GC.KeepAlive(progressFn); }
// --------------------------------------------------------------------------------------- // 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; }
private static unsafe void CallDecompressImage( byte[] rgba, int width, int height, byte[] blocks, int flags, ProgressFn progressFn ) { fixed ( byte* pRGBA = rgba ) { fixed ( byte* pBlocks = blocks ) { if ( Processor.Architecture == ProcessorArchitecture.X64 ) SquishInterface_64.SquishDecompressImage(pRGBA, width, height, pBlocks, flags, progressFn); else if ( Processor.IsFeaturePresent(ProcessorFeature.SSE2) ) SquishInterface_32_SSE2.SquishDecompressImage( pRGBA, width, height, pBlocks, flags, progressFn ); else SquishInterface_32.SquishDecompressImage( pRGBA, width, height, pBlocks, flags, progressFn ); } } GC.KeepAlive(progressFn); }
internal static extern unsafe void SquishDecompressImage(byte *rgba, int width, int height, byte *blocks, int flags, [MarshalAs(UnmanagedType.FunctionPtr)] ProgressFn progressFn);
private static unsafe void CallDecompressImage(byte[] rgba, int width, int height, byte[] blocks, int flags, ProgressFn progressFn) { fixed(byte *pRGBA = rgba) { fixed(byte *pBlocks = blocks) { if (Processor.Architecture == ProcessorArchitecture.X64) { SquishInterface_64.SquishDecompressImage(pRGBA, width, height, pBlocks, flags, progressFn); } else if (Processor.IsFeaturePresent(ProcessorFeature.SSE2)) { SquishInterface_32_SSE2.SquishDecompressImage(pRGBA, width, height, pBlocks, flags, progressFn); } else { SquishInterface_32.SquishDecompressImage(pRGBA, width, height, pBlocks, flags, progressFn); } } } GC.KeepAlive(progressFn); }