static void BitmapAssert(BitmapContent bitmap, Color color, int range) { byte[] rgba; if (bitmap is Dxt1BitmapContent) { rgba = DxtUtil.DecompressDxt1(bitmap.GetPixelData(), bitmap.Width, bitmap.Height); } else if (bitmap is Dxt3BitmapContent) { rgba = DxtUtil.DecompressDxt3(bitmap.GetPixelData(), bitmap.Width, bitmap.Height); } else if (bitmap is Dxt5BitmapContent) { rgba = DxtUtil.DecompressDxt5(bitmap.GetPixelData(), bitmap.Width, bitmap.Height); } else { rgba = bitmap.GetPixelData(); } for (var p = 0; p < rgba.Length; p += 4) { Assert.That(rgba[p + 0], Is.EqualTo(color.R).Within(range)); Assert.That(rgba[p + 1], Is.EqualTo(color.G).Within(range)); Assert.That(rgba[p + 2], Is.EqualTo(color.B).Within(range)); Assert.That(rgba[p + 3], Is.EqualTo(color.A).Within(range)); } }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat = (SurfaceFormat)reader.ReadInt32(); int width = reader.ReadInt32(); int height = reader.ReadInt32(); int levelCount = reader.ReadInt32(); int imageLength = reader.ReadInt32(); byte[] imageData = reader.ReadBytes(imageLength); switch (surfaceFormat) { case SurfaceFormat.Dxt1: imageData = DxtUtil.DecompressDxt1(imageData, width, height); break; case SurfaceFormat.Dxt3: imageData = DxtUtil.DecompressDxt3(imageData, width, height); break; } IntPtr imagePtr = IntPtr.Zero; // Changed to load the raw data // currentony only ARGB8888 is supported ESTexture2D esTexture = new ESTexture2D(imageData, surfaceFormat, width, height, new Size(width, height), All.Linear); texture = new Texture2D(reader.GraphicsDevice, new ESImage(esTexture)); return(texture); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat = (SurfaceFormat)reader.ReadInt32(); int width = reader.ReadInt32(); int height = reader.ReadInt32(); int levelCount = reader.ReadInt32(); int imageLength = reader.ReadInt32(); byte[] imageData = reader.ReadBytes(imageLength); switch (surfaceFormat) { case SurfaceFormat.Dxt1: imageData = DxtUtil.DecompressDxt1(imageData, width, height); break; case SurfaceFormat.Dxt3: imageData = DxtUtil.DecompressDxt3(imageData, width, height); break; } IntPtr imagePtr = IntPtr.Zero; try { imagePtr = Marshal.AllocHGlobal(imageData.Length); Marshal.Copy(imageData, 0, imagePtr, imageData.Length); ESTexture2D esTexture = new ESTexture2D(imagePtr, surfaceFormat, width, height, new Size(width, height), All.Linear); texture = new Texture2D(new ESImage(esTexture)); } finally { Marshal.FreeHGlobal(imagePtr); } return(texture); }
public byte[] DecompressData() { if (Format == SurfaceFormat.Alpha8) { return(Alpha8ToRgba(Data)); } else if (Format == SurfaceFormat.Color) { return(Data); } else if (Format == SurfaceFormat.Dxt5) { return(DxtUtil.DecompressDxt5(Data, Width, Height)); } else if (Format == (SurfaceFormat)28) { return(DetexCS.DetexCS.DecodeBc7(Data, Width, Height)); } else if (Format == (SurfaceFormat)27) { return(LumAlpha8ToRgba(Data)); } else { throw new PsigaShimUnsupported(); } }
/// <summary> /// Exports RenderSurface to a image file /// </summary> public void ExportTexture(string directory) { string ext = ".png"; ImageFormat exportFormat = ImageFormat.Png; if (Length > 0) { switch (Format) { case SurfacePixelFormat.PFID_CUSTOM_RAW_JPEG: { ext = ".jpg"; string filename = Path.Combine(directory, Id.ToString("X8") + ext); using (BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Create))) { writer.Write(SourceData); } } break; case SurfacePixelFormat.PFID_DXT1: { byte[] bitmapData = DxtUtil.DecompressDxt1(SourceData, Width, Height); Bitmap bitmapImage = GetBitmap(bitmapData); string filename = Path.Combine(directory, Id.ToString("X8") + ext); bitmapImage.Save(filename, exportFormat); } break; case SurfacePixelFormat.PFID_DXT3: { byte[] bitmapData = DxtUtil.DecompressDxt3(SourceData, Width, Height); Bitmap bitmapImage = GetBitmap(bitmapData); string filename = Path.Combine(directory, Id.ToString("X8") + ext); bitmapImage.Save(filename, exportFormat); } break; case SurfacePixelFormat.PFID_DXT5: { byte[] bitmapData = DxtUtil.DecompressDxt5(SourceData, Width, Height); Bitmap bitmapImage = GetBitmap(bitmapData); string filename = Path.Combine(directory, Id.ToString("X8") + ext); bitmapImage.Save(filename, exportFormat); } break; default: { List <int> colors = GetImageColorArray(); Bitmap bitmapImage = GetBitmap(colors); string filename = Path.Combine(directory, Id.ToString("X8") + ext); bitmapImage.Save(filename, exportFormat); } break; } } }
public void TestDxt5Compress() { var resPath = Path.Combine(Environment.CurrentDirectory, @"..\..\Res"); var rawPng = Path.Combine(resPath, "D愛子a_春服-pure", "0.png"); Bitmap bitmap = new Bitmap(rawPng); var bc3Bytes = DxtUtil.Dxt5Encode(bitmap); RL.ConvertToImageFile(bc3Bytes, rawPng + "-convert.png", 4096, 4096, PsbImageFormat.Png, PsbPixelFormat.DXT5); }
/// <summary> /// Gets the raw pixel data for the texture /// </summary> /// <param name="xivTex">The texture data</param> /// <returns>A byte array with the image data</returns> public Task <byte[]> GetImageData(XivTex xivTex) { return(Task.Run(async() => { byte[] imageData = null; switch (xivTex.TextureFormat) { case XivTexFormat.DXT1: imageData = DxtUtil.DecompressDxt1(xivTex.TexData, xivTex.Width, xivTex.Height); break; case XivTexFormat.DXT3: imageData = DxtUtil.DecompressDxt3(xivTex.TexData, xivTex.Width, xivTex.Height); break; case XivTexFormat.DXT5: imageData = DxtUtil.DecompressDxt5(xivTex.TexData, xivTex.Width, xivTex.Height); break; case XivTexFormat.A4R4G4B4: imageData = await Read4444Image(xivTex.TexData, xivTex.Width, xivTex.Height); break; case XivTexFormat.A1R5G5B5: imageData = await Read5551Image(xivTex.TexData, xivTex.Width, xivTex.Height); break; case XivTexFormat.A8R8G8B8: imageData = await SwapRBColors(xivTex.TexData, xivTex.Width, xivTex.Height); break; case XivTexFormat.L8: case XivTexFormat.A8: imageData = await Read8bitImage(xivTex.TexData, xivTex.Width, xivTex.Height); break; case XivTexFormat.X8R8G8B8: case XivTexFormat.R32F: case XivTexFormat.G16R16F: case XivTexFormat.G32R32F: case XivTexFormat.A16B16G16R16F: case XivTexFormat.A32B32G32R32F: case XivTexFormat.D16: default: imageData = xivTex.TexData; break; } return imageData; })); }
/// <summary> /// Creates a bitmap from the texture data. /// </summary> /// <param name="decompressedData">The decompressed data of the texture.</param> /// <param name="textureType">The textures type.</param> /// <param name="width">The textures width.</param> /// <param name="height">The textures height.</param> /// <returns>The created bitmap.</returns> //public static Bitmap TextureToBitmap(byte[] decompressedData, int textureType, int width, int height) public static void TextureToBitmap(byte[] decompressedData, TEXData texData) { BitmapSource bmpSource; var width = texData.Width; var height = texData.Height; Tuple <BitmapSource, BitmapSource> bmps = null; byte[] decompressedTextureData; switch (texData.Type) { case TextureTypes.DXT1: decompressedTextureData = DxtUtil.DecompressDxt1(decompressedData, width, height); bmps = Read32bitBitmapImageAlphaDXT(decompressedTextureData, width, height); break; case TextureTypes.DXT3: decompressedTextureData = DxtUtil.DecompressDxt3(decompressedData, width, height); bmps = Read32bitBitmapImageAlphaDXT(decompressedTextureData, width, height); break; case TextureTypes.DXT5: decompressedTextureData = DxtUtil.DecompressDxt5(decompressedData, width, height); bmps = Read32bitBitmapImageAlphaDXT(decompressedTextureData, width, height); break; case TextureTypes.A8: case TextureTypes.L8: bmpSource = Read8bitBitmapImage(decompressedData, width, height); bmps = new Tuple <BitmapSource, BitmapSource>(bmpSource, bmpSource); break; case TextureTypes.A4R4G4B4: bmps = Read4444BMPSource(decompressedData, width, height); break; case TextureTypes.A1R5G5B5: bmps = Read5551BMPSource(decompressedData, width, height); break; case TextureTypes.A8R8G8B8: case TextureTypes.X8R8G8B8: bmps = Read32bitBitmapImageAlpha(decompressedData, width, height); break; //case TextureTypes.A16B16G16R16F: // bmp = ReadRGBAFImage(decompressedData, width, height); // break; } texData.BMPSouceAlpha = bmps.Item1; texData.BMPSouceNoAlpha = bmps.Item2; }
/// <summary> /// Creates a bitmap from the texture data. /// </summary> /// <param name="decompressedData">The decompressed data of the texture.</param> /// <param name="textureType">The textures type.</param> /// <param name="width">The textures width.</param> /// <param name="height">The textures height.</param> /// <returns>The created bitmap.</returns> public static Bitmap TextureToBitmap(byte[] decompressedData, int textureType, int width, int height) { Bitmap bmp = null; byte[] decompressedTextureData; switch (textureType) { case TextureTypes.DXT1: decompressedTextureData = DxtUtil.DecompressDxt1(decompressedData, width, height); bmp = ReadLinearImage(decompressedTextureData, width, height); break; case TextureTypes.DXT3: decompressedTextureData = DxtUtil.DecompressDxt3(decompressedData, width, height); bmp = ReadLinearImage(decompressedTextureData, width, height); break; case TextureTypes.DXT5: decompressedTextureData = DxtUtil.DecompressDxt5(decompressedData, width, height); bmp = ReadLinearImage(decompressedTextureData, width, height); break; case TextureTypes.A8: case TextureTypes.L8: bmp = Read8bitImage(decompressedData, width, height); break; case TextureTypes.A4R4G4B4: bmp = Read4444Image(decompressedData, width, height); break; case TextureTypes.A1R5G5B5: bmp = Read5551Image(decompressedData, width, height); //bmp = new Bitmap(width, height, width * 2, System.Drawing.Imaging.PixelFormat.Format16bppArgb1555, Marshal.UnsafeAddrOfPinnedArrayElement(decompressedData, 0)); break; case TextureTypes.A8R8G8B8: case TextureTypes.X8R8G8B8: var u = Marshal.UnsafeAddrOfPinnedArrayElement(decompressedData, 0); bmp = new Bitmap(width, height, width * 4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, u); break; case TextureTypes.A16B16G16R16F: bmp = ReadRGBAFImage(decompressedData, width, height); break; } return(bmp); }
/// <summary> /// Gets the raw pixel data for the texture /// </summary> /// <param name="xivTex">The texture data</param> /// <returns>A byte array with the image data</returns> public byte[] GetImageData(XivTex xivTex) { byte[] imageData = null; switch (xivTex.TextureFormat) { case XivTexFormat.DXT1: imageData = DxtUtil.DecompressDxt1(xivTex.TexData, xivTex.Width, xivTex.Heigth); break; case XivTexFormat.DXT3: imageData = DxtUtil.DecompressDxt3(xivTex.TexData, xivTex.Width, xivTex.Heigth); break; case XivTexFormat.DXT5: imageData = DxtUtil.DecompressDxt5(xivTex.TexData, xivTex.Width, xivTex.Heigth); break; case XivTexFormat.A4R4G4B4: imageData = Read4444Image(xivTex.TexData, xivTex.Width, xivTex.Heigth); break; case XivTexFormat.A1R5G5B5: imageData = Read5551Image(xivTex.TexData, xivTex.Width, xivTex.Heigth); break; case XivTexFormat.A8R8G8B8: imageData = SwapRBColors(xivTex.TexData, xivTex.Width, xivTex.Heigth); break; case XivTexFormat.L8: case XivTexFormat.A8: imageData = Read8bitImage(xivTex.TexData, xivTex.Width, xivTex.Heigth); break; case XivTexFormat.X8R8G8B8: case XivTexFormat.R32F: case XivTexFormat.G16R16F: case XivTexFormat.G32R32F: case XivTexFormat.A16B16G16R16F: case XivTexFormat.A32B32G32R32F: case XivTexFormat.D16: default: imageData = xivTex.TexData; break; } return(imageData); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat = (SurfaceFormat)reader.ReadInt32(); int width = reader.ReadInt32(); int height = reader.ReadInt32(); /*int levelCount =*/ reader.ReadInt32(); int imageLength = reader.ReadInt32(); byte[] imageData = reader.ReadBytes(imageLength); #if NO_DXT35 System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch(); sw2.Reset(); sw2.Start(); // GG TODO need to remove this manual decompression KTHX switch (surfaceFormat) { case SurfaceFormat.Dxt1: imageData = DxtUtil.DecompressDxt1(imageData, width, height); surfaceFormat = SurfaceFormat.Rgba32; break; case SurfaceFormat.Dxt3: imageData = DxtUtil.DecompressDxt3(imageData, width, height); surfaceFormat = SurfaceFormat.Rgba32; break; } if (sw2.ElapsedMilliseconds > 16) { GSGE.Debug.logMessage("Surface Format decompression took " + sw2.ElapsedMilliseconds); } #endif unsafe { fixed(byte *pData = imageData) { ESTexture2D esTexture = new ESTexture2D((IntPtr)pData, imageData.Length, surfaceFormat, width, height, new Size(width, height), All.Linear); texture = new Texture2D(new ESImage(esTexture)); } } return(texture); }
public void Convert(PSB psb) { if (!FromSpec.Contains(psb.Platform)) { throw new FormatException("Can not convert Spec for this PSB"); } var asSpec = EmsAsCommon ? PsbSpec.ems : PsbSpec.common; var toSpec = psb.Platform == PsbSpec.win ? asSpec : PsbSpec.win; var toPixelFormat = toSpec == asSpec ? PsbPixelFormat.CommonRGBA8 : PsbPixelFormat.WinRGBA8; var resList = psb.CollectResources <ImageMetadata>(false); foreach (var resMd in resList) { var resourceData = resMd.Resource.Data; if (resourceData == null) { continue; } if (resMd.Compress == PsbCompressType.RL) { resourceData = RL.Decompress(resourceData); } if (resMd.PixelFormat == PsbPixelFormat.DXT5) { resourceData = RL.GetPixelBytesFromImage( DxtUtil.Dxt5Decode(resourceData, resMd.Width, resMd.Height), toPixelFormat); resMd.TypeString.Value = toPixelFormat.ToStringForPsb(); } else { RL.Switch_0_2(ref resourceData); if (UseRL) { resourceData = RL.Compress(resourceData); } } resMd.Resource.Data = resourceData; } psb.Platform = toSpec; }
public void LoadOddSizedDxtCompressed() { // This is testing that DXT compressed mip levels that // are not a multiple of 4 are properly loaded. var t = content.Load <Texture2D>(Paths.Texture("red_668_dxt")); Assert.AreEqual(SurfaceFormat.Dxt1, t.Format); Assert.AreEqual(10, t.LevelCount); Assert.AreEqual(668, t.Width); Assert.AreEqual(668, t.Height); for (var m = 0; m < t.LevelCount; m++) { var w = ((t.Width >> m) + 3) & ~3; var h = ((t.Height >> m) + 3) & ~3; var size = w * h / 2; // Get the full mip level. var b = new byte[size]; t.GetData(m, null, b, 0, size); // Decompress it to validate it. var b2 = DxtUtil.DecompressDxt1(b, t.Width >> m, t.Height >> m); // Should be a red opaque texture. for (var p = 0; p < b2.Length; p += 4) { Assert.AreEqual(255, b2[p + 0]); Assert.AreEqual(0, b2[p + 1]); Assert.AreEqual(0, b2[p + 2]); Assert.AreEqual(255, b2[p + 3]); } } t.Dispose(); }
/// <summary> /// Reads RenderSurface to bitmap structure /// </summary> public Bitmap GetBitmap() { switch (Format) { case SurfacePixelFormat.PFID_CUSTOM_RAW_JPEG: { var stream = new MemoryStream(SourceData); var image = Image.FromStream(stream); return(new Bitmap(image)); } case SurfacePixelFormat.PFID_DXT1: { var image = DxtUtil.DecompressDxt1(SourceData, Width, Height); return(GetBitmap(image)); } case SurfacePixelFormat.PFID_DXT3: { var image = DxtUtil.DecompressDxt3(SourceData, Width, Height); return(GetBitmap(image)); } case SurfacePixelFormat.PFID_DXT5: { var image = DxtUtil.DecompressDxt5(SourceData, Width, Height); return(GetBitmap(image)); } default: { List <int> colors = GetImageColorArray(); return(GetBitmap(colors)); } } }
/// <summary> /// Gets the raw pixel data for the texture /// </summary> /// <param name="xivTex">The texture data</param> /// <returns>A byte array with the image data</returns> public Task <byte[]> GetImageData(XivTex xivTex, int layer = -1) { return(Task.Run(async() => { byte[] imageData = null; var layers = xivTex.Layers; if (layers == 0) { layers = 1; } switch (xivTex.TextureFormat) { case XivTexFormat.DXT1: imageData = DxtUtil.DecompressDxt1(xivTex.TexData, xivTex.Width, xivTex.Height * layers); break; case XivTexFormat.DXT3: imageData = DxtUtil.DecompressDxt3(xivTex.TexData, xivTex.Width, xivTex.Height * layers); break; case XivTexFormat.DXT5: imageData = DxtUtil.DecompressDxt5(xivTex.TexData, xivTex.Width, xivTex.Height * layers); break; case XivTexFormat.A4R4G4B4: imageData = await Read4444Image(xivTex.TexData, xivTex.Width, xivTex.Height * layers); break; case XivTexFormat.A1R5G5B5: imageData = await Read5551Image(xivTex.TexData, xivTex.Width, xivTex.Height * layers); break; case XivTexFormat.A8R8G8B8: imageData = await SwapRBColors(xivTex.TexData, xivTex.Width, xivTex.Height * layers); break; case XivTexFormat.L8: case XivTexFormat.A8: imageData = await Read8bitImage(xivTex.TexData, xivTex.Width, xivTex.Height * layers); break; case XivTexFormat.X8R8G8B8: case XivTexFormat.R32F: case XivTexFormat.G16R16F: case XivTexFormat.G32R32F: case XivTexFormat.A16B16G16R16F: case XivTexFormat.A32B32G32R32F: case XivTexFormat.D16: default: imageData = xivTex.TexData; break; } if (layer >= 0) { var bytesPerLayer = imageData.Length / xivTex.Layers; var offset = bytesPerLayer * layer; byte[] nData = new byte[bytesPerLayer]; Array.Copy(imageData, offset, nData, 0, bytesPerLayer); imageData = nData; } return imageData; })); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { var surfaceFormat = (SurfaceFormat)reader.ReadInt32(); int width = reader.ReadInt32(); int height = reader.ReadInt32(); int levelCount = reader.ReadInt32(); int levelCountOutput = levelCount; // If the system does not fully support Power of Two textures, // skip any mip maps supplied with any non PoT textures. if (levelCount > 1 && !reader.GetGraphicsDevice().Capabilities.SupportsNonPowerOfTwo&& (!MathHelper.IsPowerOfTwo(width) || !MathHelper.IsPowerOfTwo(height))) { levelCountOutput = 1; System.Diagnostics.Debug.WriteLine( "Device does not support non Power of Two textures. Skipping mipmaps."); } SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: if (!reader.GetGraphicsDevice().Capabilities.SupportsDxt1) { convertedFormat = SurfaceFormat.Rgba32; } break; case SurfaceFormat.Dxt1SRgb: if (!reader.GetGraphicsDevice().Capabilities.SupportsDxt1) { convertedFormat = SurfaceFormat.Rgba32SRgb; } break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: if (!reader.GetGraphicsDevice().Capabilities.SupportsS3tc) { convertedFormat = SurfaceFormat.Rgba32; } break; case SurfaceFormat.Dxt3SRgb: case SurfaceFormat.Dxt5SRgb: if (!reader.GetGraphicsDevice().Capabilities.SupportsS3tc) { convertedFormat = SurfaceFormat.Rgba32SRgb; } break; case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Rgba32; break; } var texture = existingInstance ?? new Texture2D( reader.GetGraphicsDevice(), width, height, levelCountOutput > 1, convertedFormat); for (int level = 0; level < levelCountOutput; level++) { int levelDataSizeInBytes = reader.ReadInt32(); using (var levelDataBuffer = reader.ContentManager.GetScratchBuffer(levelDataSizeInBytes)) { byte[] levelData = levelDataBuffer.Buffer; if (reader.Read(levelData.AsSpan(0, levelDataSizeInBytes)) != levelDataSizeInBytes) { throw new InvalidDataException(); } int levelWidth = Math.Max(width >> level, 1); int levelHeight = Math.Max(height >> level, 1); //Convert the image data if required switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1SRgb: case SurfaceFormat.Dxt1a: if (!reader.GetGraphicsDevice().Capabilities.SupportsDxt1&& convertedFormat == SurfaceFormat.Rgba32) { levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); levelDataSizeInBytes = levelData.Length; } break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt3SRgb: if (!reader.GetGraphicsDevice().Capabilities.SupportsS3tc&& convertedFormat == SurfaceFormat.Rgba32) { levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); levelDataSizeInBytes = levelData.Length; } break; case SurfaceFormat.Dxt5: case SurfaceFormat.Dxt5SRgb: if (!reader.GetGraphicsDevice().Capabilities.SupportsS3tc&& convertedFormat == SurfaceFormat.Rgba32) { levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); levelDataSizeInBytes = levelData.Length; } break; case SurfaceFormat.NormalizedByte4: { int bytesPerPixel = surfaceFormat.GetSize(); int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { int color = BinaryPrimitives.ReadInt32LittleEndian( levelData.AsSpan(y * pitch + x * bytesPerPixel)); levelData[y * pitch + x * 4] = (byte)((color >> 16) & 0xff); //R:=W levelData[y * pitch + x * 4 + 1] = (byte)((color >> 8) & 0xff); //G:=V levelData[y * pitch + x * 4 + 2] = (byte)((color) & 0xff); //B:=U levelData[y * pitch + x * 4 + 3] = (byte)((color >> 24) & 0xff); //A:=Q } } } break; #if OPENGL case SurfaceFormat.Bgra5551: { // Shift the channels to suit OpenGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BinaryPrimitives.ReadUInt16LittleEndian(levelData.AsSpan(offset)); pixel = (ushort)(((pixel & 0x7FFF) << 1) | ((pixel & 0x8000) >> 15)); levelData[offset] = (byte)pixel; levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } } break; case SurfaceFormat.Bgra4444: { // Shift the channels to suit OpenGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BinaryPrimitives.ReadUInt16LittleEndian(levelData.AsSpan(offset)); pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); levelData[offset] = (byte)pixel; levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } } break; #endif } texture.SetData(levelData.AsSpan(0, levelDataSizeInBytes), null, level); } } return(texture); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; var surfaceFormat = (SurfaceFormat)reader.ReadInt32(); int width = reader.ReadInt32(); int height = reader.ReadInt32(); int levelCount = reader.ReadInt32(); int levelCountOutput = levelCount; // If the system does not fully support Power of Two textures, // skip any mip maps supplied with any non PoT textures. if (levelCount > 1 && !reader.GraphicsDevice.GraphicsCapabilities.SupportsNonPowerOfTwo && (!MathHelper.IsPowerOfTwo(width) || !MathHelper.IsPowerOfTwo(height))) { levelCountOutput = 1; System.Diagnostics.Debug.WriteLine( "Device does not support non Power of Two textures. Skipping mipmaps."); } SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1) convertedFormat = SurfaceFormat.Color; break; case SurfaceFormat.Dxt1SRgb: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1) convertedFormat = SurfaceFormat.ColorSRgb; break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) convertedFormat = SurfaceFormat.Color; break; case SurfaceFormat.Dxt3SRgb: case SurfaceFormat.Dxt5SRgb: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) convertedFormat = SurfaceFormat.ColorSRgb; break; case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } texture = existingInstance ?? new Texture2D(reader.GraphicsDevice, width, height, levelCountOutput > 1, convertedFormat); #if OPENGL Threading.BlockOnUIThread(() => { #endif for (int level = 0; level < levelCount; level++) { var levelDataSizeInBytes = reader.ReadInt32(); var levelData = reader.ContentManager.GetScratchBuffer(levelDataSizeInBytes); reader.Read(levelData, 0, levelDataSizeInBytes); int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) continue; //Convert the image data if required switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1SRgb: case SurfaceFormat.Dxt1a: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1 && convertedFormat == SurfaceFormat.Color) { levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); levelDataSizeInBytes = levelData.Length; } break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt3SRgb: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc && convertedFormat == SurfaceFormat.Color) { levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); levelDataSizeInBytes = levelData.Length; } break; case SurfaceFormat.Dxt5: case SurfaceFormat.Dxt5SRgb: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc && convertedFormat == SurfaceFormat.Color) { levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); levelDataSizeInBytes = levelData.Length; } break; case SurfaceFormat.Bgra5551: { #if OPENGL // Shift the channels to suit OpenGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x7FFF) << 1) | ((pixel & 0x8000) >> 15)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } #endif } break; case SurfaceFormat.Bgra4444: { #if OPENGL // Shift the channels to suit OpenGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } #endif } break; case SurfaceFormat.NormalizedByte4: { int bytesPerPixel = surfaceFormat.GetSize(); int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { int color = BitConverter.ToInt32(levelData, y * pitch + x * bytesPerPixel); levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); //R:=W levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); //G:=V levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); //B:=U levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); //A:=Q } } } break; } texture.SetData(level, null, levelData, 0, levelDataSizeInBytes); } #if OPENGL }); #endif return texture; }
protected internal override Texture2D Read( ContentReader reader, Texture2D existingInstance ) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { /* These integer values are based on the enum values * from previous XNA versions. * -flibit */ int legacyFormat = reader.ReadInt32(); if (legacyFormat == 1) { surfaceFormat = SurfaceFormat.ColorBgraEXT; } else if (legacyFormat == 28) { surfaceFormat = SurfaceFormat.Dxt1; } else if (legacyFormat == 30) { surfaceFormat = SurfaceFormat.Dxt3; } else if (legacyFormat == 32) { surfaceFormat = SurfaceFormat.Dxt5; } else { throw new NotSupportedException( "Unsupported legacy surface format." ); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = reader.ReadInt32(); int height = reader.ReadInt32(); int levelCount = reader.ReadInt32(); int levelCountOutput = levelCount; GraphicsDevice device = reader.ContentManager.GetGraphicsDevice(); // Check to see if we need to convert the surface data SurfaceFormat convertedFormat = surfaceFormat; if (surfaceFormat == SurfaceFormat.Dxt1 && !device.GLDevice.SupportsDxt1) { convertedFormat = SurfaceFormat.Color; } else if ((surfaceFormat == SurfaceFormat.Dxt3 || surfaceFormat == SurfaceFormat.Dxt5) && !device.GLDevice.SupportsS3tc) { convertedFormat = SurfaceFormat.Color; } // Check for duplicate instances if (existingInstance == null) { texture = new Texture2D( device, width, height, levelCountOutput > 1, convertedFormat ); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level += 1) { int levelDataSizeInBytes = reader.ReadInt32(); byte[] levelData = null; // Don't assign this quite yet... int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } // Swap the image data if required. if (reader.platform == 'x') { if (surfaceFormat == SurfaceFormat.Color || surfaceFormat == SurfaceFormat.ColorBgraEXT) { levelData = X360TexUtil.SwapColor( reader.ReadBytes(levelDataSizeInBytes) ); levelDataSizeInBytes = levelData.Length; } else if (surfaceFormat == SurfaceFormat.Dxt1) { levelData = X360TexUtil.SwapDxt1( reader.ReadBytes(levelDataSizeInBytes), levelWidth, levelHeight ); levelDataSizeInBytes = levelData.Length; } else if (surfaceFormat == SurfaceFormat.Dxt3) { levelData = X360TexUtil.SwapDxt3( reader.ReadBytes(levelDataSizeInBytes), levelWidth, levelHeight ); levelDataSizeInBytes = levelData.Length; } else if (surfaceFormat == SurfaceFormat.Dxt5) { levelData = X360TexUtil.SwapDxt5( reader.ReadBytes(levelDataSizeInBytes), levelWidth, levelHeight ); levelDataSizeInBytes = levelData.Length; } } // Convert the image data if required if (convertedFormat != surfaceFormat) { // May already be read in by 'x' conversion if (levelData == null) { levelData = reader.ReadBytes(levelDataSizeInBytes); } if (surfaceFormat == SurfaceFormat.Dxt1) { levelData = DxtUtil.DecompressDxt1( levelData, levelWidth, levelHeight ); } else if (surfaceFormat == SurfaceFormat.Dxt3) { levelData = DxtUtil.DecompressDxt3( levelData, levelWidth, levelHeight ); } else if (surfaceFormat == SurfaceFormat.Dxt5) { levelData = DxtUtil.DecompressDxt5( levelData, levelWidth, levelHeight ); } levelDataSizeInBytes = levelData.Length; } int levelDataByteOffset = 0; if (levelData == null) { if (reader.BaseStream is MemoryStream && ((MemoryStream)reader.BaseStream).TryGetBuffer(out levelData)) { /* Ideally, we didn't have to perform any conversion or * unnecessary reading. Just throw the buffer directly * into SetData, skipping a redundant byte[] copy. */ levelDataByteOffset = (int)reader.BaseStream.Seek(0, SeekOrigin.Current); reader.BaseStream.Seek( levelDataSizeInBytes, SeekOrigin.Current ); } else { /* If we don't have to perform any conversion and * the ContentReader is not backed by a MemoryStream * with a public buffer, we have to read the data in. */ levelData = reader.ReadBytes(levelDataSizeInBytes); } } texture.SetData( level, null, levelData, levelDataByteOffset, levelDataSizeInBytes ); } return(texture); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormat_Legacy legacyFormat = (SurfaceFormat_Legacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormat_Legacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormat_Legacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormat_Legacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormat_Legacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotImplementedException(); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = (reader.ReadInt32()); int height = (reader.ReadInt32()); int levelCount = (reader.ReadInt32()); SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { #if IPHONE // At the moment. If a DXT Texture comes in on iOS, it's really a PVR compressed // texture. We need to use this hack until the content pipeline is implemented. // For now DXT5 means we're using 4bpp PVRCompression and DXT3 means 2bpp. Look at // PvrtcBitmapContent.cs for more information.: case SurfaceFormat.Dxt3: convertedFormat = SurfaceFormat.RgbaPvrtc2Bpp; break; case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.RgbaPvrtc4Bpp; break; #elif ANDROID || PSS case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.Color; break; #endif case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } if (existingInstance == null) { texture = new Texture2D(reader.GraphicsDevice, width, height, levelCount > 1, convertedFormat); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level++) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = reader.ReadBytes(levelDataSizeInBytes); int levelWidth = width >> level; int levelHeight = height >> level; //Convert the image data if required switch (surfaceFormat) { #if ANDROID || PSS //no Dxt in OpenGL ES case SurfaceFormat.Dxt1: levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); break; case SurfaceFormat.Dxt3: levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); break; case SurfaceFormat.Dxt5: levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); break; #endif case SurfaceFormat.Bgr565: { /* * // BGR -> BGR * int offset = 0; * for (int y = 0; y < levelHeight; y++) * { * for (int x = 0; x < levelWidth; x++) * { * ushort pixel = BitConverter.ToUInt16(levelData, offset); * pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); * levelData[offset] = (byte)(pixel); * levelData[offset + 1] = (byte)(pixel >> 8); * offset += 2; * } * } */ } break; case SurfaceFormat.Bgra4444: { // Shift the channels to suit GLES int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } } break; case SurfaceFormat.NormalizedByte4: { int bytesPerPixel = surfaceFormat.Size(); int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { int color = BitConverter.ToInt32(levelData, y * pitch + x * bytesPerPixel); levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); //R:=W levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); //G:=V levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); //B:=U levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); //A:=Q } } } break; } texture.SetData(level, null, levelData, 0, levelData.Length); } return(texture); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormatLegacy legacyFormat = (SurfaceFormatLegacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormatLegacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormatLegacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormatLegacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormatLegacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotSupportedException("Unsupported legacy surface format."); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = (reader.ReadInt32()); int height = (reader.ReadInt32()); int levelCount = (reader.ReadInt32()); int levelCountOutput = levelCount; // If the system does not fully support Power of Two textures, // skip any mip maps supplied with any non PoT textures. if (levelCount > 1 && !reader.GraphicsDevice.GraphicsCapabilities.SupportsNonPowerOfTwo && (!MathHelper.IsPowerOfTwo(width) || !MathHelper.IsPowerOfTwo(height))) { levelCountOutput = 1; System.Diagnostics.Debug.WriteLine( "Device does not support non Power of Two textures. Skipping mipmaps."); } SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { #if IOS // At the moment. If a DXT Texture comes in on iOS, it's really a PVR compressed // texture. We need to use this hack until the content pipeline is implemented. // For now DXT5 means we're using 4bpp PVRCompression and DXT3 means 2bpp. Look at // PvrtcBitmapContent.cs for more information.: case SurfaceFormat.Dxt3: convertedFormat = SurfaceFormat.RgbaPvrtc2Bpp; break; case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.RgbaPvrtc4Bpp; break; #else case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1) { convertedFormat = SurfaceFormat.Color; } break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) { convertedFormat = SurfaceFormat.Color; } break; #endif case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } if (existingInstance == null) { texture = new Texture2D(reader.GraphicsDevice, width, height, levelCountOutput > 1, convertedFormat); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level++) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = reader.ReadBytes(levelDataSizeInBytes); int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } //Convert the image data if required switch (surfaceFormat) { #if !IOS case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1) { levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); } break; case SurfaceFormat.Dxt3: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) { levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); } break; case SurfaceFormat.Dxt5: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) { levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); } break; #endif case SurfaceFormat.Bgr565: { /* * // BGR -> BGR * int offset = 0; * for (int y = 0; y < levelHeight; y++) * { * for (int x = 0; x < levelWidth; x++) * { * ushort pixel = BitConverter.ToUInt16(levelData, offset); * pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); * levelData[offset] = (byte)(pixel); * levelData[offset + 1] = (byte)(pixel >> 8); * offset += 2; * } * } */ } break; case SurfaceFormat.Bgra5551: { #if OPENGL // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x7FFF) << 1) | ((pixel & 0x8000) >> 15)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } #endif } break; case SurfaceFormat.Bgra4444: { #if OPENGL // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } #endif } break; case SurfaceFormat.NormalizedByte4: { int bytesPerPixel = surfaceFormat.GetSize(); int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { int color = BitConverter.ToInt32(levelData, y * pitch + x * bytesPerPixel); levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); //R:=W levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); //G:=V levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); //B:=U levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); //A:=Q } } } break; } texture.SetData(level, null, levelData, 0, levelData.Length); } return(texture); }
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { if (fileOpen == false || listBox1.SelectedIndex == -1) { return; } int x = listBox1.SelectedIndex; string[] split = listBox1.Items[x].ToString().Split(' '); int actualNtp3 = int.Parse(split[1]); int actualGidx = int.Parse(split[2]); //MessageBox.Show(actualNtp3.ToString("X2") + ", " + actualGidx.ToString("X2")); int resx = Main.b_byteArrayToIntRev(new byte[] { 0, 0, gidxHeaders[actualNtp3][actualGidx][0x14], gidxHeaders[actualNtp3][actualGidx][0x15] }); int resy = Main.b_byteArrayToIntRev(new byte[] { 0, 0, gidxHeaders[actualNtp3][actualGidx][0x16], gidxHeaders[actualNtp3][actualGidx][0x17] }); w_texsize.Text = "Texture size: " + resx.ToString() + "x" + resy.ToString(); /*string a = ""; * for(int b = 0; b < gidxHeaders[actualNtp3][actualGidx].Length; b++) * { * a = a + gidxHeaders[actualNtp3][actualGidx][b].ToString("X2") + " "; * } * MessageBox.Show(a);*/ byte texType = gidxHeaders[actualNtp3][actualGidx][0x13]; byte[] rawimg = new byte[0]; switch (texType) { default: w_textype.Text = "Texture type: Unknown"; pictureBox1.Image = blackImage; break; case 0: w_textype.Text = "Texture type: DXT1"; rawimg = DxtUtil.DecompressDxt1(textureData[actualNtp3][actualGidx], resx, resy); break; case 1: w_textype.Text = "Texture type: DXT3/DXT5 with mipmaps"; rawimg = DxtUtil.DecompressDxt5(textureData[actualNtp3][actualGidx], resx, resy); break; case 2: w_textype.Text = "Texture type: DXT3/DXT5"; rawimg = DxtUtil.DecompressDxt5(textureData[actualNtp3][actualGidx], resx, resy); break; case 8: w_textype.Text = "Texture type: 5.6.5"; pictureBox1.Image = blackImage; break; } if (rawimg.Length > 0) { bmp = new Bitmap(resx, resy, PixelFormat.Format32bppArgb); BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, resx, resy), ImageLockMode.WriteOnly, bmp.PixelFormat); Marshal.Copy(rawimg, 0, bmpData.Scan0, resx * resy * 4); bmp.UnlockBits(bmpData); pictureBox1.Image = bmp; } }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormatLegacy legacyFormat = (SurfaceFormatLegacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormatLegacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormatLegacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormatLegacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormatLegacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotSupportedException("Unsupported legacy surface format."); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = (reader.ReadInt32()); int height = (reader.ReadInt32()); int levelCount = (reader.ReadInt32()); int levelCountOutput = levelCount; SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: convertedFormat = SurfaceFormat.Color; break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.Color; break; case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } UnityEngine.Texture2D unityTexture = new UnityEngine.Texture2D(width, height, XnaToUnity.TextureFormat(convertedFormat), levelCountOutput > 1); for (int level = 0; level < levelCount; level++) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = reader.ReadBytes(levelDataSizeInBytes); int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } //Convert the image data if required switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); break; case SurfaceFormat.Dxt3: levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); break; case SurfaceFormat.Dxt5: levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); break; } // un-premultiply alpha (instead do it in the shader) for (int i = 0; i < levelData.Length; i += 4) { float r = levelData[i + 0] / 255.0f; float g = levelData[i + 1] / 255.0f; float b = levelData[i + 2] / 255.0f; float a = levelData[i + 3] / 255.0f; levelData[i + 0] = (byte)(r / a * 255.0f); levelData[i + 1] = (byte)(g / a * 255.0f); levelData[i + 2] = (byte)(b / a * 255.0f); //levelData[i + 0] = 0; //levelData[i + 1] = 255; //levelData[i + 2] = 0; //levelData[i + 3] = 255; } // swap rows because unity textures are laid out bottom-top instead of top-bottom int rowSize = width * 4; byte[] temp = new byte[rowSize]; for (int i = 0; i < levelData.Length / 2; i += rowSize) { for (int j = 0; j < rowSize; j++) { temp[j] = levelData[i + j]; } int p = levelData.Length - (i + rowSize); for (int j = 0; j < rowSize; j++) { levelData[i + j] = levelData[p + j]; } for (int j = 0; j < rowSize; j++) { levelData[p + j] = temp[j]; } } UnityEngine.Color[] unityColors = new UnityEngine.Color[levelData.Length * 4]; unityTexture.SetPixels(XnaToUnity.Color(levelData, ref unityColors), level); unityTexture.Apply(); texture = new Texture2D(unityTexture); } return(texture); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { SurfaceFormat surfaceFormat; if (reader.version < 5) { switch ((SurfaceFormat_Legacy)reader.ReadInt32()) { case SurfaceFormat_Legacy.Color: surfaceFormat = SurfaceFormat.Color; break; case SurfaceFormat_Legacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormat_Legacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormat_Legacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; default: throw new NotImplementedException(); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width1 = reader.ReadInt32(); int height1 = reader.ReadInt32(); int num1 = reader.ReadInt32(); int num2 = num1; if (num1 > 1 && !GraphicsCapabilities.NonPowerOfTwo && (!MathHelper.IsPowerOfTwo(width1) || !MathHelper.IsPowerOfTwo(height1))) { num2 = 1; } SurfaceFormat format = surfaceFormat; if (surfaceFormat == SurfaceFormat.NormalizedByte4) { format = SurfaceFormat.Color; } if (!GraphicsExtensions.UseDxtCompression) { switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: format = SurfaceFormat.Color; break; } } Texture2D texture2D = existingInstance != null ? existingInstance : new Texture2D(reader.GraphicsDevice, width1, height1, num2 > 1, format); for (int level = 0; level < num1; ++level) { int count = reader.ReadInt32(); byte[] numArray = reader.ReadBytes(count); int width2 = width1 >> level; int height2 = height1 >> level; if (level < num2) { if (!GraphicsExtensions.UseDxtCompression) { switch (surfaceFormat) { case SurfaceFormat.Dxt1: numArray = DxtUtil.DecompressDxt1(numArray, width2, height2); break; case SurfaceFormat.Dxt3: numArray = DxtUtil.DecompressDxt3(numArray, width2, height2); break; case SurfaceFormat.Dxt5: numArray = DxtUtil.DecompressDxt5(numArray, width2, height2); break; } } switch (surfaceFormat) { case SurfaceFormat.Bgra5551: int startIndex1 = 0; for (int index1 = 0; index1 < height2; ++index1) { for (int index2 = 0; index2 < width2; ++index2) { ushort num3 = BitConverter.ToUInt16(numArray, startIndex1); ushort num4 = (ushort)(((int)num3 & (int)short.MaxValue) << 1 | ((int)num3 & 32768) >> 15); numArray[startIndex1] = (byte)num4; numArray[startIndex1 + 1] = (byte)((uint)num4 >> 8); startIndex1 += 2; } } break; case SurfaceFormat.Bgra4444: int startIndex2 = 0; for (int index1 = 0; index1 < height2; ++index1) { for (int index2 = 0; index2 < width2; ++index2) { ushort num3 = BitConverter.ToUInt16(numArray, startIndex2); ushort num4 = (ushort)(((int)num3 & 4095) << 4 | ((int)num3 & 61440) >> 12); numArray[startIndex2] = (byte)num4; numArray[startIndex2 + 1] = (byte)((uint)num4 >> 8); startIndex2 += 2; } } break; case SurfaceFormat.NormalizedByte4: int num5 = GraphicsExtensions.Size(surfaceFormat); int num6 = width2 * num5; for (int index1 = 0; index1 < height2; ++index1) { for (int index2 = 0; index2 < width2; ++index2) { int num3 = BitConverter.ToInt32(numArray, index1 * num6 + index2 * num5); numArray[index1 * num6 + index2 * 4] = (byte)(num3 >> 16 & (int)byte.MaxValue); numArray[index1 * num6 + index2 * 4 + 1] = (byte)(num3 >> 8 & (int)byte.MaxValue); numArray[index1 * num6 + index2 * 4 + 2] = (byte)(num3 & (int)byte.MaxValue); numArray[index1 * num6 + index2 * 4 + 3] = (byte)(num3 >> 24 & (int)byte.MaxValue); } } break; } texture2D.SetData <byte>(level, new Rectangle?(), numArray, 0, numArray.Length); } } return(texture2D); }
/// <summary> /// Gets the raw pixel data for the texture. /// </summary> /// <returns>A byte array with the image data.</returns> private byte[] GetImageData(int layer = -1) { byte[] imageData = null; int layers = this.layers; if (layers == 0) { layers = 1; } switch (this.textureFormat) { case XivTexFormat.DXT1: imageData = DxtUtil.DecompressDxt1(this.rawData, this.width, this.height * layers); break; case XivTexFormat.DXT3: imageData = DxtUtil.DecompressDxt3(this.rawData, this.width, this.height * layers); break; case XivTexFormat.DXT5: imageData = DxtUtil.DecompressDxt5(this.rawData, this.width, this.height * layers); break; case XivTexFormat.A4R4G4B4: imageData = Read4444Image(this.rawData, this.width, this.height * layers); break; case XivTexFormat.A1R5G5B5: imageData = Read5551Image(this.rawData, this.width, this.height * layers); break; case XivTexFormat.A8R8G8B8: imageData = SwapRBColors(this.rawData, this.width, this.height * layers); break; case XivTexFormat.L8: case XivTexFormat.A8: imageData = Read8bitImage(this.rawData, this.width, this.height * layers); break; case XivTexFormat.X8R8G8B8: case XivTexFormat.R32F: case XivTexFormat.G16R16F: case XivTexFormat.G32R32F: case XivTexFormat.A16B16G16R16F: case XivTexFormat.A32B32G32R32F: case XivTexFormat.D16: default: imageData = this.rawData; break; } if (layer >= 0) { int bytesPerLayer = imageData.Length / this.layers; int offset = bytesPerLayer * layer; byte[] nData = new byte[bytesPerLayer]; Array.Copy(imageData, offset, nData, 0, bytesPerLayer); imageData = nData; } return(imageData); }
protected internal override Texture2D Read( ContentReader reader, Texture2D existingInstance ) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormat_Legacy legacyFormat = (SurfaceFormat_Legacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormat_Legacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormat_Legacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormat_Legacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormat_Legacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotSupportedException( "Unsupported legacy surface format." ); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = reader.ReadInt32(); int height = reader.ReadInt32(); int levelCount = reader.ReadInt32(); int levelCountOutput = levelCount; SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { case SurfaceFormat.Dxt1: if (!OpenGLDevice.Instance.SupportsDxt1) { convertedFormat = SurfaceFormat.Color; } break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: if (!OpenGLDevice.Instance.SupportsS3tc) { convertedFormat = SurfaceFormat.Color; } break; case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } if (existingInstance == null) { texture = new Texture2D( reader.GraphicsDevice, width, height, levelCountOutput > 1, convertedFormat ); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level += 1) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = null; // Don't assign this quite yet... int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } // Convert the image data if required switch (surfaceFormat) { case SurfaceFormat.Dxt1: if (!OpenGLDevice.Instance.SupportsDxt1) { levelData = reader.ReadBytes(levelDataSizeInBytes); levelData = DxtUtil.DecompressDxt1( levelData, levelWidth, levelHeight ); } break; case SurfaceFormat.Dxt3: if (!OpenGLDevice.Instance.SupportsS3tc) { levelData = reader.ReadBytes(levelDataSizeInBytes); levelData = DxtUtil.DecompressDxt3( levelData, levelWidth, levelHeight ); } break; case SurfaceFormat.Dxt5: if (!OpenGLDevice.Instance.SupportsS3tc) { levelData = reader.ReadBytes(levelDataSizeInBytes); levelData = DxtUtil.DecompressDxt5( levelData, levelWidth, levelHeight ); } break; case SurfaceFormat.Bgr565: { levelData = reader.ReadBytes(levelDataSizeInBytes); } break; case SurfaceFormat.Bgra5551: { levelData = reader.ReadBytes(levelDataSizeInBytes); // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y += 1) { for (int x = 0; x < levelWidth; x += 1) { ushort pixel = BitConverter.ToUInt16( levelData, offset ); pixel = (ushort)( ((pixel & 0x7FFF) << 1) | ((pixel & 0x8000) >> 15) ); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } } break; case SurfaceFormat.Bgra4444: { levelData = reader.ReadBytes(levelDataSizeInBytes); // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y += 1) { for (int x = 0; x < levelWidth; x += 1) { ushort pixel = BitConverter.ToUInt16( levelData, offset ); pixel = (ushort)( ((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12) ); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } } break; case SurfaceFormat.NormalizedByte4: { levelData = reader.ReadBytes(levelDataSizeInBytes); int bytesPerPixel = 4; // According to Texture.GetFormatSize() int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y += 1) { for (int x = 0; x < levelWidth; x += 1) { int color = BitConverter.ToInt32( levelData, y * pitch + x * bytesPerPixel ); // R:=W levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); // G:=V levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); // B:=U levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); // A:=Q levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); } } } break; } if (levelData == null && reader.BaseStream.GetType() != typeof(System.IO.MemoryStream)) { /* If the ContentReader is not backed by a * MemoryStream, we have to read the data in. */ levelData = reader.ReadBytes(levelDataSizeInBytes); } if (levelData != null) { /* If we had to convert the data, or get the data from a * non-MemoryStream, we set the data with our levelData * reference. */ texture.SetData(level, null, levelData, 0, levelData.Length); } else { /* Ideally, we didn't have to perform any conversion or * unnecessary reading. Just throw the buffer directly * into SetData, skipping a redundant byte[] copy. */ texture.SetData <byte>( level, null, (((System.IO.MemoryStream)(reader.BaseStream)).GetBuffer()), (int)reader.BaseStream.Position, levelDataSizeInBytes ); reader.BaseStream.Seek( levelDataSizeInBytes, System.IO.SeekOrigin.Current ); } } return(texture); }
public TextureToBitmap(byte[] decompressedData, int textureType, int[] dimensions) { byte[] decompressedTexture; switch (textureType) { //DXT1 case 13344: typeString = "DXT1"; decompressedTexture = DxtUtil.DecompressDxt1(decompressedData, dimensions[0], dimensions[1]); bmp = readLinearImage(decompressedTexture, dimensions[0], dimensions[1]); break; //DXT3 case 13360: typeString = "DXT3"; decompressedTexture = DxtUtil.DecompressDxt3(decompressedData, dimensions[0], dimensions[1]); bmp = readLinearImage(decompressedTexture, dimensions[0], dimensions[1]); break; //DXT5 case 13361: typeString = "DXT5"; decompressedTexture = DxtUtil.DecompressDxt5(decompressedData, dimensions[0], dimensions[1]); bmp = readLinearImage(decompressedTexture, dimensions[0], dimensions[1]); break; //8-bit image case 4401: case 4400: typeString = "8bit"; bmp = read8bitImage(decompressedData, dimensions[0], dimensions[1]); break; //16-bit image in RGB4444 format case 5184: typeString = "16bit R4G4B4A4"; bmp = read4444Image(decompressedData, dimensions[0], dimensions[1]); break; //16-bit image in RGB5551 format case 5185: typeString = "16bit R5G5B5A1"; bmp = read5551Image(decompressedData, dimensions[0], dimensions[1]); break; //32-bit A8R8G8B8 image case 5200: case 4440: case 5201: typeString = "32bit A8R8G8B8"; bmp = new Bitmap(dimensions[0], dimensions[1], dimensions[0] * 4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, Marshal.UnsafeAddrOfPinnedArrayElement(decompressedData, 0)); break; //64-bit A16R16G16B16 image case 9312: typeString = "64bit A16R16G16B16"; bmp = readRGBAFImage(decompressedData, dimensions[0], dimensions[1]); break; } }
protected internal override Texture2D Read( ContentReader reader, Texture2D existingInstance ) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { /* These integer values are based on the enum values * from previous XNA versions. * -flibit */ int legacyFormat = reader.ReadInt32(); if (legacyFormat == 1) { surfaceFormat = SurfaceFormat.ColorBgraEXT; } else if (legacyFormat == 28) { surfaceFormat = SurfaceFormat.Dxt1; } else if (legacyFormat == 30) { surfaceFormat = SurfaceFormat.Dxt3; } else if (legacyFormat == 32) { surfaceFormat = SurfaceFormat.Dxt5; } else { throw new NotSupportedException( "Unsupported legacy surface format." ); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = reader.ReadInt32(); int height = reader.ReadInt32(); int levelCount = reader.ReadInt32(); int levelCountOutput = levelCount; // Check to see if we need to convert the surface data SurfaceFormat convertedFormat = surfaceFormat; if (surfaceFormat == SurfaceFormat.Dxt1 && !reader.GraphicsDevice.GLDevice.SupportsDxt1) { convertedFormat = SurfaceFormat.Color; } else if ((surfaceFormat == SurfaceFormat.Dxt3 || surfaceFormat == SurfaceFormat.Dxt5) && !reader.GraphicsDevice.GLDevice.SupportsS3tc) { convertedFormat = SurfaceFormat.Color; } // Check for duplicate instances if (existingInstance == null) { texture = new Texture2D( reader.GraphicsDevice, width, height, levelCountOutput > 1, convertedFormat ); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level += 1) { int levelDataSizeInBytes = reader.ReadInt32(); byte[] levelData = null; // Don't assign this quite yet... int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } // Swap the image data if required. if (reader.platform == 'x') { if (surfaceFormat == SurfaceFormat.Color || surfaceFormat == SurfaceFormat.ColorBgraEXT) { if (levelData == null) { levelData = reader.ReadBytes(levelDataSizeInBytes); } levelData = X360TexUtil.SwapColor( levelData ); } else if (surfaceFormat == SurfaceFormat.Dxt1) { if (levelData == null) { levelData = reader.ReadBytes(levelDataSizeInBytes); } levelData = X360TexUtil.SwapDxt1( levelData, levelWidth, levelHeight ); } else if (surfaceFormat == SurfaceFormat.Dxt3) { if (levelData == null) { levelData = reader.ReadBytes(levelDataSizeInBytes); } levelData = X360TexUtil.SwapDxt3( levelData, levelWidth, levelHeight ); } else if (surfaceFormat == SurfaceFormat.Dxt5) { if (levelData == null) { levelData = reader.ReadBytes(levelDataSizeInBytes); } levelData = X360TexUtil.SwapDxt5( levelData, levelWidth, levelHeight ); } } // Convert the image data if required if (surfaceFormat == SurfaceFormat.Dxt1 && !reader.GraphicsDevice.GLDevice.SupportsDxt1) { if (levelData == null) { levelData = reader.ReadBytes(levelDataSizeInBytes); } levelData = DxtUtil.DecompressDxt1( levelData, levelWidth, levelHeight ); } else if (surfaceFormat == SurfaceFormat.Dxt3 && !reader.GraphicsDevice.GLDevice.SupportsS3tc) { if (levelData == null) { levelData = reader.ReadBytes(levelDataSizeInBytes); } levelData = DxtUtil.DecompressDxt3( levelData, levelWidth, levelHeight ); } else if (surfaceFormat == SurfaceFormat.Dxt5 && !reader.GraphicsDevice.GLDevice.SupportsS3tc) { if (levelData == null) { levelData = reader.ReadBytes(levelDataSizeInBytes); } levelData = DxtUtil.DecompressDxt5( levelData, levelWidth, levelHeight ); } if (levelData == null && reader.BaseStream.GetType() != typeof(System.IO.MemoryStream)) { /* If the ContentReader is not backed by a * MemoryStream, we have to read the data in. */ levelData = reader.ReadBytes(levelDataSizeInBytes); } if (levelData != null) { /* If we had to convert the data, or get the data from a * non-MemoryStream, we set the data with our levelData * reference. */ texture.SetData(level, null, levelData, 0, levelData.Length); } else { /* Ideally, we didn't have to perform any conversion or * unnecessary reading. Just throw the buffer directly * into SetData, skipping a redundant byte[] copy. */ texture.SetData <byte>( level, null, (((System.IO.MemoryStream)(reader.BaseStream)).GetBuffer()), (int)reader.BaseStream.Position, levelDataSizeInBytes ); reader.BaseStream.Seek( levelDataSizeInBytes, System.IO.SeekOrigin.Current ); } } return(texture); }
public static byte[] ExtractImageCore(BinaryReader reader, RectInfo?rectInfoList = null) { var magic = Encoding.ASCII.GetString(reader.ReadBytes(4)); var endianCheck1 = reader.ReadInt32(); var endianCheck2 = reader.ReadInt32(); var requiresEndianFix = endianCheck2 == 0x00010100; reader.BaseStream.Seek(0x0c, SeekOrigin.Begin); var dataSize = ReadInt32(reader, requiresEndianFix) - 0x40; var width = ReadInt16(reader, requiresEndianFix); var height = ReadInt16(reader, requiresEndianFix); if (!requiresEndianFix) { reader.BaseStream.Seek(0x03, SeekOrigin.Current); } /* * GRAYSCALE_FORMAT 0x01 * GRAYSCALE_FORMAT_2 0x06 * BGR_16BIT_FORMAT 0x0C * BGRA_16BIT_FORMAT 0x0D * BGR_FORMAT 0x0E * BGRA_FORMAT 0x10 * BGR_4BIT_FORMAT 0x11 * BGR_8BIT_FORMAT 0x12 * DXT1_FORMAT 0x16 * DXT3_FORMAT 0x18 * DXT5_FORMAT 0x1A */ var dataFormat = reader.ReadByte(); reader.BaseStream.Seek(0x40, SeekOrigin.Begin); var bitmapData = reader.ReadBytes(dataSize); var paletteEntries = new List <Color>(); var pixelFormat = PixelFormat.Undefined; if (dataFormat == 0x01) { // GRAYSCALE_FORMAT8 pixelFormat = PixelFormat.Format8bppIndexed; } else if (dataFormat == 0x06) { // GRAYSCALE_FORMAT_2 pixelFormat = PixelFormat.Format8bppIndexed; } else if (dataFormat == 0x0c) { // BGR_16BIT_FORMAT pixelFormat = PixelFormat.Format16bppRgb565; } else if (dataFormat == 0x0d) { // BGRA_16BIT_FORMAT byte[] newBitmapData = new byte[width * height * 4]; for (int didx = 0, i = 0; i < height; i++) { for (var j = 0; j < width; j++, didx += 2) { ushort c = (ushort)((bitmapData[didx + 1] << 8) | bitmapData[didx]); DxtUtil.ConvertArgb4444ToArgb8888(c, out var a, out var r, out var g, out var b); newBitmapData[(j * 4) + (i * width * 4)] = a; newBitmapData[(j * 4) + 1 + (i * width * 4)] = r; newBitmapData[(j * 4) + 2 + (i * width * 4)] = g; newBitmapData[(j * 4) + 3 + (i * width * 4)] = b; } } bitmapData = newBitmapData; pixelFormat = PixelFormat.Format32bppArgb; } else if (dataFormat == 0x0e) { // BGR_FORMAT pixelFormat = PixelFormat.Format24bppRgb; } else if (dataFormat == 0x10) { // BGRA_FORMAT pixelFormat = PixelFormat.Format32bppArgb; } else if (dataFormat == 0x11) { // BGR_4BIT_FORMAT var bitmapDataOnly = new byte[width * height / 2]; Buffer.BlockCopy(bitmapData, 0, bitmapDataOnly, 0, bitmapDataOnly.Length); var paletteData = new byte[bitmapData.Length - bitmapDataOnly.Length - 0x14]; // Skip palette header Buffer.BlockCopy(bitmapData, bitmapDataOnly.Length + 0x14, paletteData, 0, paletteData.Length); bitmapData = bitmapDataOnly; pixelFormat = PixelFormat.Format4bppIndexed; for (int i = 0; i < paletteData.Length; i += 4) { paletteEntries.Add(Color.FromArgb(paletteData[i + 3], paletteData[i], paletteData[i + 1], paletteData[i + 2])); } // Flip pixels for (int i = 0; i < bitmapData.Length; i++) { var l = (bitmapData[i] & 0x0f) << 4; var r = (bitmapData[i] & 0xf0) >> 4; bitmapData[i] = (byte)(l | r); } } else if (dataFormat == 0x12) { // BGR_8BIT_FORMAT var bitmapDataOnly = new byte[width * height]; Buffer.BlockCopy(bitmapData, 0, bitmapDataOnly, 0, bitmapDataOnly.Length); var paletteData = new byte[bitmapData.Length - bitmapDataOnly.Length - 0x14]; // Skip palette header Buffer.BlockCopy(bitmapData, bitmapDataOnly.Length + 0x14, paletteData, 0, paletteData.Length); bitmapData = bitmapDataOnly; pixelFormat = PixelFormat.Format8bppIndexed; for (int i = 0; i < paletteData.Length; i += 4) { paletteEntries.Add(Color.FromArgb(paletteData[i + 3], paletteData[i], paletteData[i + 1], paletteData[i + 2])); } } else if (dataFormat == 0x16) { // DXT1_FORMAT pixelFormat = PixelFormat.Format32bppArgb; bitmapData = DxtUtil.DecompressDxt1(bitmapData, width, height); } else if (dataFormat == 0x18) { // DXT3_FORMAT pixelFormat = PixelFormat.Format32bppArgb; bitmapData = DxtUtil.DecompressDxt3(bitmapData, width, height); } else if (dataFormat == 0x1a) { // DXT5_FORMAT pixelFormat = PixelFormat.Format32bppArgb; bitmapData = DxtUtil.DecompressDxt5(bitmapData, width, height); } else { throw new Exception(String.Format("Found unknown pixel format: {0:x2}", dataFormat)); } for (int i = 0; i < bitmapData.Length;) { if (pixelFormat == PixelFormat.Format16bppArgb1555) { var a = bitmapData[i] & 0x0f; var r = (bitmapData[i] >> 4) & 0x0f; var g = bitmapData[i + 1] & 0x0f; var b = (bitmapData[i + 1] >> 4) & 0x0f; bitmapData[i + 1] = (byte)((a << 4) | b); bitmapData[i + 0] = (byte)((g << 4) | r); i += 2; } else if (pixelFormat == PixelFormat.Format16bppRgb565) { bitmapData[i] = (byte)((bitmapData[i] & 0xc0) | (bitmapData[i] & 0x3f) >> 1); i += 2; } else if (pixelFormat == PixelFormat.Format24bppRgb) { var t = bitmapData[i + 2]; bitmapData[i + 2] = bitmapData[i]; bitmapData[i] = t; i += 3; } else if (pixelFormat == PixelFormat.Format32bppArgb) { var t = bitmapData[i + 2]; bitmapData[i + 2] = bitmapData[i]; bitmapData[i] = t; i += 4; } else { break; } } if (pixelFormat == PixelFormat.Undefined || pixelFormat == PixelFormat.Format16bppArgb1555) { // Create DDS file var output = new List <byte>(); output.AddRange(new byte[] { 0x44, 0x44, 0x53, 0x20, 0x7C, 0x00, 0x00, 0x00, 0x07, 0x10, 0x08, 0x00 }); output.AddRange(BitConverter.GetBytes(height)); output.AddRange(BitConverter.GetBytes(width)); output.AddRange(BitConverter.GetBytes(dataSize)); output.AddRange(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 }); if (pixelFormat == PixelFormat.Format16bppArgb1555) { output.AddRange(new byte[] { 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); } else if (pixelFormat == PixelFormat.Format16bppRgb555) { output.AddRange(new byte[] { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); } else { output.AddRange(new byte[] { 0x04, 0x00, 0x00, 0x00 }); if (dataFormat == 0x16) { output.AddRange(Encoding.ASCII.GetBytes("DXT1")); } else if (dataFormat == 0x18) { output.AddRange(Encoding.ASCII.GetBytes("DXT3")); } else if (dataFormat == 0x1a) { output.AddRange(Encoding.ASCII.GetBytes("DXT5")); } output.AddRange(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); } output.AddRange(bitmapData); return(output.ToArray()); } else { var b = new Bitmap(width, height, pixelFormat); if (pixelFormat == PixelFormat.Format8bppIndexed || pixelFormat == PixelFormat.Format4bppIndexed) { ColorPalette palette = b.Palette; Color[] entries = palette.Entries; if (paletteEntries.Count == 0) { for (int i = 0; i < 256; i++) { Color c = Color.FromArgb((byte)i, (byte)i, (byte)i); entries[i] = c; } } else { for (int i = 0; i < paletteEntries.Count; i++) { entries[i] = paletteEntries[i]; } } b.Palette = palette; } var boundsRect = new Rectangle(0, 0, width, height); BitmapData bmpData = b.LockBits(boundsRect, ImageLockMode.WriteOnly, b.PixelFormat); IntPtr ptr = bmpData.Scan0; if (pixelFormat != PixelFormat.Format24bppRgb) { int bytes = bmpData.Stride * b.Height; Marshal.Copy(bitmapData, 0, ptr, bytes); } else { // Because things are stupid, we have to pad the lines for 24bit images ourself... for (int i = 0; i < height; i++) { Marshal.Copy(bitmapData, i * width * 3, ptr + (bmpData.Stride * i), width * 3); } } b.UnlockBits(bmpData); // Split into separate smaller bitmap if (rectInfoList != null) { var rect = new Rectangle(rectInfoList.Value.X, rectInfoList.Value.Y, rectInfoList.Value.W, rectInfoList.Value.H); Bitmap subimage = new Bitmap(rect.Width, rect.Height); Console.WriteLine(rect); using (Graphics g = Graphics.FromImage(subimage)) { g.DrawImage(b, new Rectangle(0, 0, subimage.Width, subimage.Height), rect, GraphicsUnit.Pixel); } b = subimage; } ImageConverter converter = new ImageConverter(); return((byte[])converter.ConvertTo(b, typeof(byte[]))); } }