Пример #1
0
        private static void EncodeImage(ImagingFactory imagingFactory, Image image, WicFlags flags, Guid containerFormat, BitmapFrameEncode frame)
        {
            Guid pfGuid = ToWic(image.Format, false);

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

              EncodeMetadata(frame, containerFormat, image.Format);

              if (targetGuid != pfGuid)
              {
            // Conversion required to write.
            GCHandle handle = GCHandle.Alloc(image.Data, GCHandleType.Pinned);
            using (var source = new Bitmap(imagingFactory, image.Width, image.Height, pfGuid, new DataRectangle(handle.AddrOfPinnedObject(), image.RowPitch), image.Data.Length))
            {
              using (var converter = new FormatConverter(imagingFactory))
              {
            if (!converter.CanConvert(pfGuid, targetGuid))
              throw new NotSupportedException("Format conversion is not supported.");

            converter.Initialize(source, targetGuid, GetWicDither(flags), null, 0, BitmapPaletteType.Custom);
            frame.WriteSource(converter, new Rectangle(0, 0, image.Width, image.Height));
              }
            }

            handle.Free();
              }
              else
              {
            // No conversion required.
            frame.WritePixels(image.Height, image.RowPitch, image.Data);
              }

              frame.Commit();
        }
Пример #2
0
        /// <summary>
        /// Function to perform conversion/transformation of a bitmap.
        /// </summary>
        /// <param name="sourceData">WIC bitmap to transform.</param>
        /// <param name="destData">Destination data buffer.</param>
        /// <param name="rowPitch">Number of bytes per row in the image.</param>
        /// <param name="slicePitch">Number of bytes in total for the image.</param>
        /// <param name="destFormat">Destination format for transformation.</param>
        /// <param name="isSourcesRGB">TRUE if the source format is sRGB.</param>
        /// <param name="isDestsRGB">TRUE if the destination format is sRGB.</param>
        /// <param name="dither">Dithering to apply to images that get converted to a lower bit depth.</param>
        /// <param name="destRect">Rectangle containing the area to scale or clip</param>
        /// <param name="clip">TRUE to perform clipping instead of scaling.</param>
        /// <param name="scaleFilter">Filter to apply to scaled data.</param>
        public void TransformImageData(WIC.BitmapSource sourceData, IntPtr destData, int rowPitch, int slicePitch, Guid destFormat, bool isSourcesRGB, bool isDestsRGB, ImageDithering dither, Rectangle destRect, bool clip, ImageFilter scaleFilter)
        {
            WIC.BitmapSource    source        = sourceData;
            WIC.FormatConverter converter     = null;
            WIC.BitmapClipper   clipper       = null;
            WIC.BitmapScaler    scaler        = null;
            WIC.ColorContext    sourceContext = null;
            WIC.ColorContext    destContext   = null;
            WIC.ColorTransform  sRGBTransform = null;

            try
            {
                if (destFormat != Guid.Empty)
                {
                    if (sourceData.PixelFormat != destFormat)
                    {
                        converter = new WIC.FormatConverter(Factory);

                        if (!converter.CanConvert(sourceData.PixelFormat, destFormat))
                        {
                            throw new GorgonException(GorgonResult.FormatNotSupported,
                                                      string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, destFormat));
                        }

                        converter.Initialize(source, destFormat, (WIC.BitmapDitherType)dither, null, 0, WIC.BitmapPaletteType.Custom);
                        source = converter;
                    }

                    if ((isDestsRGB) ||
                        (isSourcesRGB))
                    {
                        sRGBTransform = new WIC.ColorTransform(Factory);
                        sourceContext = new WIC.ColorContext(Factory);
                        destContext   = new WIC.ColorContext(Factory);

                        sourceContext.InitializeFromExifColorSpace(isSourcesRGB ? 1 : 2);
                        destContext.InitializeFromExifColorSpace(isDestsRGB ? 1 : 2);

                        sRGBTransform.Initialize(source, sourceContext, destContext, destFormat);
                        source = sRGBTransform;
                    }
                }

                if (destRect.IsEmpty)
                {
                    source.CopyPixels(rowPitch, destData, slicePitch);
                    return;
                }

                Guid pixelFormat = source.PixelFormat;

                if (!clip)
                {
                    scaler = new WIC.BitmapScaler(Factory);
                    scaler.Initialize(source,
                                      destRect.Width,
                                      destRect.Height,
                                      (WIC.BitmapInterpolationMode)scaleFilter);
                    source = scaler;
                }
                else
                {
                    destRect.Width  = destRect.Width.Min(source.Size.Width);
                    destRect.Height = destRect.Height.Min(source.Size.Height);

                    if ((destRect.Width < source.Size.Width) ||
                        (destRect.Height < source.Size.Height))
                    {
                        clipper = new WIC.BitmapClipper(Factory);
                        clipper.Initialize(source,
                                           new DX.Rectangle(destRect.X, destRect.Y, destRect.Width, destRect.Height));
                        source     = clipper;
                        destRect.X = 0;
                        destRect.Y = 0;
                    }
                }

                // We have a change of format (probably due to the filter when scaling)... so we need to convert.
                if (source.PixelFormat != pixelFormat)
                {
                    converter = new WIC.FormatConverter(Factory);

                    if (!converter.CanConvert(source.PixelFormat, pixelFormat))
                    {
                        throw new GorgonException(GorgonResult.FormatNotSupported,
                                                  string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, pixelFormat));
                    }

                    converter.Initialize(source,
                                         pixelFormat,
                                         WIC.BitmapDitherType.None,
                                         null,
                                         0,
                                         WIC.BitmapPaletteType.Custom);
                    source = converter;
                }

                source.CopyPixels(rowPitch, destData, slicePitch);
            }
            finally
            {
                if (converter != null)
                {
                    converter.Dispose();
                }

                if (sourceContext != null)
                {
                    sourceContext.Dispose();
                }

                if (destContext != null)
                {
                    destContext.Dispose();
                }

                if (sRGBTransform != null)
                {
                    sRGBTransform.Dispose();
                }

                if (scaler != null)
                {
                    scaler.Dispose();
                }

                if (clipper != null)
                {
                    clipper.Dispose();
                }
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        /// <summary>
        /// Function to convert the format of a bitmap into the format of the buffer.
        /// </summary>
        /// <param name="sourceFormat">Format to convert from.</param>
        /// <param name="destFormat">Format to convert into.</param>
        /// <param name="dithering">Dithering to apply.</param>
        /// <param name="filter">Filtering to apply to scaled bitmaps.</param>
        /// <param name="bitmap">Bitmap to convert.</param>
        /// <param name="bitmapPalette">Palette for the bitmap.</param>
        /// <param name="alphaValue">Value of pixel to consider transparent.</param>
        /// <param name="buffer">Buffer holding the converted data.</param>
        /// <param name="scale">TRUE to scale when converting, FALSE to keep at original size.</param>
        /// <param name="clip">TRUE to perform clipping, FALSE to keep at original size.</param>
        private void ConvertFormat(Guid sourceFormat, Guid destFormat, WIC.BitmapDitherType dithering,
                                   WIC.BitmapInterpolationMode filter, WIC.BitmapSource bitmap,
                                   WIC.Palette bitmapPalette, int alphaValue,
                                   GorgonImageBuffer buffer, bool scale, bool clip)
        {
            WIC.BitmapSource source       = bitmap;
            double           alphaPercent = alphaValue / 255.0;
            var paletteType = WIC.BitmapPaletteType.Custom;

            // If we have a palette, then confirm that the dithering method is valid.
            if (bitmapPalette != null)
            {
                // Do not apply dithering if we're using
                // a custom palette and request ordered dithering.
                switch (dithering)
                {
                case WIC.BitmapDitherType.Ordered4x4:
                case WIC.BitmapDitherType.Ordered8x8:
                case WIC.BitmapDitherType.Ordered16x16:
                    if (bitmapPalette.TypeInfo == WIC.BitmapPaletteType.Custom)
                    {
                        dithering = WIC.BitmapDitherType.None;
                    }
                    break;
                }
                paletteType = bitmapPalette.TypeInfo;
            }

            try
            {
                // Create a scaler if need one.
                if ((scale) && (!clip))
                {
                    var scaler = new WIC.BitmapScaler(Factory);
                    scaler.Initialize(bitmap, buffer.Width, buffer.Height, filter);
                    source = scaler;
                }

                // Create a clipper if we want to clip and the image needs resizing.
                if ((clip) && (scale) && ((buffer.Width < bitmap.Size.Width) || (buffer.Height < bitmap.Size.Height)))
                {
                    var clipper = new WIC.BitmapClipper(Factory);
                    clipper.Initialize(bitmap, new DX.Rectangle(0, 0, buffer.Width < bitmap.Size.Width ? buffer.Width : bitmap.Size.Width,
                                                                buffer.Height < bitmap.Size.Height ? buffer.Height : bitmap.Size.Height));
                    source = clipper;
                }

                using (var converter = new WIC.FormatConverter(Factory))
                {
                    if (!converter.CanConvert(sourceFormat, destFormat))
                    {
                        throw new GorgonException(GorgonResult.FormatNotSupported,
                                                  string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, buffer.Format));
                    }

                    converter.Initialize(source, destFormat, dithering, bitmapPalette, alphaPercent, paletteType);

                    if (!scale)
                    {
                        int rowPitch   = (GetBitsPerPixel(destFormat) * bitmap.Size.Width + 7) / 8;
                        int slicePitch = rowPitch * bitmap.Size.Height;

                        if ((rowPitch != buffer.PitchInformation.RowPitch) || (slicePitch != buffer.PitchInformation.SlicePitch))
                        {
                            throw new GorgonException(GorgonResult.CannotWrite, Resources.GORGFX_IMAGE_PITCH_TOO_SMALL);
                        }
                    }
                    converter.CopyPixels(buffer.PitchInformation.RowPitch, buffer.Data.BasePointer, buffer.PitchInformation.SlicePitch);
                }
            }
            finally
            {
                if (source != bitmap)
                {
                    source.Dispose();
                }
            }
        }