public UnmanagedBitmapWrapper(BitmapSourceSafeMILHandle bitmapSource) :
            base(true)
        {            
            _bitmapInit.BeginInit();

            //
            // This constructor is used by BitmapDecoder and BitmapFrameDecode for thumbnails and
            // previews. The bitmapSource parameter comes from BitmapSource.CreateCachedBitmap
            // which already calculated memory pressure, so there's no need to do it here.
            //
            WicSourceHandle = bitmapSource;
            _bitmapInit.EndInit();
            UpdateCachedSettings();
        }
        static internal InPlaceBitmapMetadataWriter CreateFromFrameDecode(BitmapSourceSafeMILHandle frameHandle, object syncObject)
        {
            Invariant.Assert(frameHandle != null);

            SafeMILHandle /* IWICFastMetadataEncoder */ fmeHandle = null;
            SafeMILHandle /* IWICMetadataQueryWriter */ metadataHandle = null;

            using (FactoryMaker factoryMaker = new FactoryMaker())
            {
                lock (syncObject)
                {
                    HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateFastMetadataEncoderFromFrameDecode(
                            factoryMaker.ImagingFactoryPtr,
                            frameHandle,
                            out fmeHandle));
                }
            }

            HRESULT.Check(UnsafeNativeMethods.WICFastMetadataEncoder.GetMetadataQueryWriter(
                    fmeHandle,
                    out metadataHandle));

            return new InPlaceBitmapMetadataWriter(fmeHandle, metadataHandle, syncObject);
        }
 internal static extern int /* HRESULT */ WICConvertBitmapSource( 
     ref Guid dstPixelFormatGuid,
     SafeMILHandle /* IWICBitmapSource */ pISrc, 
     out BitmapSourceSafeMILHandle /* IWICBitmapSource* */ ppIDst); 
 internal static extern int /*HRESULT*/ CreateFastMetadataEncoderFromFrameDecode(
     IntPtr THIS_PTR, 
     BitmapSourceSafeMILHandle /* IWICBitmapFrameDecode */ pIFrameDecode,
     out SafeMILHandle /* IWICFastMetadataEncoder */ ppIBitmap); 
 internal static extern int /*HRESULT*/ CreateBitmapFromHICON(
     IntPtr THIS_PTR, 
     IntPtr hIcon,
     out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap); 
 internal static extern void GetBackBuffer(
     SafeMILHandle /* CSwDoubleBufferedBitmap */ THIS_PTR,
     out BitmapSourceSafeMILHandle /* IWICBitmap */ pBackBuffer,
     out uint pBackBufferSize
     );
Example #7
0
        private void EnsureSource() 
        {
            if (_frameSource == null)
            {
                if (_decoder == null) 
                {
                    HRESULT.Check((int)WinCodecErrors.WINCODEC_ERR_NOTINITIALIZED); 
                } 

                // 
                // Its possible that the frame was originally created with a network URI
                // and DelayCreation was enabled. In this case, the decoder may not yet
                // exist even though the download is complete. The code below creates a
                // decoder if one does not exist. 
                //
                if (_decoder.InternalDecoder == null) 
                { 
                    Debug.Assert(_decoder is LateBoundBitmapDecoder);
                    Debug.Assert(IsDownloading == false); 

                    _decoder = ((LateBoundBitmapDecoder)_decoder).Decoder;
                    _syncObject = _decoder.SyncObject;
 
                    Debug.Assert(_decoder.InternalDecoder != null);
                } 
 
                IntPtr frameDecode = IntPtr.Zero;
 
                Debug.Assert(_syncObject != null);
                lock (_syncObject)
                {
                    HRESULT.Check(UnsafeNativeMethods.WICBitmapDecoder.GetFrame( 
                        _decoder.InternalDecoder,
                        (uint)_frameNumber, 
                        out frameDecode 
                        ));
 
                    _frameSource = new BitmapSourceSafeMILHandle(frameDecode);
                    _frameSource.CalculateSize();
                }
            } 
        }
 internal static extern int /*HRESULT*/ CreateBitmapFromSection(
     UInt32 width,
     UInt32 height,
     ref Guid pixelFormatGuid, 
     IntPtr hSection,
     UInt32 stride, 
     UInt32 offset, 
     out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
 internal static extern int GetAsSoftwareBitmap(SafeMILHandle pInteropDeviceBitmap, out BitmapSourceSafeMILHandle pIWICBitmapSource);
 internal static extern int /* HRESULT */ CreateBitmapFlipRotator(
     IntPtr pICodecFactory,
     out BitmapSourceSafeMILHandle /* IWICBitmapFlipRotator */ ppBitmapFlipRotator); 
 internal static extern int /* HRESULT */ CreateFormatConverter(
     IntPtr pICodecFactory, 
     out BitmapSourceSafeMILHandle /* IWICFormatConverter */ ppFormatConverter); 
Example #12
0
        internal override void FinalizeCreation()
        {
            _bitmapInit.EnsureInitializedComplete();
            BitmapSourceSafeMILHandle wicFormatter = null;

            using (FactoryMaker factoryMaker = new FactoryMaker())
            {
                try
                {
                    IntPtr wicFactory = factoryMaker.ImagingFactoryPtr;

                    HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateFormatConverter(
                                      wicFactory,
                                      out wicFormatter));

                    SafeMILHandle internalPalette;
                    if (DestinationPalette != null)
                    {
                        internalPalette = DestinationPalette.InternalPalette;
                    }
                    else
                    {
                        internalPalette = new SafeMILHandle();
                    }

                    Guid format = DestinationFormat.Guid;

                    lock (_syncObject)
                    {
                        HRESULT.Check(UnsafeNativeMethods.WICFormatConverter.Initialize(
                                          wicFormatter,
                                          Source.WicSourceHandle,
                                          ref format,
                                          DitherType.DitherTypeErrorDiffusion,
                                          internalPalette,
                                          AlphaThreshold,
                                          WICPaletteType.WICPaletteTypeOptimal
                                          ));
                    }

                    //
                    // This is just a link in a BitmapSource chain. The memory is being used by
                    // the BitmapSource at the end of the chain, so no memory pressure needs
                    // to be added here.
                    //
                    WicSourceHandle = wicFormatter;

                    // Even if our source is cached, format conversion is expensive and so we'll
                    // always maintain our own cache for the purpose of rendering.
                    _isSourceCached = false;
                }
                catch
                {
                    _bitmapInit.Reset();
                    throw;
                }
                finally
                {
                    if (wicFormatter != null)
                    {
                        wicFormatter.Close();
                    }
                }
            }

            CreationCompleted = true;
            UpdateCachedSettings();
        }
Example #13
0
        internal override void FinalizeCreation()
        {
            _bitmapInit.EnsureInitializedComplete();
            BitmapSourceSafeMILHandle wicTransformer = null;

            double scaleX, scaleY;
            WICBitmapTransformOptions options;

            GetParamsFromTransform(Transform, out scaleX, out scaleY, out options);

            using (FactoryMaker factoryMaker = new FactoryMaker())
            {
                try
                {
                    IntPtr wicFactory = factoryMaker.ImagingFactoryPtr;

                    wicTransformer = _source.WicSourceHandle;

                    if (!DoubleUtil.IsOne(scaleX) || !DoubleUtil.IsOne(scaleY))
                    {
                        uint width  = Math.Max(1, (uint)(scaleX * _source.PixelWidth + 0.5));
                        uint height = Math.Max(1, (uint)(scaleY * _source.PixelHeight + 0.5));

                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapScaler(
                                          wicFactory,
                                          out wicTransformer));

                        lock (_syncObject)
                        {
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapScaler.Initialize(
                                              wicTransformer,
                                              _source.WicSourceHandle,
                                              width,
                                              height,
                                              WICInterpolationMode.Fant));
                        }
                    }

                    if (options != WICBitmapTransformOptions.WICBitmapTransformRotate0)
                    {
                        // Rotations are extremely slow if we're pulling from a decoder because we end
                        // up decoding multiple times.  Caching the source lets us rotate faster at the cost
                        // of increased memory usage.
                        wicTransformer = CreateCachedBitmap(
                            null,
                            wicTransformer,
                            BitmapCreateOptions.PreservePixelFormat,
                            BitmapCacheOption.Default,
                            _source.Palette);
                        // BitmapSource.CreateCachedBitmap already calculates memory pressure for
                        // the new bitmap, so there's no need to do it before setting it to
                        // WicSourceHandle.

                        BitmapSourceSafeMILHandle rotator = null;

                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFlipRotator(
                                          wicFactory,
                                          out rotator));

                        lock (_syncObject)
                        {
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapFlipRotator.Initialize(
                                              rotator,
                                              wicTransformer,
                                              options));
                        }

                        wicTransformer = rotator;
                    }

                    // If we haven't introduced either a scaler or rotator, add a null rotator
                    // so that our WicSourceHandle isn't the same as our Source's.
                    if (options == WICBitmapTransformOptions.WICBitmapTransformRotate0 &&
                        DoubleUtil.IsOne(scaleX) && DoubleUtil.IsOne(scaleY))
                    {
                        HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFlipRotator(
                                          wicFactory,
                                          out wicTransformer));

                        lock (_syncObject)
                        {
                            HRESULT.Check(UnsafeNativeMethods.WICBitmapFlipRotator.Initialize(
                                              wicTransformer,
                                              _source.WicSourceHandle,
                                              WICBitmapTransformOptions.WICBitmapTransformRotate0));
                        }
                    }

                    WicSourceHandle = wicTransformer;
                    _isSourceCached = _source.IsSourceCached;
                }
                catch
                {
                    _bitmapInit.Reset();
                    throw;
                }
            }

            CreationCompleted = true;
            UpdateCachedSettings();
        }
 internal static extern int /*HRESULT*/
     GetBitmap(
     SafeMILHandle /* IMILRenderTargetBitmap */ THIS_PTR,
     out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
 internal static extern int /* HRESULT */ CreateColorTransform(
     out BitmapSourceSafeMILHandle  /* IWICColorTransform */ ppWICColorTransform);
 internal static extern int /*HRESULT*/ CreateBitmapFromSource(
     IntPtr THIS_PTR,
     SafeMILHandle /* IWICBitmapSource */ pIBitmapSource,
     WICBitmapCreateCacheOptions options, 
     out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
 internal static extern int /* HRESULT */ CreateBitmapRenderTargetForBitmap(
     IntPtr THIS_PTR, 
     BitmapSourceSafeMILHandle /* IWICBitmap */ pIBitmap,
     out SafeMILHandle /* IMILRenderTargetBitmap */ ppIRenderTargetBitmap); 
 internal static extern int /*HRESULT*/ CreateBitmapFromMemory(
     IntPtr THIS_PTR,
     UInt32 width, 
     UInt32 height,
     ref Guid pixelFormatGuid, 
     UInt32 stride, 
     UInt32 cbBufferSize,
     IntPtr /* BYTE* */ pvPixels, 
     out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap);
 internal unsafe static extern int /* HRESULT */ CreateCWICWrapperBitmap(
     BitmapSourceSafeMILHandle /* IWICBitmapSource */ pIWICBitmapSource,
     out BitmapSourceSafeMILHandle /* CWICWrapperBitmap as IWICBitmapSource */ pCWICWrapperBitmap);
 internal static extern int /*HRESULT*/ CreateBitmap( 
     IntPtr THIS_PTR,
     UInt32 width, 
     UInt32 height,
     ref Guid pixelFormatGuid,
     WICBitmapCreateCacheOptions options,
     out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap); 
Example #21
0
        private void EnsureThumbnail() 
        {
            if (_isThumbnailCached || IsDownloading) 
            {
                return;
            }
            else 
            {
                EnsureSource(); 
 
                IntPtr /* IWICBitmapSource */ thumbnail = IntPtr.Zero;
 
                lock (_syncObject)
                {
                    // Check if there is embedded thumbnail or not
                    int hr = UnsafeNativeMethods.WICBitmapFrameDecode.GetThumbnail( 
                        _frameSource,
                        out thumbnail 
                        ); 

                    if (hr != (int)WinCodecErrors.WINCODEC_ERR_CODECNOTHUMBNAIL) 
                    {
                        HRESULT.Check(hr);
                    }
                } 

                _isThumbnailCached = true; 
 
                if (thumbnail != IntPtr.Zero)
                { 
                    BitmapSourceSafeMILHandle thumbHandle = new BitmapSourceSafeMILHandle(thumbnail);
                    SafeMILHandle unmanagedPalette = BitmapPalette.CreateInternalPalette();
                    BitmapPalette palette = null;
 
                    int hr = UnsafeNativeMethods.WICBitmapSource.CopyPalette(
                                thumbHandle, 
                                unmanagedPalette 
                                );
                    if (hr == HRESULT.S_OK) 
                    {
                        palette = new BitmapPalette(unmanagedPalette);
                    }
 
                    _thumbnail = new UnmanagedBitmapWrapper(
                        CreateCachedBitmap( 
                            null, 
                            thumbHandle,
                            BitmapCreateOptions.PreservePixelFormat, 
                            _cacheOption,
                            palette
                            ));
                    _thumbnail.Freeze(); 
                }
            } 
        } 
 internal static extern int /*HRESULT*/ CreateBitmapFromHBITMAP(
     IntPtr THIS_PTR,
     IntPtr hBitmap,
     IntPtr hPalette, 
     WICBitmapAlphaChannelOption options,
     out BitmapSourceSafeMILHandle /* IWICBitmap */ ppIBitmap); 
        internal static BitmapSourceSafeMILHandle CreateCachedBitmap(
            BitmapFrame frame,
            BitmapSourceSafeMILHandle wicSource,
            BitmapCreateOptions createOptions,
            BitmapCacheOption cacheOption,
            BitmapPalette palette
            )
        {
            BitmapSourceSafeMILHandle wicConverter = null;
            BitmapSourceSafeMILHandle wicConvertedSource = null;

            // For NoCache, return the original
            if (cacheOption == BitmapCacheOption.None)
            {
                return wicSource;
            }

            using (FactoryMaker factoryMaker = new FactoryMaker())
            {
                IntPtr wicFactory = factoryMaker.ImagingFactoryPtr;
                bool changeFormat = false;
                PixelFormat originalFmt = PixelFormats.Pbgra32;

                WICBitmapCreateCacheOptions wicCache = WICBitmapCreateCacheOptions.WICBitmapCacheOnLoad;
                if (cacheOption == BitmapCacheOption.OnDemand)
                {
                    wicCache = WICBitmapCreateCacheOptions.WICBitmapCacheOnDemand;
                }

                originalFmt = PixelFormat.GetPixelFormat(wicSource);
                PixelFormat destFmt = originalFmt;

                // check that we need to change the format of the bitmap
                if (0 == (createOptions & BitmapCreateOptions.PreservePixelFormat))
                {
                    if (!IsCompatibleFormat(originalFmt))
                        changeFormat = true;

                    destFmt = BitmapSource.GetClosestDUCEFormat(originalFmt, palette);
                }

                if (frame != null &&
                    (createOptions & BitmapCreateOptions.IgnoreColorProfile) == 0 &&
                    frame.ColorContexts != null &&
                    frame.ColorContexts[0] != null &&
                    frame.ColorContexts[0].IsValid &&
                    !frame._isColorCorrected &&
                    PixelFormat.GetPixelFormat(wicSource).Format != PixelFormatEnum.Extended
                    )
                {
                    ColorContext destinationColorContext;

                    // We need to make sure, we can actually create the ColorContext for the destination destFmt
                    // If the destFmt is gray or scRGB, the following is not supported, so we cannot
                    // create the ColorConvertedBitmap
                    try
                    {
                        destinationColorContext = new ColorContext(destFmt);
                    }
                    catch (NotSupportedException)
                    {
                        destinationColorContext = null;
                    }

                    if (destinationColorContext != null)
                    {
                        // NOTE: Never do this for a non-MIL pixel format, because the format converter has
                        // special knowledge to deal with the profile

                        bool conversionSuccess = false;
                        bool badColorContext = false;

                        // First try if the color converter can handle the source format directly
                        // Its possible that the color converter does not support certain pixelformats, so put a try/catch here.
                        try
                        {
                            ColorConvertedBitmap colorConvertedBitmap = new ColorConvertedBitmap(
                                frame,
                                frame.ColorContexts[0],
                                destinationColorContext,
                                destFmt
                                );

                            wicSource = colorConvertedBitmap.WicSourceHandle;
                            frame._isColorCorrected = true;
                            conversionSuccess = true;
                            changeFormat = false;   // Changeformat no longer necessary, because destFmt already created
                            // by ColorConvertedBitmap
                        }
                        catch (NotSupportedException)
                        {
                        }
                        catch (FileFormatException)
                        {
                            // If the file contains a bad color context, we catch the exception here
                            // and don't bother trying the color conversion below, since color transform isn't possible
                            // with the given color context.
                            badColorContext = true;
                        }

                        if (!conversionSuccess && changeFormat && !badColorContext)
                        {   // If the conversion failed, we first use
                            // a FormatConvertedBitmap, and then Color Convert that one...
                            changeFormat = false;

                            FormatConvertedBitmap formatConvertedBitmap = new FormatConvertedBitmap(frame, destFmt, null, 0.0);

                            ColorConvertedBitmap colorConvertedBitmap = new ColorConvertedBitmap(
                                formatConvertedBitmap,
                                frame.ColorContexts[0],
                                destinationColorContext,
                                destFmt
                                );

                            wicSource = colorConvertedBitmap.WicSourceHandle;
                            frame._isColorCorrected = true;
                            Debug.Assert(destFmt == colorConvertedBitmap.Format);
                            changeFormat = false;   // Changeformat no longer necessary, because destFmt already created
                            // by ColorConvertedBitmap
                        }
                    }
                }

                if (changeFormat)
                {
                    // start up a format converter
                    Guid fmtDestFmt = destFmt.Guid;
                    HRESULT.Check(UnsafeNativeMethods.WICCodec.WICConvertBitmapSource(
                            ref fmtDestFmt,
                            wicSource,
                            out wicConverter));

                    // dump the converted contents into a bitmap
                    HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFromSource(
                            wicFactory,
                            wicConverter,
                            wicCache,
                            out wicConvertedSource));
                }
                else
                {
                    // Create the unmanaged resources
                    HRESULT.Check(UnsafeNativeMethods.WICImagingFactory.CreateBitmapFromSource(
                            wicFactory,
                            wicSource,
                            wicCache,
                            out wicConvertedSource));
                }

                wicConvertedSource.CalculateSize();
            }

            return wicConvertedSource;
        }
        internal CachedBitmap(BitmapSourceSafeMILHandle bitmap) : base(true)
        {
            if (bitmap == null)
            {
                throw new ArgumentNullException("bitmap");
            }

            // We're not calling CachedBitmap.Begin/EndInit because that would
            // invoke FinalizeCreation which calls CreateCachedBitmap that does
            // unnecessary work and only deals with BitmapFrames
            _bitmapInit.BeginInit();

            _source = null;
            _createOptions = BitmapCreateOptions.None;
            _cacheOption = BitmapCacheOption.OnLoad;

            //
            // This constructor is used by D3DImage, which does not calculate memory pressure for
            // the bitmap parameter before calling the constructor.
            //
            bitmap.CalculateSize();
            // This will QI to IWICBitmapSource for us. QI also AddRefs, of course.
            WicSourceHandle = bitmap;
            _syncObject = WicSourceHandle;

            IsSourceCached = true;
            CreationCompleted = true;

            _bitmapInit.EndInit();
        }