public static unsafe Document Load(Stream input)
        {
            Document doc = null;

            using (DdsNative.DdsImage image = DdsNative.Load(input))
            {
                doc = new Document(image.Width, image.Height);

                BitmapLayer layer = Layer.CreateBackgroundLayer(image.Width, image.Height);

                Surface surface = layer.Surface;

                for (int y = 0; y < surface.Height; ++y)
                {
                    byte *     src = image.GetRowAddressUnchecked(y);
                    ColorBgra *dst = surface.GetRowAddressUnchecked(y);

                    for (int x = 0; x < surface.Width; ++x)
                    {
                        dst->R = src[0];
                        dst->G = src[1];
                        dst->B = src[2];
                        dst->A = src[3];

                        src += 4;
                        ++dst;
                    }
                }

                doc.Layers.Add(layer);
            }

            return(doc);
        }
        public static void Save(
            IServiceProvider services,
            Document input,
            Stream output,
            DdsFileFormat format,
            DdsErrorMetric errorMetric,
            BC7CompressionMode compressionMode,
            bool cubeMap,
            bool generateMipmaps,
            ResamplingAlgorithm sampling,
            Surface scratchSurface,
            ProgressEventHandler progressCallback)
        {
            using (RenderArgs args = new RenderArgs(scratchSurface))
            {
                input.Render(args, true);
            }

            DdsNative.DdsProgressCallback ddsProgress = null;
            if (progressCallback != null)
            {
                ddsProgress = (UIntPtr done, UIntPtr total) =>
                {
                    double progress = (double)done.ToUInt64() / (double)total.ToUInt64();
                    try
                    {
                        progressCallback(null, new ProgressEventArgs(progress * 100.0, true));
                        return(true);
                    }
                    catch (OperationCanceledException)
                    {
                        return(false);
                    }
                };
            }

            int  width           = scratchSurface.Width;
            int  height          = scratchSurface.Height;
            int  arraySize       = 1;
            Size?cubeMapFaceSize = null;

            if (cubeMap && IsCrossedCubeMapSize(scratchSurface))
            {
                if (width > height)
                {
                    width  /= 4;
                    height /= 3;
                }
                else
                {
                    width  /= 3;
                    height /= 4;
                }
                arraySize       = 6;
                cubeMapFaceSize = new Size(width, height);
            }

            int  mipLevels = generateMipmaps ? GetMipCount(width, height) : 1;
            bool enableHardwareAcceleration = (bool)services.GetService <ISettingsService>().GetSetting(AppSettingPaths.UI.EnableHardwareAcceleration).Value;

            DdsNative.DDSSaveInfo info = new DdsNative.DDSSaveInfo
            {
                width                      = width,
                height                     = height,
                arraySize                  = arraySize,
                mipLevels                  = mipLevels,
                format                     = format,
                errorMetric                = errorMetric,
                compressionMode            = compressionMode,
                cubeMap                    = cubeMapFaceSize.HasValue,
                enableHardwareAcceleration = enableHardwareAcceleration
            };

            using (TextureCollection textures = GetTextures(scratchSurface, cubeMapFaceSize, mipLevels, sampling))
            {
                DdsNative.Save(info, textures, output, ddsProgress);
            }
        }