public static byte[] ConvertXboxFormats(byte[] data, uint width, uint height, BitmapFormat format, bool requireDecompression) { BitmapFormat destinationFormat = GetEquivalentBitmapFormat(format); if (format == BitmapFormat.Dxn) { // flip x and y channels data = BitmapDecoder.SwapXYDxn(data, (int)width, (int)height); } if (destinationFormat == format && !requireDecompression) { return(data); } if (format == BitmapFormat.Ctx1) { data = BitmapDecoder.Ctx1ToDxn(data, (int)width, (int)height); format = BitmapFormat.Dxn; } else if (format != destinationFormat) { byte[] uncompressedData = BitmapDecoder.DecodeBitmap(data, format, (int)width, (int)height); uncompressedData = TrimAlignedBitmap(format, destinationFormat, (int)width, (int)height, uncompressedData); data = BitmapDecoder.EncodeBitmap(uncompressedData, destinationFormat, (int)width, (int)height); format = destinationFormat; } if (requireDecompression) { data = ConvertNonMultipleBlockSizeBitmap(data, width, height, format); } return(data); }
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); }