protected void CompressMip(DXT1Mip mip, byte[] buffer) { Debug.Assert(buffer.Length == (mip.Width * mip.Height * srcPixelSize)); byte[] block = new byte[64]; int blocksWidth = mip.Width / 4; int blocksHeight = mip.Height / 4; int stride = mip.Width * srcPixelSize; int copyLen = 4 * srcPixelSize; int dxtOffset = 0; for (int y = 0; y < mip.Height; y += 4) { int lineOffset = y * stride; for (int x = 0; x < mip.Width; x += 4) { int offset = lineOffset + x * srcPixelSize; int destOffset = 0; // fill the block with data from the source image for (int line = 0; line < 4; line++) { Buffer.BlockCopy(buffer, offset, block, destOffset, copyLen); offset += stride; destOffset += copyLen; } CompressBlockDXT1Opaque(block, mip.Buffer, dxtOffset); dxtOffset += 8; } } }
public DXT1Image(Image source) { // make sure width and height are divisible by 4 Debug.Assert((source.Width & 0x3) == 0); Debug.Assert((source.Height & 0x3) == 0); // width and height are powers of 2 Debug.Assert(isPowerOf2(source.Width)); Debug.Assert(isPowerOf2(source.Height)); // only support RGB 24-bit images for now //Debug.Assert(source.Format == PixelFormat.R8G8B8); // only normal textures Debug.Assert(source.NumFaces == 1); Debug.Assert(source.NumMipMaps == 1); width = source.Width; height = source.Height; int mipWidth = width; int mipHeight = height; int mipLevels; if (width > height) { mipLevels = log2(width) - 1; } else { mipLevels = log2(height) - 1; } compressedMips = new DXT1Mip[mipLevels]; // start by using the source image data for the first iterations. // later iterations will use new allocated buffers containing scaled pixels byte[] rawBuffer = source.Data; for( int mipLevel = 0; mipLevel < mipLevels; mipLevel++) { compressedMips[mipLevel] = new DXT1Mip(mipWidth, mipHeight); //CompressMip(compressedMips[mipLevel], rawBuffer); unsafe { byte [] outBuffer = compressedMips[mipLevel].Buffer; GCHandle inHandle = GCHandle.Alloc(rawBuffer, GCHandleType.Pinned); GCHandle outHandle = GCHandle.Alloc(outBuffer, GCHandleType.Pinned); IntPtr pIn = inHandle.AddrOfPinnedObject(); IntPtr pOut = outHandle.AddrOfPinnedObject(); CompressImageDXT1(pIn, pOut, mipWidth, mipHeight); inHandle.Free(); outHandle.Free(); } mipWidth = mipWidth / 2; mipHeight = mipHeight / 2; // create a new uncompressed buffer by scaling the last buffer // to the new mip size rawBuffer = scaleRawHalfBox(mipWidth, mipHeight, rawBuffer); } }
public DXT1Image(Image source) { // make sure width and height are divisible by 4 Debug.Assert((source.Width & 0x3) == 0); Debug.Assert((source.Height & 0x3) == 0); // width and height are powers of 2 Debug.Assert(isPowerOf2(source.Width)); Debug.Assert(isPowerOf2(source.Height)); // only support RGB 24-bit images for now //Debug.Assert(source.Format == PixelFormat.R8G8B8); // only normal textures Debug.Assert(source.NumFaces == 1); Debug.Assert(source.NumMipMaps == 1); width = source.Width; height = source.Height; int mipWidth = width; int mipHeight = height; int mipLevels; if (width > height) { mipLevels = log2(width) - 1; } else { mipLevels = log2(height) - 1; } compressedMips = new DXT1Mip[mipLevels]; // start by using the source image data for the first iterations. // later iterations will use new allocated buffers containing scaled pixels byte[] rawBuffer = source.Data; for (int mipLevel = 0; mipLevel < mipLevels; mipLevel++) { compressedMips[mipLevel] = new DXT1Mip(mipWidth, mipHeight); //CompressMip(compressedMips[mipLevel], rawBuffer); unsafe { byte [] outBuffer = compressedMips[mipLevel].Buffer; GCHandle inHandle = GCHandle.Alloc(rawBuffer, GCHandleType.Pinned); GCHandle outHandle = GCHandle.Alloc(outBuffer, GCHandleType.Pinned); IntPtr pIn = inHandle.AddrOfPinnedObject(); IntPtr pOut = outHandle.AddrOfPinnedObject(); CompressImageDXT1(pIn, pOut, mipWidth, mipHeight); inHandle.Free(); outHandle.Free(); } mipWidth = mipWidth / 2; mipHeight = mipHeight / 2; // create a new uncompressed buffer by scaling the last buffer // to the new mip size rawBuffer = scaleRawHalfBox(mipWidth, mipHeight, rawBuffer); } }