Пример #1
0
        private void SaveFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions, BitmapFrame frame)
        {
            SetupFrame(frameEncodeHandle, encoderOptions);

            // Helpful for debugging stress and remote dumps
            _encodeState = EncodeState.FrameEncodeInitialized;

            // Set the size
            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetSize(
                frameEncodeHandle,
                frame.PixelWidth,
                frame.PixelHeight
                ));

            // Helpful for debugging stress and remote dumps
            _encodeState = EncodeState.FrameEncodeSizeSet;

            // Set the resolution
            double dpiX = frame.DpiX;
            double dpiY = frame.DpiY;

            if (dpiX <= 0)
            {
                dpiX = 96;
            }
            if (dpiY <= 0)
            {
                dpiY = 96;
            }

            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetResolution(
                frameEncodeHandle,
                dpiX,
                dpiY
                ));

            // Helpful for debugging stress and remote dumps
            _encodeState = EncodeState.FrameEncodeResolutionSet;

            if (_supportsFrameThumbnails)
            {
                // Set the thumbnail.
                BitmapSource thumbnail = frame.Thumbnail;

                if (thumbnail != null)
                {
                    SafeMILHandle thumbnailHandle = thumbnail.WicSourceHandle;

                    lock (thumbnail.SyncObject)
                    {
                        HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.SetThumbnail(
                            frameEncodeHandle,
                            thumbnailHandle
                            ));

                        // Helpful for debugging stress and remote dumps
                        _encodeState = EncodeState.FrameEncodeThumbnailSet;
                    }
                }
            }

            // if the source has been color corrected, we want to use a corresponding color profile
            if (frame._isColorCorrected)
            {
                ColorContext colorContext = new ColorContext(frame.Format);
                IntPtr[] colorContextPtrs = new IntPtr[1] { colorContext.ColorContextHandle.DangerousGetHandle() };

                int hr = UnsafeNativeMethods.WICBitmapFrameEncode.SetColorContexts(
                    frameEncodeHandle,
                    1,
                    colorContextPtrs
                    );

                // It's possible that some encoders may not support color contexts so don't check hr
                if (hr == HRESULT.S_OK)
                {
                    // Helpful for debugging stress and remote dumps
                    _encodeState = EncodeState.FrameEncodeColorContextsSet;
                }
            }
            // if the caller has explicitly provided color contexts, add them to the encoder
            else
            {
                IList<ColorContext> colorContexts = frame.ColorContexts;
                if (colorContexts != null && colorContexts.Count > 0)
                {             
                    int count = colorContexts.Count;

                    // Marshal can't convert SafeMILHandle[] so we must
                    {
                        IntPtr[] colorContextPtrs = new IntPtr[count];
                        for (int i = 0; i < count; ++i)
                        {
                            colorContextPtrs[i] = colorContexts[i].ColorContextHandle.DangerousGetHandle();
                        }

                        int hr = UnsafeNativeMethods.WICBitmapFrameEncode.SetColorContexts(
                            frameEncodeHandle,
                            (uint)count,
                            colorContextPtrs
                            );

                        // It's possible that some encoders may not support color contexts so don't check hr
                        if (hr == HRESULT.S_OK)
                        {
                            // Helpful for debugging stress and remote dumps
                            _encodeState = EncodeState.FrameEncodeColorContextsSet;
                        }
                    }
                }
            }

            // Set the pixel format and palette

            lock (frame.SyncObject)
            {
                SafeMILHandle outSourceHandle = new SafeMILHandle();
                SafeMILHandle bitmapSourceHandle = frame.WicSourceHandle;
                SafeMILHandle paletteHandle = new SafeMILHandle();

                // Set the pixel format and palette of the bitmap.
                // This could (but hopefully won't) introduce a format converter.
                HRESULT.Check(UnsafeNativeMethods.WICCodec.WICSetEncoderFormat(
                    bitmapSourceHandle,
                    paletteHandle,
                    frameEncodeHandle,
                    out outSourceHandle
                    ));

                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeFormatSet;
                _writeSourceHandles.Add(outSourceHandle);

                // Set the metadata
                if (_supportsFrameMetadata)
                {
                    BitmapMetadata metadata = frame.Metadata as BitmapMetadata;

                    // If the frame has metadata associated with a different container format, then we ignore it.
                    if (metadata != null && metadata.GuidFormat == ContainerFormat)
                    {
                        SafeMILHandle /* IWICMetadataQueryWriter */ metadataHandle = new SafeMILHandle();

                        HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.GetMetadataQueryWriter(
                            frameEncodeHandle,
                            out metadataHandle
                            ));

                        PROPVARIANT propVar = new PROPVARIANT();

                        try
                        {
                            propVar.Init(metadata);

                            lock (metadata.SyncObject)
                            {
                                HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName(
                                    metadataHandle,
                                    "/",
                                    ref propVar
                                    ));

                                // Helpful for debugging stress and remote dumps
                                _encodeState = EncodeState.FrameEncodeMetadataSet;
                            }
                        }
                        finally
                        {
                            propVar.Clear();
                        }
                    }
                }

                Int32Rect r = new Int32Rect();
                HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.WriteSource(
                    frameEncodeHandle,
                    outSourceHandle,
                    ref r
                    ));

                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeSourceWritten;

                HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.Commit(
                    frameEncodeHandle
                    ));

                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.FrameEncodeCommitted;
            }
        }
Пример #2
0
        public virtual void Save(System.IO.Stream stream)
        {
            VerifyAccess();
            EnsureBuiltIn();
            EnsureUnmanagedEncoder();

            // No-op to get rid of build error
            if (_encodeState == EncodeState.None)
            {
            }

            if (_hasSaved)
            {
                throw new InvalidOperationException(SR.Get(SRID.Image_OnlyOneSave));
            }

            if (_frames == null)
            {
                throw new System.NotSupportedException(SR.Get(SRID.Image_NoFrames, null));
            }

            int count = _frames.Count;
            if (count <= 0)
            {
                throw new System.NotSupportedException(SR.Get(SRID.Image_NoFrames, null));
            }

            IntPtr comStream = IntPtr.Zero;
            SafeMILHandle encoderHandle = _encoderHandle;

            try
            {
                comStream = StreamAsIStream.IStreamFrom(stream);

                // does this addref the stream?
                HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.Initialize(
                    encoderHandle,
                    comStream,
                    WICBitmapEncodeCacheOption.WICBitmapEncodeNoCache
                    ));

                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.EncoderInitialized;

                // Save global thumbnail if any.
                if (_thumbnail != null)
                {
                    Debug.Assert(_supportsGlobalThumbnail);
                    SafeMILHandle thumbnailBitmapSource = _thumbnail.WicSourceHandle;

                    lock (_thumbnail.SyncObject)
                    {
                        HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.SetThumbnail(
                            encoderHandle,
                            thumbnailBitmapSource
                            ));

                        // Helpful for debugging stress and remote dumps
                        _encodeState = EncodeState.EncoderThumbnailSet;
                    }
                }

                // Save global palette if any.
                if (_palette != null && _palette.Colors.Count > 0)
                {
                    SafeMILHandle paletteHandle = _palette.InternalPalette;

                    HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.SetPalette(
                        encoderHandle,
                        paletteHandle
                        ));

                    // Helpful for debugging stress and remote dumps
                    _encodeState = EncodeState.EncoderPaletteSet;
                }

                // Save global metadata if any.
                if (_metadata != null && _metadata.GuidFormat == ContainerFormat)
                {
                    Debug.Assert(_supportsGlobalMetadata);

                    EnsureMetadata(false);

                    if (_metadata.InternalMetadataHandle != _metadataHandle)
                    {
                        PROPVARIANT propVar = new PROPVARIANT();

                        try
                        {
                            propVar.Init(_metadata);

                            lock (_metadata.SyncObject)
                            {
                                HRESULT.Check(UnsafeNativeMethods.WICMetadataQueryWriter.SetMetadataByName(
                                    _metadataHandle,
                                    "/",
                                    ref propVar
                                    ));
                            }
                        }
                        finally
                        {
                            propVar.Clear();
                        }
                    }
                }

                for (int i = 0; i < count; i++)
                {
                    SafeMILHandle frameEncodeHandle = new SafeMILHandle();
                    SafeMILHandle encoderOptions = new SafeMILHandle();
                    HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.CreateNewFrame(
                        encoderHandle,
                        out frameEncodeHandle,
                        out encoderOptions
                        ));

                    // Helpful for debugging stress and remote dumps
                    _encodeState = EncodeState.EncoderCreatedNewFrame;
                    _frameHandles.Add(frameEncodeHandle);

                    SaveFrame(frameEncodeHandle, encoderOptions, _frames[i]);

                    // If multiple frames are not supported, break out
                    if (!_supportsMultipleFrames)
                    {
                        break;
                    }
                }

                // Now let the encoder know we are done encoding the file.
                HRESULT.Check(UnsafeNativeMethods.WICBitmapEncoder.Commit(encoderHandle));

                // Helpful for debugging stress and remote dumps
                _encodeState = EncodeState.EncoderCommitted;
            }
            finally
            {
                UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref comStream);
            }

            _hasSaved = true;
        }
Пример #3
0
        internal override void SetupFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions)
        { 
            PROPBAG2 propBag = new PROPBAG2(); 
            PROPVARIANT propValue = new PROPVARIANT();
 
            // There is only one encoder option supported here:

            if (_interlaceOption != c_defaultInterlaceOption)
            { 
                try
                { 
                    propBag.Init("InterlaceOption"); 
                    propValue.Init(_interlaceOption == PngInterlaceOption.On);
 
                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag, 
                        ref propValue));
                } 
                finally 
                {
                    propBag.Clear(); 
                    propValue.Clear();
                }
            }
 
            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.Initialize(
                frameEncodeHandle, 
                encoderOptions 
                ));
        } 
Пример #4
0
        internal override void SetupFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions)
        {
            PROPBAG2 propBag = new PROPBAG2();
            PROPVARIANT propValue = new PROPVARIANT();

            if (_imagequalitylevel != c_defaultImageQualityLevel)
            {
                try
                {
                    propBag.Init("ImageQuality");
                    propValue.Init((float)_imagequalitylevel);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_transformation != c_defaultTransformation)
            {
                try
                {
                    propBag.Init("BitmapTransform");
                    propValue.Init((byte) _transformation);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_lossless != c_defaultLossless)
            {
                try
                {
                    propBag.Init("Lossless");
                    propValue.Init((bool)_lossless);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_usecodecoptions != c_defaultUseCodecOptions)
            {
                try
                {
                    propBag.Init("UseCodecOptions");
                    propValue.Init((bool)_usecodecoptions);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_qualitylevel != c_defaultQualityLevel)
            {
                try
                {
                    propBag.Init("Quality");
                    propValue.Init((byte)_qualitylevel);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_subsamplinglevel != c_defaultSubsamplingLevel)
            {
                try
                {
                    propBag.Init("Subsampling");
                    propValue.Init((byte)_subsamplinglevel);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_overlaplevel != c_defaultOverlapLevel)
            {
                try
                {
                    propBag.Init("Overlap");
                    propValue.Init((byte)_overlaplevel);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_horizontaltileslices != c_defaultHorizontalTileSlices)
            {
                try
                {
                    propBag.Init("HorizontalTileSlices");
                    propValue.Init((ushort)_horizontaltileslices );

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_verticaltileslices != c_defaultVerticalTileSlices)
            {
                try
                {
                    propBag.Init("VerticalTileSlices");
                    propValue.Init((ushort)_verticaltileslices );

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_frequencyorder != c_defaultFrequencyOrder)
            {
                try
                {
                    propBag.Init("FrequencyOrder");
                    propValue.Init((bool)_frequencyorder);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_interleavedalpha != c_defaultInterleavedAlpha)
            {
                try
                {
                    propBag.Init("InterleavedAlpha");
                    propValue.Init((bool)_interleavedalpha);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_alphaqualitylevel != c_defaultAlphaQualityLevel)
            {
                try
                {
                    propBag.Init("AlphaQuality");
                    propValue.Init((byte)_alphaqualitylevel);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_compresseddomaintranscode  != c_defaultCompressedDomainTranscode)
            {
                try
                {
                    propBag.Init("CompressedDomainTranscode");
                    propValue.Init((bool)_compresseddomaintranscode);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_imagedatadiscardlevel != c_defaultImageDataDiscardLevel)
            {
                try
                {
                    propBag.Init("ImageDataDiscard");
                    propValue.Init((byte)_imagedatadiscardlevel);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_alphadatadiscardlevel != c_defaultAlphaDataDiscardLevel)
            {
                try
                {
                    propBag.Init("AlphaDataDiscard");
                    propValue.Init((byte)_alphadatadiscardlevel);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_ignoreoverlap != c_defaultIgnoreOverlap)
            {
                try
                {
                    propBag.Init("IgnoreOverlap");
                    propValue.Init((bool)_ignoreoverlap);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.Initialize(
                frameEncodeHandle,
                encoderOptions
                ));
        }
        internal override void SetupFrame(SafeMILHandle frameEncodeHandle, SafeMILHandle encoderOptions)
        {
            PROPBAG2 propBag = new PROPBAG2();
            PROPVARIANT propValue = new PROPVARIANT();

            // There are only two encoder options supported here:

            if (_transformation != c_defaultTransformation)
            {
                try
                {
                    propBag.Init("BitmapTransform");
                    propValue.Init((byte) _transformation);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            if (_qualityLevel != c_defaultQualityLevel)
            {
                try
                {
                    propBag.Init("ImageQuality");
                    propValue.Init( ((float)_qualityLevel) / 100.0f);

                    HRESULT.Check(UnsafeNativeMethods.IPropertyBag2.Write(
                        encoderOptions,
                        1,
                        ref propBag,
                        ref propValue));
                }
                finally
                {
                    propBag.Clear();
                    propValue.Clear();
                }
            }

            HRESULT.Check(UnsafeNativeMethods.WICBitmapFrameEncode.Initialize(
                frameEncodeHandle,
                encoderOptions
                ));
        }