public byte[] Save(IEnumerable <Color> colors) { if (_width < 0 || _height < 0) { throw new InvalidDataException("Height and Width has to be set for PVRTC."); } var ms = new MemoryStream(); using (var bw = new BinaryWriterX(ms, true)) foreach (var color in colors) { bw.Write(color.R); bw.Write(color.G); bw.Write(color.B); bw.Write(color.A); } var pvrtcTex = PVRTexture.CreateTexture(ms.ToArray(), (uint)_width, (uint)_height, 1, PixelFormat.RGBA8888, false, VariableType.UnsignedByteNorm, ColourSpace.lRGB); pvrtcTex.Transcode((PixelFormat)_format, VariableType.UnsignedByteNorm, ColourSpace.lRGB); byte[] encodedTex = new byte[pvrtcTex.GetTextureDataSize()]; pvrtcTex.GetTextureData(encodedTex, pvrtcTex.GetTextureDataSize()); return(encodedTex); }
public IEnumerable <Color> Load(byte[] tex) { if (_width < 0 || _height < 0) { throw new InvalidDataException("Height and Width has to be set for PVRTC."); } var pvrtcTex = PVRTexture.CreateTexture(tex, (uint)_width, (uint)_height, 1, (PixelFormat)_format, false, VariableType.UnsignedByteNorm, ColourSpace.lRGB); pvrtcTex.Transcode(PixelFormat.RGBA8888, VariableType.UnsignedByteNorm, ColourSpace.lRGB); byte[] decodedTex = new byte[pvrtcTex.GetTextureDataSize()]; pvrtcTex.GetTextureData(decodedTex, pvrtcTex.GetTextureDataSize()); using (var br = new BinaryReaderX(new MemoryStream(decodedTex))) { while (br.BaseStream.Position < br.BaseStream.Length) { var v0 = br.ReadByte(); var v1 = br.ReadByte(); var v2 = br.ReadByte(); var v3 = br.ReadByte(); yield return(Color.FromArgb(v3, v0, v1, v2)); } } }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat sourceFormat; if (!sourceBitmap.TryGetFormat(out sourceFormat)) { return(false); } // A shortcut for copying the entire bitmap to another bitmap of the same type and format if (SurfaceFormat.RgbEtc1 == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion) { SetPixelData(sourceBitmap.GetPixelData()); return(true); } // Destination region copy is not yet supported if (destinationRegion != new Rectangle(0, 0, Width, Height)) { return(false); } // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy if (!(sourceBitmap is PixelBitmapContent <Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height) { try { BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion); return(true); } catch (InvalidOperationException) { return(false); } } // Create the texture object in the PVR library var sourceData = sourceBitmap.GetPixelData(); var rgba32F = (PixelFormat)0x2020202061626772; // static const PixelType PVRStandard32PixelType = PixelType('r', 'g', 'b', 'a', 32, 32, 32, 32); using (var pvrTexture = PVRTexture.CreateTexture(sourceData, (uint)sourceBitmap.Width, (uint)sourceBitmap.Height, 1, rgba32F, true, VariableType.Float, ColourSpace.lRGB)) { // Resize the bitmap if needed if ((sourceBitmap.Width != Width) || (sourceBitmap.Height != Height)) { pvrTexture.Resize((uint)Width, (uint)Height, 1, ResizeMode.Cubic); } pvrTexture.Transcode(PixelFormat.ETC1, VariableType.UnsignedByte, ColourSpace.lRGB /*, CompressorQuality.ETCMediumPerceptual, true*/); var texDataSize = pvrTexture.GetTextureDataSize(0); var texData = new byte[texDataSize]; pvrTexture.GetTextureData(texData, texDataSize); SetPixelData(texData); } return(true); }
/// <summary> /// Exports the specified image. /// </summary> /// <param name="image">The image.</param> /// <param name="libraryData">The library data.</param> /// <param name="export">The export request.</param> private void Export(TexImage image, PvrTextureLibraryData libraryData, ExportRequest request) { Log.Info("Exporting to " + request.FilePath + " ..."); if (request.MinimumMipMapSize > 1) // if a mimimun mipmap size was requested { int newMipMapCount = image.MipmapCount; for (int i = image.MipmapCount - 1; i > 0; --i) // looking for the mipmap level corresponding to the minimum size requeted. { if (libraryData.Header.GetWidth((uint)i) >= request.MinimumMipMapSize || libraryData.Header.GetHeight((uint)i) >= request.MinimumMipMapSize) { break; } --newMipMapCount; } // Creating a new texture corresponding to the requested mipmap levels PVRTextureHeader header = new PVRTextureHeader(RetrieveNativeFormat(image.Format), image.Height, image.Width, image.Depth, newMipMapCount, image.ArraySize, image.FaceCount); PVRTexture texture = new PVRTexture(header, IntPtr.Zero); try { for (uint i = 0; i < image.FaceCount; ++i) { for (uint j = 0; j < image.ArraySize; ++j) { for (uint k = 0; k < newMipMapCount; ++k) { Core.Utilities.CopyMemory(texture.GetDataPtr(k, j, i), libraryData.Texture.GetDataPtr(k, j, i), (int)libraryData.Header.GetDataSize((int)k, false, false)); } } } } catch (AccessViolationException e) { texture.Dispose(); Log.Error("Failed to export texture with the mipmap minimum size request. ", e); throw new TextureToolsException("Failed to export texture with the mipmap minimum size request. ", e); } // Saving the texture into a file and deleting it texture.Save(request.FilePath); texture.Dispose(); } else { libraryData.Texture.Save(request.FilePath); } image.Save(request.FilePath); }
public unsafe static void PvrToPng(string file) { using (var texture = new PVRTexture(file)) { using (var header = texture.GetHeader()) { int width = (int)header.GetWidth(), height = (int)header.GetHeight(); Utilities.Transcode(texture, PixelType.Standard8PixelType, header.GetChannelType(), header.GetColourSpace(), ECompressorQuality.ePVRTCNormal, true); using (Bitmap bitmap = new Bitmap(width, height)) { var bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); var bpp = 32; var bytes_per_line = (width * bpp); var startPoint = (uint *)bitmapData.Scan0; var texturePoint = (uint *)texture.GetDataPtr(); try { for (int line = 0; line < height; line++) { for (int row = 0; row < width; row++) { int index = line * width + row; var src = texturePoint + index; var desc = startPoint + index; var x = *src; //abgr to //argb (*desc) = ((x & 0xFF000000)) | ((x & 0x00FF0000) >> 16) | ((x & 0x0000FF00)) | ((x & 0x000000FF) << 16); } } bitmap.UnlockBits(bitmapData); bitmap.Save(Path.ChangeExtension(file, "png"), ImageFormat.Png); } catch (Exception) { bitmap.UnlockBits(bitmapData); } } } } }
/// <summary> /// Switches the channels R and B. /// </summary> /// <param name="image">The image.</param> /// <param name="libraryData">The library data.</param> /// <param name="request">The request.</param> /// <exception cref="TexLibraryException">Unsuported format for channel switching.</exception> private void SwitchChannels(TexImage image, PvrTextureLibraryData libraryData, SwitchingBRChannelsRequest request) { Log.Info("Switching channels B and R ..."); switch (image.Format) { case SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm: image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm; break; case SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_Typeless: image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_Typeless; break; case SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm_SRgb: image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb; break; case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_Typeless: image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_Typeless; break; case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm: image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm; break; case SiliconStudio.Paradox.Graphics.PixelFormat.R8G8B8A8_UNorm_SRgb: image.Format = SiliconStudio.Paradox.Graphics.PixelFormat.B8G8R8A8_UNorm_SRgb; break; default: Log.Error("Unsuported format for channel switching."); throw new TextureToolsException("Unsuported format for channel switching."); } PVRTexture textureTemp = new PVRTexture(libraryData.Header, libraryData.Texture.GetDataPtr()); EChannelName e1 = EChannelName.eBlue; EChannelName e2 = EChannelName.eRed; Utilities.CopyChannels(libraryData.Texture, textureTemp, 1, out e1, out e2); Utilities.CopyChannels(libraryData.Texture, textureTemp, 1, out e2, out e1); textureTemp.Dispose(); UpdateImage(image, libraryData); }
public IEnumerable <Color> Load(byte[] tex, int taskCount) { var pvrtcTex = PVRTexture.CreateTexture(tex, (uint)_width, (uint)_height, 1, (PixelFormat)_format, false, VariableType.UnsignedByte, ColorSpace.lRGB); pvrtcTex.Transcode(PixelFormat.RGBA8888, VariableType.UnsignedByteNorm, ColorSpace.lRGB); byte[] decodedTex = new byte[pvrtcTex.GetTextureDataSize()]; pvrtcTex.GetTextureData(decodedTex, pvrtcTex.GetTextureDataSize()); using (var br = new BinaryReader(new MemoryStream(decodedTex))) { while (br.BaseStream.Position < br.BaseStream.Length) { var v0 = br.ReadByte(); var v1 = br.ReadByte(); var v2 = br.ReadByte(); var v3 = br.ReadByte(); yield return(Color.FromArgb(v3, v0, v1, v2)); } } }
public byte[] Save(IEnumerable <Color> colors, int taskCount) { var ms = new MemoryStream(); using (var bw = new BinaryWriter(ms, System.Text.Encoding.ASCII, true)) foreach (var color in colors) { bw.Write(color.R); bw.Write(color.G); bw.Write(color.B); bw.Write(color.A); } var pvrtcTex = PVRTexture.CreateTexture(ms.ToArray(), (uint)_width, (uint)_height, 1, PixelFormat.RGBA8888, false, VariableType.UnsignedByteNorm, ColorSpace.lRGB); pvrtcTex.Transcode((PixelFormat)_format, VariableType.UnsignedByteNorm, ColorSpace.lRGB, CompressorQuality.PVRTCHigh); byte[] encodedTex = new byte[pvrtcTex.GetTextureDataSize()]; pvrtcTex.GetTextureData(encodedTex, pvrtcTex.GetTextureDataSize()); return(encodedTex); }
public void Export(string exportFilename) { switch (this.m_TextureFormat) { case 1: case 2: case 3: case 4: case 5: case 7: case 10: case 12: case 13: using (BinaryWriter writer = new BinaryWriter(File.Open(exportFilename, FileMode.Create))) { writer.Write(0x20534444); writer.Write(0x7c); writer.Write(this.dwFlags); writer.Write(this.m_Height); writer.Write(this.m_Width); writer.Write(this.dwPitchOrLinearSize); writer.Write(0); writer.Write(this.dwMipMapCount); writer.Write(new byte[0x2c]); writer.Write(this.dwSize); writer.Write(this.dwFlags2); writer.Write(this.dwFourCC); writer.Write(this.dwRGBBitCount); writer.Write(this.dwRBitMask); writer.Write(this.dwGBitMask); writer.Write(this.dwBBitMask); writer.Write(this.dwABitMask); writer.Write(this.dwCaps); writer.Write(this.dwCaps2); writer.Write(new byte[12]); writer.Write(this.image_data); writer.Close(); } return; case 30: case 0x1f: case 0x20: case 0x21: case 0x22: { using (PVRTextureHeader headerIn = new PVRTextureHeader((ulong)((uint)this.pvrPixelFormat), this.m_Height, this.m_Width, 1, 1, 1, 1, EPVRTColourSpace.ePVRTCSpacelRGB, EPVRTVariableType.ePVRTVarTypeUnsignedByteNorm, false)) { IntPtr destination = Marshal.AllocHGlobal(this.image_data.Length); try { Marshal.Copy(this.image_data, 0, destination, this.image_data.Length); using (PVRTexture sTexture = new PVRTexture(headerIn, destination)) { Utilities.Transcode(sTexture, PixelType.Standard8PixelType, headerIn.GetChannelType(), headerIn.GetColourSpace(), ECompressorQuality.ePVRTCNormal, true); Utilities.Rotate90(sTexture, EPVRTAxis.ePVRTAxisZ, true); Utilities.Rotate90(sTexture, EPVRTAxis.ePVRTAxisZ, true); sTexture.Save(exportFilename); } } catch (Exception ex) { throw ex; } finally { Marshal.FreeHGlobal(destination); } return; } } } using (BinaryWriter writer2 = new BinaryWriter(File.Open(exportFilename, FileMode.Create))) { writer2.Write(this.image_data); writer2.Close(); } }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { if (!sourceBitmap.TryGetFormat(out SurfaceFormat sourceFormat)) { return(false); } TryGetFormat(out SurfaceFormat format); // A shortcut for copying the entire bitmap to another bitmap of the same type and format if (format == sourceFormat && sourceRegion == new Rectangle(0, 0, Width, Height) && sourceRegion == destinationRegion) { SetPixelData(sourceBitmap.GetPixelData()); return(true); } // Destination region copy is not yet supported if (destinationRegion != new Rectangle(0, 0, Width, Height)) { return(false); } // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy if (sourceBitmap is PixelBitmapContent <RgbaVector> && sourceRegion.Width == destinationRegion.Width && sourceRegion.Height == destinationRegion.Height) { PixelFormat targetFormat; switch (format) { case SurfaceFormat.RgbPvrtc2Bpp: targetFormat = PixelFormat.PVRTCI_2bpp_RGB; break; case SurfaceFormat.RgbaPvrtc2Bpp: targetFormat = PixelFormat.PVRTCI_2bpp_RGBA; break; case SurfaceFormat.RgbPvrtc4Bpp: targetFormat = PixelFormat.PVRTCI_4bpp_RGB; break; case SurfaceFormat.RgbaPvrtc4Bpp: targetFormat = PixelFormat.PVRTCI_4bpp_RGBA; break; default: return(false); } // Create the texture object in the PVR library var sourceData = sourceBitmap.GetPixelData(); var rgba32F = (PixelFormat)0x2020202061626772; // static const PixelType PVRStandard32PixelType = PixelType('r', 'g', 'b', 'a', 32, 32, 32, 32); using (var pvrTexture = PVRTexture.CreateTexture( sourceData, (uint)sourceBitmap.Width, (uint)sourceBitmap.Height, 1, rgba32F, true, VariableType.Float, ColourSpace.lRGB)) { // Resize the bitmap if needed if ((sourceBitmap.Width != Width) || (sourceBitmap.Height != Height)) { pvrTexture.Resize((uint)Width, (uint)Height, 1, ResizeMode.Cubic); } // On Linux, anything less than CompressorQuality.PVRTCHigh crashes in libpthread.so at the end of compression pvrTexture.Transcode(targetFormat, VariableType.UnsignedByte, ColourSpace.lRGB, CompressorQuality.PVRTCHigh); var texDataSize = pvrTexture.GetTextureDataSize(0); var texData = new byte[texDataSize]; pvrTexture.GetTextureData(texData, texDataSize); SetPixelData(texData); } return(true); } try { Copy(sourceBitmap, sourceRegion, this, destinationRegion); return(true); } catch (InvalidOperationException) { return(false); } }
public static unsafe bool Decompress(this Texture2DInfo tex, TextureFormat format) { var data = tex.RawData; int width = tex.Width, height = tex.Height, pos, outPos; switch (format) { case TextureFormat.Alpha8: { pos = 0; outPos = 0; var out_ = new byte[width * height * 4]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var fA = pData[pos]; pOut[outPos] = fA; pOut[outPos + 1] = fA; pOut[outPos + 2] = fA; pOut[outPos + 3] = 0xff; pos += 1; outPos += 4; } } tex.RawData = out_; return(true); } case TextureFormat.ARGB4444: { pos = 0; outPos = 0; var out_ = new byte[width * height * 4]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var v0 = pData[pos]; var v1 = pData[pos + 1]; // 4bit little endian {B, G}, {R, A } var fB = v0 & 0xF0 >> 4; var fG = (v0 & 0xF0) >> 4; var fR = v1 & 0xF0 >> 4; var fA = (v1 & 0xF0) >> 4; fA = (fA * 255 + 7) / 15; fR = (fR * 255 + 7) / 15; fG = (fG * 255 + 7) / 15; fB = (fB * 255 + 7) / 15; pOut[outPos] = (byte)fR; pOut[outPos + 1] = (byte)fG; pOut[outPos + 2] = (byte)fB; pOut[outPos + 3] = (byte)fA; pos += 2; outPos += 4; } } tex.RawData = out_; return(true); } case TextureFormat.RGBA4444: { pos = 0; outPos = 0; var out_ = new byte[width * height * 4]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var v0 = pData[pos]; var v1 = pData[pos + 1]; // 4bit little endian {B, G}, {R, A } var fA = v0 & 0xF0 >> 4; var fR = (v0 & 0xF0) >> 4; var fG = v1 & 0xF0 >> 4; var fB = (v1 & 0xF0) >> 4; fA = (fA * 255 + 7) / 15; fR = (fR * 255 + 7) / 15; fG = (fG * 255 + 7) / 15; fB = (fB * 255 + 7) / 15; pOut[outPos] = (byte)fR; pOut[outPos + 1] = (byte)fG; pOut[outPos + 2] = (byte)fB; pOut[outPos + 3] = (byte)fA; pos += 2; outPos += 4; } } tex.RawData = out_; return(true); } case TextureFormat.RGBA32: { pos = 0; outPos = 0; var out_ = new byte[width * height * 4]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var fR = pData[pos]; var fG = pData[pos + 1]; var fB = pData[pos + 2]; var fA = pData[pos + 3]; pOut[outPos] = fR; pOut[outPos + 1] = fG; pOut[outPos + 2] = fB; pOut[outPos + 3] = fA; pos += 4; outPos += 4; } } tex.RawData = out_; return(true); } case TextureFormat.ARGB32: { pos = 0; outPos = 0; var out_ = new byte[width * height * 4]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var fA = pData[pos]; var fR = pData[pos + 1]; var fG = pData[pos + 2]; var fB = pData[pos + 3]; pOut[outPos] = fR; pOut[outPos + 1] = fG; pOut[outPos + 2] = fB; pOut[outPos + 3] = fA; pos += 4; outPos += 4; } } tex.RawData = out_; return(true); } case TextureFormat.RGB24: { pos = 0; outPos = 0; var out_ = new byte[width * height * 4]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var fR = pData[pos]; var fG = pData[pos + 1]; var fB = pData[pos + 2]; pOut[outPos] = fR; pOut[outPos + 1] = fG; pOut[outPos + 2] = fB; pOut[outPos + 3] = 0XFF; pos += 3; outPos += 4; } } tex.RawData = out_; return(true); } case TextureFormat.RGB565: case TextureFormat.ETC2_RGBA8: case TextureFormat.ETC2_RGBA1: case TextureFormat.ETC_RGB4: { PixelFormat format2; switch (format) { case TextureFormat.RGB565: format2 = PixelFormat.RGB565; break; case TextureFormat.ETC2_RGBA8: format2 = PixelFormat.ETC2_RGBA; break; case TextureFormat.ETC2_RGBA1: format2 = PixelFormat.ETC2_RGB_A1; break; case TextureFormat.ETC_RGB4: format2 = PixelFormat.ETC1; break; default: throw new ArgumentOutOfRangeException(nameof(format), format.ToString()); } using (var pvrTexture = PVRTexture.CreateTexture(data, (uint)width, (uint)height, 1, format2, true, VariableType.UnsignedByte, ColourSpace.sRGB)) { pvrTexture.Transcode(PixelFormat.RGBA8888, VariableType.UnsignedByte, ColourSpace.sRGB, CompressorQuality.PVRTCNormal, false); var texDataSize = pvrTexture.GetTextureDataSize(0); var out_ = new byte[texDataSize]; pvrTexture.GetTextureData(out_, texDataSize); tex.RawData = out_; return(true); } } case TextureFormat.DXT1: case TextureFormat.DXT5: { using (var pvrTexture = PVRTexture.CreateTexture(data, (uint)width, (uint)height, 1, format == TextureFormat.DXT1 ? PixelFormat.DXT1 : PixelFormat.DXT5, true, VariableType.UnsignedByte, ColourSpace.sRGB)) { pvrTexture.Transcode(PixelFormat.RGBA8888, VariableType.UnsignedByte, ColourSpace.sRGB, CompressorQuality.PVRTCNormal, false); var texDataSize = pvrTexture.GetTextureDataSize(0); var out_ = new byte[texDataSize]; pvrTexture.GetTextureData(out_, texDataSize); tex.RawData = out_; return(true); } } case TextureFormat.ASTC_RGB_4x4: case TextureFormat.ASTC_RGBA_4x4: AstcencWrapper.DecodeASTC(data, width, height, 4, 4, out tex.RawData); return(true); default: throw new ArgumentOutOfRangeException(nameof(format), format.ToString()); } }
public static unsafe bool Compress(this Texture2DInfo tex, TextureFormat format) { var data = tex.RawData; int width = tex.Width, height = tex.Height, pos, outPos; switch (format) { case TextureFormat.Alpha8: { pos = 0; outPos = 0; var out_ = new byte[width * height]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var fR = pData[pos]; var fG = pData[pos + 1]; var fB = pData[pos + 2]; var fA = pData[pos + 3]; pOut[outPos] = (byte)(((fR + fB + fG) / 3) & 0XFF); pos += 4; outPos += 1; } } tex.RawData = out_; return(true); } case TextureFormat.ARGB4444: case TextureFormat.RGB565: { pos = 0; outPos = 0; using (var pvrTexture = PVRTexture.CreateTexture(data, (uint)width, (uint)height, 1, PixelFormat.RGBA8888, true, VariableType.UnsignedByte, ColourSpace.sRGB)) { var doDither = true; pvrTexture.Transcode(PixelFormat.RGBA4444, VariableType.UnsignedByte, ColourSpace.sRGB, format == TextureFormat.ARGB4444 ? CompressorQuality.PVRTCNormal : CompressorQuality.ETCMedium, doDither); var texDataSize = pvrTexture.GetTextureDataSize(0); var out_ = new byte[texDataSize]; pvrTexture.GetTextureData(out_, texDataSize); if (format == TextureFormat.RGB565) { var data2 = out_; out_ = new byte[texDataSize]; fixed(byte *pOut = out_, pData = data2) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var v0 = pData[pos]; var v1 = pData[pos + 1]; // 4bit little endian {A, B},{G, R} var sA = v0 & 0xF0 >> 4; var sB = (v0 & 0xF0) >> 4; var sG = v1 & 0xF0 >> 4; var sR = (v1 & 0xF0) >> 4; // swap to little endian {B, G, R, A } var fB = sB & 0xf; var fG = sG & 0xf; var fR = sR & 0xf; var fA = sA & 0xf; pOut[outPos] = (byte)((fG << 4) + fB); pOut[outPos + 1] = (byte)((fA << 4) + fR); pos += 2; outPos += 2; } } } tex.RawData = out_; return(true); } } case TextureFormat.RGB24: { pos = 0; outPos = 0; var out_ = new byte[width * height * 3]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { // 4bit little endian {A, B},{G, R} var fR = pData[pos]; var fG = pData[pos + 1]; var fB = pData[pos + 2]; var fA = pData[pos + 3]; pOut[outPos] = fR; pOut[outPos + 1] = fG; pOut[outPos + 2] = fB; pos += 4; outPos += 3; } } tex.RawData = out_; return(true); } case TextureFormat.RGBA32: return(true); case TextureFormat.ARGB32: { pos = 0; outPos = 0; var out_ = new byte[width * height * 4]; fixed(byte *pOut = out_, pData = data) for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var fA = pData[pos]; var fR = pData[pos + 1]; var fG = pData[pos + 2]; var fB = pData[pos + 3]; out_[outPos] = fR; out_[outPos + 1] = fG; out_[outPos + 2] = fB; out_[outPos + 3] = fA; pos += 4; outPos += 4; } } tex.RawData = out_; return(true); } //case TextureFormat.ATC_RGBA8: //case TextureFormat.ATC_RGB4: case TextureFormat.ETC2_RGBA8: case TextureFormat.ETC_RGB4: TextureConverterWrapper.CompressionFormat format2; switch (format) { //case TextureFormat.ATC_RGBA8: format2 = TextureConverterWrapper.CompressionFormat.AtcRgbaExplicitAlpha; break; //case TextureFormat.ATC_RGB4: format2 = TextureConverterWrapper.CompressionFormat.AtcRgb; break; case TextureFormat.ETC2_RGBA8: format2 = TextureConverterWrapper.CompressionFormat.Etc2Rgba; break; case TextureFormat.ETC_RGB4: format2 = TextureConverterWrapper.CompressionFormat.Etc1; break; default: throw new ArgumentOutOfRangeException(nameof(format), format.ToString()); } tex.RawData = TextureConverterWrapper.Compress(data, width, height, format2); return(true); case TextureFormat.DXT1: case TextureFormat.DXT5: { var dxtCompressor = new Compressor(); var inputOptions = new InputOptions(); inputOptions.SetAlphaMode(format == TextureFormat.DXT1 ? AlphaMode.None : AlphaMode.Premultiplied); inputOptions.SetTextureLayout(TextureType.Texture2D, width, height, 1); fixed(byte *pData = data) for (var x = 0; x < data.Length; x += 4) { pData[x] ^= pData[x + 2]; pData[x + 2] ^= pData[x]; pData[x] ^= pData[x + 2]; } var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var dataPtr = dataHandle.AddrOfPinnedObject(); inputOptions.SetMipmapData(dataPtr, width, height, 1, 0, 0); inputOptions.SetMipmapGeneration(false); inputOptions.SetGamma(1.0f, 1.0f); var compressionOptions = new CompressionOptions(); compressionOptions.SetFormat(format == TextureFormat.DXT1 ? Nvidia.TextureTools.Format.DXT1 : Nvidia.TextureTools.Format.DXT5); compressionOptions.SetQuality(Quality.Normal); var outputOptions = new OutputOptions(); outputOptions.SetOutputHeader(false); var out_ = new byte[0]; using (var handler = new DxtDataHandler(out_, outputOptions)) { dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions); out_ = handler.dst; } tex.RawData = out_; return(true); } finally { dataHandle.Free(); } } case TextureFormat.ASTC_RGBA_4x4: case TextureFormat.ASTC_RGB_4x4: AstcencWrapper.EncodeASTC(data, width, height, 4, 4, out tex.RawData); return(true); default: throw new ArgumentOutOfRangeException(nameof(format), format.ToString()); } }