Beispiel #1
0
        /// <summary>
        /// Encodes all cubemap faces and mipmap levels into a Dds file.
        /// Order is +X, -X, +Y, -Y, +Z, -Z. Back maps to positive Z and front to negative Z.
        /// </summary>
        public DdsFile EncodeCubeMapToDds(Image <Rgba32> right, Image <Rgba32> left, Image <Rgba32> top, Image <Rgba32> down,
                                          Image <Rgba32> back, Image <Rgba32> front)
        {
            DdsFile         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}");
                }

                var(ddsHeader, dxt10Header) = DdsHeader.InitializeCompressed(right.Width, right.Height,
                                                                             compressedEncoder.GetDxgiFormat());
                output = new DdsFile(ddsHeader, dxt10Header);

                if (OutputOptions.ddsBc1WriteAlphaFlag &&
                    OutputOptions.format == CompressionFormat.BC1WithAlpha)
                {
                    output.Header.ddsPixelFormat.dwFlags |= PixelFormatFlags.DDPF_ALPHAPIXELS;
                }
            }
            else
            {
                uncompressedEncoder = GetRawEncoder(OutputOptions.format);
                var ddsHeader = DdsHeader.InitializeUncompressed(right.Width, right.Height,
                                                                 uncompressedEncoder.GetDxgiFormat());
                output = new DdsFile(ddsHeader);
            }

            uint numMipMaps = (uint)OutputOptions.maxMipMapLevel;

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

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


                for (int mip = 0; mip < numMipMaps; mip++)
                {
                    byte[] encoded = null;
                    if (OutputOptions.format.IsCompressedFormat())
                    {
                        var blocks = ImageToBlocks.ImageTo4X4(mipChain[mip].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[mip].GetPixelSpan());
                    }

                    if (mip == 0)
                    {
                        output.Faces.Add(new DdsFace((uint)mipChain[mip].Width, (uint)mipChain[mip].Height,
                                                     (uint)encoded.Length, mipChain.Count));
                    }

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

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

            output.Header.dwCaps       |= HeaderCaps.DDSCAPS_COMPLEX;
            output.Header.dwMipMapCount = numMipMaps;
            if (numMipMaps > 1)
            {
                output.Header.dwCaps |= HeaderCaps.DDSCAPS_MIPMAP;
            }
            output.Header.dwCaps2 |= HeaderCaps2.DDSCAPS2_CUBEMAP |
                                     HeaderCaps2.DDSCAPS2_CUBEMAP_POSITIVEX |
                                     HeaderCaps2.DDSCAPS2_CUBEMAP_NEGATIVEX |
                                     HeaderCaps2.DDSCAPS2_CUBEMAP_POSITIVEY |
                                     HeaderCaps2.DDSCAPS2_CUBEMAP_NEGATIVEY |
                                     HeaderCaps2.DDSCAPS2_CUBEMAP_POSITIVEZ |
                                     HeaderCaps2.DDSCAPS2_CUBEMAP_NEGATIVEZ;

            return(output);
        }
Beispiel #2
0
        /// <summary>
        /// Encodes all mipmap levels into a Ktx file.
        /// </summary>
        public DdsFile EncodeToDds(Image <Rgba32> inputImage)
        {
            DdsFile         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}");
                }

                var(ddsHeader, dxt10Header) = DdsHeader.InitializeCompressed(inputImage.Width, inputImage.Height,
                                                                             compressedEncoder.GetDxgiFormat());
                output = new DdsFile(ddsHeader, dxt10Header);

                if (OutputOptions.ddsBc1WriteAlphaFlag &&
                    OutputOptions.format == CompressionFormat.BC1WithAlpha)
                {
                    output.Header.ddsPixelFormat.dwFlags |= PixelFormatFlags.DDPF_ALPHAPIXELS;
                }
            }
            else
            {
                uncompressedEncoder = GetRawEncoder(OutputOptions.format);
                var ddsHeader = DdsHeader.InitializeUncompressed(inputImage.Width, inputImage.Height,
                                                                 uncompressedEncoder.GetDxgiFormat());
                output = new DdsFile(ddsHeader);
            }

            uint numMipMaps = (uint)OutputOptions.maxMipMapLevel;

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

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

            for (int mip = 0; mip < numMipMaps; mip++)
            {
                byte[] encoded = null;
                if (OutputOptions.format.IsCompressedFormat())
                {
                    var blocks = ImageToBlocks.ImageTo4X4(mipChain[mip].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[mip].GetPixelSpan());
                }

                if (mip == 0)
                {
                    output.Faces.Add(new DdsFace((uint)inputImage.Width, (uint)inputImage.Height,
                                                 (uint)encoded.Length, (int)numMipMaps));
                }

                output.Faces[0].MipMaps[mip] = new DdsMipMap(encoded,
                                                             (uint)inputImage.Width,
                                                             (uint)inputImage.Height);
            }

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

            output.Header.dwMipMapCount = numMipMaps;
            if (numMipMaps > 1)
            {
                output.Header.dwCaps |= HeaderCaps.DDSCAPS_COMPLEX | HeaderCaps.DDSCAPS_MIPMAP;
            }

            return(output);
        }