Beispiel #1
0
        //-------------------------------------------------------------------------------------
        // Encodes a single frame
        //-------------------------------------------------------------------------------------
        private static void EncodeImage(PixelBuffer image, WICFlags flags, WIC.BitmapFrameEncode frame)
        {
            Guid pfGuid;

            if (!ToWIC(image.Format, out pfGuid))
            {
                throw new NotSupportedException("Format not supported");
            }

            frame.Initialize();
            frame.SetSize(image.Width, image.Height);
            frame.SetResolution(72, 72);
            Guid targetGuid = pfGuid;

            frame.SetPixelFormat(ref targetGuid);

            if (targetGuid != pfGuid)
            {
                using (var source = new WIC.Bitmap(Factory, image.Width, image.Height, pfGuid, new SDX.DataRectangle(image.DataPointer, image.RowStride), image.BufferStride))
                {
                    using (var converter = new WIC.FormatConverter(Factory))
                    {
                        using (var palette = new WIC.Palette(Factory))
                        {
                            palette.Initialize(source, 256, true);
                            converter.Initialize(source, targetGuid, GetWICDither(flags), palette, 0, WIC.BitmapPaletteType.Custom);

                            int bpp = GetBitsPerPixel(targetGuid);
                            if (bpp == 0)
                            {
                                throw new NotSupportedException("Unable to determine the Bpp for the target format");
                            }

                            int rowPitch   = (image.Width * bpp + 7) / 8;
                            int slicePitch = rowPitch * image.Height;

                            var temp = SDX.Utilities.AllocateMemory(slicePitch);
                            try
                            {
                                converter.CopyPixels(rowPitch, temp, slicePitch);
                                frame.Palette = palette;
                                frame.WritePixels(image.Height, temp, rowPitch, slicePitch);
                            }
                            finally
                            {
                                SDX.Utilities.FreeMemory(temp);
                            }
                        }
                    }
                }
            }
            else
            {
                // No conversion required
                frame.WritePixels(image.Height, image.DataPointer, image.RowStride, image.BufferStride);
            }

            frame.Commit();
        }
        private Result SaveWICTextureToFileFix(
            DeviceContext context,
            Texture2D source,
            ref Guid guidContainerFormat,
            string fileName)
        {
            if (fileName == null)
            {
                return(Result.InvalidArg);
            }

            Result res = CaptureTextureFix(context, source, out Texture2DDescription desc, out Texture2D staging);

            if (res.Failure)
            {
                return(res);
            }

            Guid pfGuid;
            //bool sRGB = false;
            Guid targetGuid;

            switch (desc.Format)
            {
            case DXGI.Format.R32G32B32A32_Float: pfGuid = WIC.PixelFormat.Format128bppRGBAFloat; break;

            case DXGI.Format.R16G16B16A16_Float: pfGuid = WIC.PixelFormat.Format64bppRGBAHalf; break;

            case DXGI.Format.R16G16B16A16_UNorm: pfGuid = WIC.PixelFormat.Format64bppRGBA; break;

            case DXGI.Format.R10G10B10_Xr_Bias_A2_UNorm: pfGuid = WIC.PixelFormat.Format32bppRGBA1010102XR; break;     // DXGI 1.1

            case DXGI.Format.R10G10B10A2_UNorm: pfGuid = WIC.PixelFormat.Format32bppRGBA1010102; break;

            case DXGI.Format.B5G5R5A1_UNorm: pfGuid = WIC.PixelFormat.Format16bppBGRA5551; break;

            case DXGI.Format.B5G6R5_UNorm: pfGuid = WIC.PixelFormat.Format16bppBGR565; break;

            case DXGI.Format.R32_Float: pfGuid = WIC.PixelFormat.Format32bppGrayFloat; break;

            case DXGI.Format.R16_Float: pfGuid = WIC.PixelFormat.Format16bppGrayHalf; break;

            case DXGI.Format.R16_UNorm: pfGuid = WIC.PixelFormat.Format16bppGray; break;

            case DXGI.Format.R8_UNorm: pfGuid = WIC.PixelFormat.Format8bppGray; break;

            case DXGI.Format.A8_UNorm: pfGuid = WIC.PixelFormat.Format8bppAlpha; break;

            case DXGI.Format.R8G8B8A8_UNorm:
                pfGuid = WIC.PixelFormat.Format32bppRGBA;
                break;

            case DXGI.Format.R8G8B8A8_UNorm_SRgb:
                pfGuid = WIC.PixelFormat.Format32bppRGBA;
                //sRGB = true;
                break;

            case DXGI.Format.B8G8R8A8_UNorm:     // DXGI 1.1
                pfGuid = WIC.PixelFormat.Format32bppBGRA;
                break;

            case DXGI.Format.B8G8R8A8_UNorm_SRgb:     // DXGI 1.1
                pfGuid = WIC.PixelFormat.Format32bppBGRA;
                //sRGB = true;
                break;

            case DXGI.Format.B8G8R8X8_UNorm:     // DXGI 1.1
                pfGuid = WIC.PixelFormat.Format32bppBGR;
                break;

            case DXGI.Format.B8G8R8X8_UNorm_SRgb:     // DXGI 1.1
                pfGuid = WIC.PixelFormat.Format32bppBGR;
                //sRGB = true;
                break;

            default:
                return(Result.GetResultFromWin32Error(unchecked ((int)0x80070032)));
            }

            // Create file
            FileStream fs = new FileStream(fileName, FileMode.Create);

            WIC.BitmapEncoder encoder = new WIC.BitmapEncoder(DirectX.ImageFactory, guidContainerFormat);
            encoder.Initialize(fs);


            WIC.BitmapFrameEncode frameEncode = new WIC.BitmapFrameEncode(encoder);
            frameEncode.Initialize();
            frameEncode.SetSize(desc.Width, desc.Height);
            frameEncode.SetResolution(72.0, 72.0);


            switch (desc.Format)
            {
            case DXGI.Format.R32G32B32A32_Float:
            case DXGI.Format.R16G16B16A16_Float:
                targetGuid = WIC.PixelFormat.Format24bppBGR;
                break;

            case DXGI.Format.R16G16B16A16_UNorm: targetGuid = WIC.PixelFormat.Format48bppBGR; break;

            case DXGI.Format.B5G5R5A1_UNorm: targetGuid = WIC.PixelFormat.Format16bppBGR555; break;

            case DXGI.Format.B5G6R5_UNorm: targetGuid = WIC.PixelFormat.Format16bppBGR565; break;

            case DXGI.Format.R32_Float:
            case DXGI.Format.R16_Float:
            case DXGI.Format.R16_UNorm:
            case DXGI.Format.R8_UNorm:
            case DXGI.Format.A8_UNorm:
                targetGuid = WIC.PixelFormat.Format8bppGray;
                break;

            default:
                targetGuid = WIC.PixelFormat.Format24bppBGR;
                break;
            }

            frameEncode.SetPixelFormat(ref targetGuid);

            #region Write

            DataBox db = context.MapSubresource(staging, 0, MapMode.Read, MapFlags.None, out DataStream stream);

            if (pfGuid != targetGuid)
            {
                WIC.FormatConverter formatCoverter = new WIC.FormatConverter(DirectX.ImageFactory);

                if (formatCoverter.CanConvert(pfGuid, targetGuid))
                {
                    WIC.Bitmap src = new WIC.Bitmap(DirectX.ImageFactory, desc.Width, desc.Height, pfGuid,
                                                    new DataRectangle(db.DataPointer, db.RowPitch));

                    formatCoverter.Initialize(src, targetGuid, SharpDX.WIC.BitmapDitherType.None, null, 0, SharpDX.WIC.BitmapPaletteType.Custom);

                    frameEncode.WriteSource(formatCoverter, new Rectangle(0, 0, desc.Width, desc.Height));
                }
            }
            else
            {
                frameEncode.WritePixels(desc.Height, new DataRectangle(db.DataPointer, db.RowPitch));
            }

            context.UnmapSubresource(staging, 0);

            frameEncode.Commit();
            encoder.Commit();

            #endregion

            frameEncode.Dispose();
            encoder.Dispose();

            fs.Close();

            return(Result.Ok);
        }