private static BaseBitmap ConvertGen3Bitmap(byte[] primaryData, byte[] secondaryData, BitmapTextureInteropDefinition definition, Bitmap bitmap, int imageIndex, bool isPaired, int pairIndex, BitmapTextureInteropDefinition otherDefinition, bool forDDS) { if (primaryData == null && secondaryData == null) { return(null); } using (var result = new MemoryStream()) { int mipLevelCount = definition.MipmapCount; int layerCount = definition.BitmapType == BitmapType.CubeMap ? 6 : definition.Depth; if (definition.BitmapType == BitmapType.Array && mipLevelCount > 1) { mipLevelCount = 1; definition.MipmapCount = 1; } if (!forDDS) { // order for d3d9, all faces first, then mipmaps for (int mipLevel = 0; mipLevel < mipLevelCount; mipLevel++) { for (int layerIndex = 0; layerIndex < layerCount; layerIndex++) { if (definition.BitmapType == BitmapType.CubeMap) // swap cubemap faces { if (layerIndex == 2) { layerIndex = 3; } else if (layerIndex == 3) { layerIndex = 2; } } ConvertGen3BitmapData(result, primaryData, secondaryData, definition, bitmap, imageIndex, mipLevel, layerIndex, isPaired, pairIndex, otherDefinition); if (definition.BitmapType == BitmapType.CubeMap) { if (layerIndex == 3) { layerIndex = 2; } else if (layerIndex == 2) { layerIndex = 3; } } } } } else { for (int layerIndex = 0; layerIndex < layerCount; layerIndex++) { if (definition.BitmapType == BitmapType.CubeMap) // swap cubemap faces { if (layerIndex == 2) { layerIndex = 3; } else if (layerIndex == 3) { layerIndex = 2; } } for (int mipLevel = 0; mipLevel < mipLevelCount; mipLevel++) { ConvertGen3BitmapData(result, primaryData, secondaryData, definition, bitmap, imageIndex, mipLevel, layerIndex, isPaired, pairIndex, otherDefinition); } if (definition.BitmapType == BitmapType.CubeMap) { if (layerIndex == 3) { layerIndex = 2; } else if (layerIndex == 2) { layerIndex = 3; } } } } var resultData = result.ToArray(); BaseBitmap resultBitmap = new BaseBitmap(bitmap.Images[imageIndex]); var newFormat = BitmapUtils.GetEquivalentBitmapFormat(bitmap.Images[imageIndex].Format); resultBitmap.UpdateFormat(newFormat); if (BitmapUtils.RequiresDecompression(resultBitmap.Format, (uint)resultBitmap.Width, (uint)resultBitmap.Height)) { resultBitmap.Format = BitmapFormat.A8R8G8B8; } if (!BitmapUtils.IsCompressedFormat(resultBitmap.Format)) { resultBitmap.Flags &= ~BitmapFlags.Compressed; } else { resultBitmap.Flags |= BitmapFlags.Compressed; } // // Update resource definition/image, truncate DXN to level 4x4 // resultBitmap.Data = resultData; if (resultBitmap.Format == BitmapFormat.Dxn) // wouldn't be required if d3d9 supported non power of two DXN and with mips less than 8x8 { GenerateCompressedMipMaps(resultBitmap); } if (resultBitmap.Type == BitmapType.Array) // for HO, arrays use the index of Texture3D { resultBitmap.Type = BitmapType.Texture3D; } return(resultBitmap); } }
private static bool ConvertImage(BaseBitmap bitmap) { BitmapFormat targetFormat = bitmap.Format; var data = bitmap.Data; bool DXTFlip = false; switch (bitmap.Format) { case BitmapFormat.Dxt5aMono: case BitmapFormat.Dxt3aMono: targetFormat = BitmapFormat.Y8; bitmap.Flags &= ~BitmapFlags.Compressed; break; case BitmapFormat.Dxt3aAlpha: case BitmapFormat.Dxt5aAlpha: targetFormat = BitmapFormat.A8; bitmap.Flags &= ~BitmapFlags.Compressed; break; case BitmapFormat.DxnMonoAlpha: case BitmapFormat.Dxt5a: case BitmapFormat.AY8: targetFormat = BitmapFormat.A8Y8;; bitmap.Flags &= ~BitmapFlags.Compressed; break; case BitmapFormat.A4R4G4B4: case BitmapFormat.R5G6B5: targetFormat = BitmapFormat.A8R8G8B8; break; case BitmapFormat.A8Y8: case BitmapFormat.Y8: case BitmapFormat.A8: case BitmapFormat.A8R8G8B8: case BitmapFormat.X8R8G8B8: case BitmapFormat.A16B16G16R16F: case BitmapFormat.A32B32G32R32F: case BitmapFormat.V8U8: break; case BitmapFormat.Dxt1: case BitmapFormat.Dxt3: case BitmapFormat.Dxt5: case BitmapFormat.Dxn: if (bitmap.Height != bitmap.NearestHeight || bitmap.Width != bitmap.NearestWidth) { targetFormat = BitmapFormat.A8R8G8B8; bitmap.Flags &= ~BitmapFlags.Compressed; DXTFlip = true; } break; case BitmapFormat.Ctx1: bitmap.UpdateFormat(BitmapFormat.Dxn); data = BitmapDecoder.Ctx1ToDxn(data, bitmap.NearestWidth, bitmap.NearestHeight); targetFormat = BitmapFormat.Dxn; break; default: throw new Exception($"Unsupported bitmap format {bitmap.Format}"); } if (targetFormat != bitmap.Format) { data = BitmapDecoder.DecodeBitmap(data, bitmap.Format, bitmap.NearestWidth, bitmap.NearestHeight); data = BitmapDecoder.EncodeBitmap(data, targetFormat, bitmap.NearestWidth, bitmap.NearestHeight); bool reformat = false; if (bitmap.NearestHeight != bitmap.Height || bitmap.NearestWidth != bitmap.Width) { reformat = true; } if (reformat) { var compressionFactor = BitmapFormatUtils.GetCompressionFactor(targetFormat); int fixedSize = (int)(bitmap.Width * bitmap.Height / compressionFactor); int tilePitch = (int)(bitmap.NearestWidth / compressionFactor); int pitch = (int)(bitmap.Width / compressionFactor); byte[] fixedData = new byte[fixedSize]; int numberOfPass = bitmap.Height; // encode does not give back block compressed data. for (int i = 0; i < numberOfPass; i++) // may need to compute an offset for special bitmaps { Array.Copy(data, i * tilePitch, fixedData, i * pitch, pitch); } data = fixedData; } bitmap.UpdateFormat(targetFormat); bitmap.Data = data; } bitmap.Data = data; if (DXTFlip) { return(false); } return(true); }