Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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));
                }
            }
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        /// <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);
        }
Esempio n. 5
0
 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);
                 }
             }
         }
     }
 }
Esempio n. 6
0
        /// <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);
        }
Esempio n. 7
0
        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));
                }
            }
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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);
            }
        }
Esempio n. 11
0
        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());
            }
        }
Esempio n. 12
0
        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());
            }
        }