예제 #1
0
        /// <summary>
        /// Encodes all cubemap faces and mipmap levels into a Ktx file.
        /// Order is +X, -X, +Y, -Y, +Z, -Z. Back maps to positive Z and front to negative Z.
        /// </summary>
        public KtxFile EncodeCubeMapToKtx(Image <Rgba32> right, Image <Rgba32> left, Image <Rgba32> top, Image <Rgba32> down,
                                          Image <Rgba32> back, Image <Rgba32> front)
        {
            KtxFile         output;
            IBcBlockEncoder compressedEncoder   = null;
            IRawEncoder     uncompressedEncoder = null;

            if (right.Width != left.Width || right.Width != top.Width || right.Width != down.Width ||
                right.Width != back.Width || right.Width != front.Width ||
                right.Height != left.Height || right.Height != top.Height || right.Height != down.Height ||
                right.Height != back.Height || right.Height != front.Height)
            {
                throw new ArgumentException("All input images of a cubemap should be the same size.");
            }

            Image <Rgba32>[] faces = new[] { right, left, top, down, back, front };

            if (OutputOptions.format.IsCompressedFormat())
            {
                compressedEncoder = GetEncoder(OutputOptions.format);
                if (compressedEncoder == null)
                {
                    throw new NotSupportedException($"This format is not supported: {OutputOptions.format}");
                }
                output = new KtxFile(
                    KtxHeader.InitializeCompressed(right.Width, right.Height,
                                                   compressedEncoder.GetInternalFormat(),
                                                   compressedEncoder.GetBaseInternalFormat()));
            }
            else
            {
                uncompressedEncoder = GetRawEncoder(OutputOptions.format);
                output = new KtxFile(
                    KtxHeader.InitializeUncompressed(right.Width, right.Height,
                                                     uncompressedEncoder.GetGlType(),
                                                     uncompressedEncoder.GetGlFormat(),
                                                     uncompressedEncoder.GetGlTypeSize(),
                                                     uncompressedEncoder.GetInternalFormat(),
                                                     uncompressedEncoder.GetBaseInternalFormat()));
            }
            uint numMipMaps = (uint)OutputOptions.maxMipMapLevel;

            if (!OutputOptions.generateMipMaps)
            {
                numMipMaps = 1;
            }

            uint mipLength = MipMapper.CalculateMipChainLength(right.Width, right.Height, numMipMaps);

            for (uint i = 0; i < mipLength; i++)
            {
                output.MipMaps.Add(new KtxMipmap(0, 0, 0, (uint)faces.Length));
            }

            for (int f = 0; f < faces.Length; f++)
            {
                var mipChain = MipMapper.GenerateMipChain(faces[f], ref numMipMaps);

                for (int i = 0; i < numMipMaps; i++)
                {
                    byte[] encoded = null;
                    if (OutputOptions.format.IsCompressedFormat())
                    {
                        var blocks = ImageToBlocks.ImageTo4X4(mipChain[i].Frames[0], out int blocksWidth, out int blocksHeight);
                        encoded = compressedEncoder.Encode(blocks, blocksWidth, blocksHeight, OutputOptions.quality,
                                                           !Debugger.IsAttached && Options.multiThreaded);
                    }
                    else
                    {
                        encoded = uncompressedEncoder.Encode(mipChain[i].GetPixelSpan());
                    }

                    if (f == 0)
                    {
                        output.MipMaps[i] = new KtxMipmap((uint)encoded.Length,
                                                          (uint)mipChain[i].Width,
                                                          (uint)mipChain[i].Height, (uint)faces.Length);
                    }

                    output.MipMaps[i].Faces[f] = new KtxMipFace(encoded,
                                                                (uint)mipChain[i].Width,
                                                                (uint)mipChain[i].Height);
                }

                foreach (var image in mipChain)
                {
                    image.Dispose();
                }
            }

            output.Header.NumberOfFaces        = (uint)faces.Length;
            output.Header.NumberOfMipmapLevels = mipLength;

            return(output);
        }
예제 #2
0
        /// <summary>
        /// Encodes all mipmap levels into a Ktx file.
        /// </summary>
        public KtxFile EncodeToKtx(Image <Rgba32> inputImage)
        {
            KtxFile         output;
            IBcBlockEncoder compressedEncoder   = null;
            IRawEncoder     uncompressedEncoder = null;

            if (OutputOptions.format.IsCompressedFormat())
            {
                compressedEncoder = GetEncoder(OutputOptions.format);
                if (compressedEncoder == null)
                {
                    throw new NotSupportedException($"This format is not supported: {OutputOptions.format}");
                }
                output = new KtxFile(
                    KtxHeader.InitializeCompressed(inputImage.Width, inputImage.Height,
                                                   compressedEncoder.GetInternalFormat(),
                                                   compressedEncoder.GetBaseInternalFormat()));
            }
            else
            {
                uncompressedEncoder = GetRawEncoder(OutputOptions.format);
                output = new KtxFile(
                    KtxHeader.InitializeUncompressed(inputImage.Width, inputImage.Height,
                                                     uncompressedEncoder.GetGlType(),
                                                     uncompressedEncoder.GetGlFormat(),
                                                     uncompressedEncoder.GetGlTypeSize(),
                                                     uncompressedEncoder.GetInternalFormat(),
                                                     uncompressedEncoder.GetBaseInternalFormat()));
            }

            uint numMipMaps = (uint)OutputOptions.maxMipMapLevel;

            if (!OutputOptions.generateMipMaps)
            {
                numMipMaps = 1;
            }

            var mipChain = MipMapper.GenerateMipChain(inputImage, ref numMipMaps);

            for (int i = 0; i < numMipMaps; i++)
            {
                byte[] encoded = null;
                if (OutputOptions.format.IsCompressedFormat())
                {
                    var blocks = ImageToBlocks.ImageTo4X4(mipChain[i].Frames[0], out int blocksWidth, out int blocksHeight);
                    encoded = compressedEncoder.Encode(blocks, blocksWidth, blocksHeight, OutputOptions.quality,
                                                       !Debugger.IsAttached && Options.multiThreaded);
                }
                else
                {
                    encoded = uncompressedEncoder.Encode(mipChain[i].GetPixelSpan());
                }

                output.MipMaps.Add(new KtxMipmap((uint)encoded.Length,
                                                 (uint)inputImage.Width,
                                                 (uint)inputImage.Height, 1));
                output.MipMaps[i].Faces[0] = new KtxMipFace(encoded,
                                                            (uint)inputImage.Width,
                                                            (uint)inputImage.Height);
            }

            foreach (var image in mipChain)
            {
                image.Dispose();
            }

            output.Header.NumberOfFaces        = 1;
            output.Header.NumberOfMipmapLevels = numMipMaps;

            return(output);
        }