Пример #1
0
        internal ColorTransform(SafeMILHandle bitmapSource, ColorContext srcContext, ColorContext dstContext, System.Windows.Media.PixelFormat pixelFormat)
        {
            InitializeICM();

            if (srcContext == null)
            {
                srcContext = new ColorContext(pixelFormat);
            }
            if (dstContext == null)
            {
                dstContext = new ColorContext(pixelFormat);
            }

            _inputColorType  = srcContext.ColorType;
            _outputColorType = dstContext.ColorType;

            //if this failed or the handle is invalid, we can't continue
            if (srcContext.ProfileHandle != null && !srcContext.ProfileHandle.IsInvalid)
            {
                //if this failed or the handle is invalid, we can't continue
                if (dstContext.ProfileHandle != null && !dstContext.ProfileHandle.IsInvalid)
                {
                    _colorTransformHelper.CreateTransform(srcContext.ProfileHandle, dstContext.ProfileHandle);
                }
            }
        }
Пример #2
0
        /// <summary> 
        /// Construct a ColorConvertedBitmap
        /// </summary>
        /// <param name="source">Input BitmapSource to color convert</param>
        /// <param name="sourceColorContext">Source Color Context</param> 
        /// <param name="destinationColorContext">Destination Color Context</param>
        /// <param name="format">Destination Pixel format</param> 
        public ColorConvertedBitmap(BitmapSource source, ColorContext sourceColorContext, ColorContext destinationColorContext, PixelFormat format) 
            : base(true) // Use base class virtuals
        { 
            if (source == null)
            {
                throw new ArgumentNullException("source");
            } 

            if (sourceColorContext == null) 
            { 
                throw new ArgumentNullException("sourceColorContext");
            } 

            if (destinationColorContext == null)
            {
                throw new ArgumentNullException("destinationColorContext"); 
            }
 
            _bitmapInit.BeginInit(); 

            Source = source; 
            SourceColorContext = sourceColorContext;
            DestinationColorContext = destinationColorContext;
            DestinationFormat = format;
 
            _bitmapInit.EndInit();
            FinalizeCreation(); 
        } 
Пример #3
0
        internal ColorTransform(SafeMILHandle bitmapSource, ColorContext srcContext, ColorContext dstContext, System.Windows.Media.PixelFormat pixelFormat) 
        {
            InitializeICM(); 

            if (srcContext == null)
            {
                srcContext = new ColorContext(pixelFormat); 
            }
            if (dstContext == null) 
            { 
                dstContext = new ColorContext(pixelFormat);
            } 

            _inputColorType = srcContext.ColorType;
            _outputColorType = dstContext.ColorType;
 
            //if this failed or the handle is invalid, we can't continue
            if (srcContext.ProfileHandle != null && !srcContext.ProfileHandle.IsInvalid) 
            { 
                //if this failed or the handle is invalid, we can't continue
                if (dstContext.ProfileHandle != null && !dstContext.ProfileHandle.IsInvalid) 
                {
                    _colorTransformHelper.CreateTransform(srcContext.ProfileHandle, dstContext.ProfileHandle);
                }
            } 
        }
Пример #4
0
        private async Task ProcessTask(Tuple<int, int, double> task)
        {
            int width = task.Item1;
            int height = task.Item2;
            double k = task.Item3;
            WriteableBitmap bitmap = (WriteableBitmap)MainImage.Source;

            // Create new bitmap if current bit is invalid or obsolete.
            if (bitmap == null || bitmap.PixelWidth != width || bitmap.PixelWidth != height)
            {
                bitmap = new WriteableBitmap(width, height, 96.0, 96.0, PixelFormats.Bgr32, null);
            }

            ColorContext cc = new ColorContext(PixelFormats.Bgr32);

            this.Title = cc.ProfileUri.ToString();

            bitmap.Lock();

            IntPtr buffer = bitmap.BackBuffer;
            int stride = bitmap.BackBufferStride;

            // Generate the content of the bitmap.
            await Task.Run(() => FillBitmap(buffer, width, height, stride, k));

            bitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
            bitmap.Unlock();

            MainImage.Source = bitmap;
        }
Пример #5
0
        internal ColorTransform(ColorContext srcContext, ColorContext dstContext)
        {
            InitializeICM();

            if (srcContext == null)
            {
                srcContext = new ColorContext(PixelFormats.Bgra32);
            }

            if (dstContext == null)
            {
                dstContext = new ColorContext(PixelFormats.Bgra32);
            }

            _inputColorType  = srcContext.ColorType;
            _outputColorType = dstContext.ColorType;

            _colorTransformHelper.CreateTransform(srcContext.ProfileHandle, dstContext.ProfileHandle);
        }
Пример #6
0
        internal ColorTransform(ColorContext srcContext, ColorContext dstContext) 
        { 
            InitializeICM();
 
            if (srcContext == null)
            {
                srcContext = new ColorContext(PixelFormats.Bgra32);
            } 

            if (dstContext == null) 
            { 
                dstContext = new ColorContext(PixelFormats.Bgra32);
            } 

            _inputColorType = srcContext.ColorType;
            _outputColorType = dstContext.ColorType;
 
            _colorTransformHelper.CreateTransform(srcContext.ProfileHandle, dstContext.ProfileHandle);
        } 
Пример #7
0
        //------------------------------------------------------
        //
        //  Equality Methods/Properties
        //
        //------------------------------------------------------

        #region Equality methods and Properties

        /// <summary>
        /// Equals method
        /// </summary>
        override public bool Equals(object obj)
        {
            ColorContext context = obj as ColorContext;

            return(context == this);
        }
Пример #8
0
        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;
        }
        /// <summary>
        ///  Return an object that should be set on the targetObject's targetProperty
        ///  for this markup extension.  For ColorConvertedBitmapExtension, this is the object found in 
        ///  a resource dictionary in the current parent chain that is keyed by ResourceKey
        /// </summary> 
        /// <returns> 
        ///  The object to set on this property.
        /// </returns> 
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (_image == null)
            { 
                throw new InvalidOperationException(SR.Get(SRID.ColorConvertedBitmapExtensionNoSourceImage));
            } 
            if (_sourceProfile == null) 
            {
                throw new InvalidOperationException(SR.Get(SRID.ColorConvertedBitmapExtensionNoSourceProfile)); 
            }

            // [BreakingChange] Dev10 Bug #454108
            // We really should throw an ArgumentNullException here for serviceProvider. 

            // Save away the BaseUri. 
            IUriContext uriContext = serviceProvider.GetService(typeof(IUriContext)) as IUriContext; 
            if( uriContext == null )
            { 
                throw new InvalidOperationException(SR.Get(SRID.MarkupExtensionNoContext, GetType().Name, "IUriContext" ));
            }
            _baseUri = uriContext.BaseUri;
 

            Uri imageUri = GetResolvedUri(_image); 
            Uri sourceProfileUri = GetResolvedUri(_sourceProfile); 
            Uri destinationProfileUri = GetResolvedUri(_destinationProfile);
 
            ColorContext sourceContext = new ColorContext(sourceProfileUri);
            ColorContext destinationContext = destinationProfileUri != null ?
                                                new ColorContext(destinationProfileUri) :
                                                new ColorContext(PixelFormats.Default); 

            BitmapDecoder decoder = BitmapDecoder.Create( 
                                                                imageUri, 
                                                                BitmapCreateOptions.IgnoreColorProfile | BitmapCreateOptions.IgnoreImageCache,
                                                                BitmapCacheOption.None 
                                                                );

            BitmapSource bitmap = decoder.Frames[0];
            FormatConvertedBitmap formatConverted = new FormatConvertedBitmap(bitmap, PixelFormats.Bgra32, null, 0.0); 

            object result = formatConverted; 
 
            try
            { 
                ColorConvertedBitmap colorConverted = new ColorConvertedBitmap(formatConverted, sourceContext, destinationContext, PixelFormats.Bgra32);
                result= colorConverted;
            }
            catch (FileFormatException) 
            {   // Gracefully ignore non-matching profile
                // If the file contains a bad color context, we catch the exception here 
                // since color transform isn't possible 
                // with the given color context.
            } 

            return result;
        }
Пример #10
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;
            }
        }
Пример #11
0
        internal override void FinalizeCreation() 
        {
            _bitmapInit.EnsureInitializedComplete(); 
            Uri uri = UriSource; 
            if (_baseUri != null)
                uri = new Uri(_baseUri, UriSource); 

            if ((CreateOptions & BitmapCreateOptions.IgnoreImageCache) != 0)
            {
                ImagingCache.RemoveFromImageCache(uri); 
            }
 
            BitmapImage bitmapImage = CheckCache(uri); 

            if (bitmapImage != null && 
                bitmapImage.CheckAccess() &&
                bitmapImage.SourceRect.Equals(SourceRect) &&
                bitmapImage.DecodePixelWidth == DecodePixelWidth &&
                bitmapImage.DecodePixelHeight == DecodePixelHeight && 
                bitmapImage.Rotation == Rotation &&
                (bitmapImage.CreateOptions & BitmapCreateOptions.IgnoreColorProfile) == 
                (CreateOptions & BitmapCreateOptions.IgnoreColorProfile) 
               )
            { 
                _syncObject = bitmapImage.SyncObject;
                lock (_syncObject)
                {
                    WicSourceHandle = bitmapImage.WicSourceHandle; 
                    IsSourceCached = bitmapImage.IsSourceCached;
                    _convertedDUCEPtr = bitmapImage._convertedDUCEPtr; 
 
                    //
                    // We nee d to keep the strong reference to the cached image for a few reasons: 
                    //
                    //    The application may release the original cached image and then keep a
                    //    reference to this image only, in which case, the cache can be collected.
                    //    This will cause a few undesirable results: 
                    //    1. The application may choose to decode the same URI again in which case
                    //       we will not retrieve it from the cache even though we have a copy already 
                    //       decoded. 
                    //    2. The original cached image holds onto the file stream indirectly which if
                    //       collected can cause bad behavior if the entire image is not loaded into 
                    //       memory.
                    //
                    _cachedBitmapImage = bitmapImage;
                } 
                UpdateCachedSettings();
                return; 
            } 

            BitmapDecoder decoder = null; 
            if (_decoder == null)
            {
                // Note: We do not want to insert in the cache if there is a chance that
                //       the decode pixel width/height may cause the decoder LOD to change 
                decoder = BitmapDecoder.CreateFromUriOrStream(
                    _baseUri, 
                    UriSource, 
                    StreamSource,
                    CreateOptions & ~BitmapCreateOptions.DelayCreation, 
                    BitmapCacheOption.None, // do not cache the frames since we will do that here
                    _uriCachePolicy,
                    false
                    ); 

                if (decoder.IsDownloading) 
                { 
                    _isDownloading = true;
                    _decoder = decoder; 
                    decoder.DownloadProgress += OnDownloadProgress;
                    decoder.DownloadCompleted += OnDownloadCompleted;
                    decoder.DownloadFailed += OnDownloadFailed;
                } 
                else
                { 
                    Debug.Assert(decoder.SyncObject != null); 
                }
            } 
            else
            {
                // We already had a decoder, meaning we were downloading
                Debug.Assert(!_decoder.IsDownloading); 
                decoder = _decoder;
                _decoder = null; 
            } 

            if (decoder.Frames.Count == 0) 
            {
                throw new System.ArgumentException(SR.Get(SRID.Image_NoDecodeFrames));
            }
 
            BitmapFrame frame = decoder.Frames[0];
            BitmapSource source = frame; 
 
            Int32Rect sourceRect = SourceRect;
 
            if (sourceRect.X == 0 && sourceRect.Y == 0 &&
                sourceRect.Width == source.PixelWidth &&
                sourceRect.Height == source.PixelHeight)
            { 
                sourceRect = Int32Rect.Empty;
            } 
 
            if (!sourceRect.IsEmpty)
            { 
                CroppedBitmap croppedSource = new CroppedBitmap();
                croppedSource.BeginInit();
                croppedSource.Source = source;
                croppedSource.SourceRect = sourceRect; 
                croppedSource.EndInit();
 
                source = croppedSource; 
                if (_isDownloading)
                { 
                    // Unregister the download events because this is a dummy image. See comment below.
                    source.UnregisterDownloadEventSource();
                }
            } 

            int finalWidth = DecodePixelWidth; 
            int finalHeight = DecodePixelHeight; 

            if (finalWidth == 0 && finalHeight == 0) 
            {
                finalWidth = source.PixelWidth;
                finalHeight = source.PixelHeight;
            } 
            else if (finalWidth == 0)
            { 
                finalWidth = (source.PixelWidth * finalHeight) / source.PixelHeight; 
            }
            else if (finalHeight == 0) 
            {
                finalHeight = (source.PixelHeight * finalWidth) / source.PixelWidth;
            }
 
            if (finalWidth != source.PixelWidth || finalHeight != source.PixelHeight ||
                Rotation != Rotation.Rotate0) 
            { 
                TransformedBitmap transformedSource = new TransformedBitmap();
                transformedSource.BeginInit(); 
                transformedSource.Source = source;

                TransformGroup transformGroup = new TransformGroup();
 
                if (finalWidth != source.PixelWidth || finalHeight != source.PixelHeight)
                { 
                    int oldWidth = source.PixelWidth; 
                    int oldHeight = source.PixelHeight;
 
                    Debug.Assert(oldWidth > 0 && oldHeight > 0);

                    transformGroup.Children.Add(
                        new ScaleTransform( 
                            (1.0*finalWidth)/ oldWidth,
                            (1.0*finalHeight)/oldHeight)); 
                } 

                if (Rotation != Rotation.Rotate0) 
                {
                    double rotation = 0.0;

                    switch (Rotation) 
                    {
                        case Rotation.Rotate0: 
                            rotation = 0.0; 
                            break;
                        case Rotation.Rotate90: 
                            rotation = 90.0;
                            break;
                        case Rotation.Rotate180:
                            rotation = 180.0; 
                            break;
                        case Rotation.Rotate270: 
                            rotation = 270.0; 
                            break;
                        default: 
                            Debug.Assert(false);
                            break;
                    }
 
                    transformGroup.Children.Add(new RotateTransform(rotation));
                } 
 
                transformedSource.Transform = transformGroup;
 
                transformedSource.EndInit();

                source = transformedSource;
                if (_isDownloading) 
                {
                    // 
                    // If we're currently downloading, then the BitmapFrameDecode isn't actually 
                    // the image, it's just a 1x1 placeholder. The chain we're currently building
                    // will be replaced with another chain once download completes, so there's no 
                    // need to have this chain handle DownloadCompleted.
                    //
                    // Having this chain handle DownloadCompleted is actually a bad thing. Because
                    // the dummy is just 1x1, the TransformedBitmap we're building here will have 
                    // a large scaling factor (to scale the image from 1x1 up to whatever
                    // DecodePixelWidth/Height specifies). When the TransformedBitmap receives 
                    // DownloadCompleted from the BFD, it will call into WIC to create a new 
                    // bitmap scaler using the same large scaling factor, which can produce a huge
                    // bitmap (since the BFD is now no longer 1x1). This problem is made worse if 
                    // this BitmapImage has BitmapCacheOption.OnLoad, since that will put a
                    // CachedBitmap after the TransformedBitmap. When DownloadCompleted propagates
                    // from the TransformedBitmap down to the CachedBitmap, the CachedBitmap will
                    // call CreateBitmapFromSource using the TransformedBitmap, which calls 
                    // CopyPixels on the huge TransformedBitmap. We want to avoid chewing up the
                    // CPU and the memory, so we unregister the download event handlers here. 
                    // 
                    source.UnregisterDownloadEventSource();
                } 
            }

            //
            // If the original image has a color profile and IgnoreColorProfile is not one of the create options, 
            // apply the profile so bits are color-corrected.
            // 
            if ((CreateOptions & BitmapCreateOptions.IgnoreColorProfile) == 0 && 
                frame.ColorContexts != null &&
                frame.ColorContexts[0] != null && 
                frame.ColorContexts[0].IsValid &&
                source.Format.Format != PixelFormatEnum.Extended
                )
            { 
                // NOTE: Never do this for a non-MIL pixel format, because the format converter has
                // special knowledge to deal with the profile 
 
                PixelFormat duceFormat = BitmapSource.GetClosestDUCEFormat(source.Format, source.Palette);
                bool changeFormat = (source.Format != duceFormat); 
                ColorContext destinationColorContext;

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

                if (destinationColorContext != null) 
                { 
                    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( 
                            source, 
                            frame.ColorContexts[0],
                            destinationColorContext, 
                            duceFormat
                            );

                        source = colorConvertedBitmap; 
                        if (_isDownloading)
                        { 
                            // Unregister the download events because this is a dummy image. See comment above. 
                            source.UnregisterDownloadEventSource();
                        } 
                        conversionSuccess = true;
                    }
                    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 && !badColorContext && changeFormat)
                    {   // If the conversion failed, we first use 
                        // a FormatConvertedBitmap, and then Color Convert that one... 
                        FormatConvertedBitmap formatConvertedBitmap = new FormatConvertedBitmap(source, duceFormat, source.Palette, 0.0);
 
                        ColorConvertedBitmap colorConvertedBitmap = new ColorConvertedBitmap(
                            formatConvertedBitmap,
                            frame.ColorContexts[0],
                            destinationColorContext, 
                            duceFormat
                            ); 
 
                        source = colorConvertedBitmap;
                        if (_isDownloading) 
                        {
                            // Unregister the download events because this is a dummy image. See comment above.
                            source.UnregisterDownloadEventSource();
                        } 
                    }
                } 
            } 

            if (CacheOption != BitmapCacheOption.None) 
            {
                try
                {
                    // The bitmaps bits could be corrupt, and this will cause an exception if the CachedBitmap forces a decode. 
                    CachedBitmap cachedSource = new CachedBitmap(source, CreateOptions & ~BitmapCreateOptions.DelayCreation, CacheOption);
                    source = cachedSource; 
                    if (_isDownloading) 
                    {
                        // Unregister the download events because this is a dummy image. See comment above. 
                        source.UnregisterDownloadEventSource();
                    }
                }
                catch (Exception e) 
                {
                    RecoverFromDecodeFailure(e); 
                    CreationCompleted = true; // we're bailing out because the decode failed 
                    return;
                } 
            }

            // If CacheOption == OnLoad, no need to keep the stream around
            if (decoder != null && CacheOption == BitmapCacheOption.OnLoad) 
            {
                decoder.CloseStream(); 
            } 
            else if (CacheOption != BitmapCacheOption.OnLoad)
            { 
                //ensure that we don't GC the source
                _finalSource = source;
            }
 
            WicSourceHandle = source.WicSourceHandle;
            IsSourceCached = source.IsSourceCached; 
 
            CreationCompleted = true;
            UpdateCachedSettings(); 

            // Only insert in the imaging cache if download is complete
            if (!IsDownloading)
            { 
                InsertInCache(uri);
            } 
        } 
Пример #12
0
		/// <summary>
		/// Convert color profile of BitmapSource for color management.
		/// </summary>
		/// <param name="bitmapSource">Source BitmapSource</param>
		/// <param name="sourceProfile">Source color profile</param>
		/// <param name="destinationProfile">Destination color profile</param>
		/// <returns>Outcome BitmapSource</returns>
		/// <remarks>Source color profile is color profile embedded in image file and destination color profile is
		/// color profile used by the monitor to which the Window belongs.</remarks>
		public static BitmapSource ConvertColorProfile(BitmapSource bitmapSource, ColorContext sourceProfile, ColorContext destinationProfile)
		{
			var bitmapConverted = new ColorConvertedBitmap();
			bitmapConverted.BeginInit();
			bitmapConverted.Source = bitmapSource;
			bitmapConverted.SourceColorContext = sourceProfile;
			bitmapConverted.DestinationColorContext = destinationProfile;
			bitmapConverted.DestinationFormat = PixelFormats.Bgra32;
			bitmapConverted.EndInit();

			return bitmapConverted;
		}
Пример #13
0
		/// <summary>
		/// Convert Stream to BitmapSource.
		/// </summary>
		/// <param name="stream">Stream</param>
		/// <param name="outerSize">Target outer size</param>
		/// <param name="willReadExif">Whether Exif metadata will be read from Stream</param>
		/// <param name="destinationProfile">Destination color profile for color management</param>
		/// <returns>BitmapSource</returns>
		private static BitmapSource ConvertStreamToBitmapSource(Stream stream, Size outerSize, bool willReadExif, ColorContext destinationProfile)
		{
			if (0 < stream.Position)
				stream.Seek(0, SeekOrigin.Begin);

			var bitmapFrame = BitmapFrame.Create(
				stream,
				BitmapCreateOptions.IgnoreColorProfile | BitmapCreateOptions.PreservePixelFormat, // For color management
				BitmapCacheOption.OnLoad);

			var orientation = willReadExif ? GetExifOrientation(bitmapFrame) : 0; // 0 means invalid.

			var bitmapSource = ResizeAndReflectExifOrientation(bitmapFrame, outerSize, orientation);

			if (destinationProfile != null)
			{
				var sourceProfile = GetColorProfile(bitmapFrame);
				bitmapSource = ConvertColorProfile(bitmapSource, sourceProfile, destinationProfile);
			}

			bitmapSource.Freeze();

			return bitmapSource;
		}
Пример #14
0
		/// <summary>
		/// Convert byte array to BitmapSource applying Uniform transformation.
		/// </summary>
		/// <param name="bytes">Byte array</param>
		/// <param name="outerSize">Target outer size</param>
		/// <param name="willReadExif">Whether Exif metadata will be read from byte array</param>
		/// <param name="destinationProfile">Destination color profile for color management</param>
		/// <returns>BitmapSource</returns>
		internal static async Task<BitmapSource> ConvertBytesToBitmapSourceUniformAsync(byte[] bytes, Size outerSize, bool willReadExif, ColorContext destinationProfile = null)
		{
			if ((bytes == null) || !bytes.Any())
				throw new ArgumentNullException("bytes");

			try
			{
				using (var ms = new MemoryStream())
				{
					await ms.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);

					if (willReadExif || (destinationProfile != null))
					{
						return await Task.Run(() => ConvertStreamToBitmapSource(ms, outerSize, willReadExif, destinationProfile));
					}

					return await Task.Run(() => ConvertStreamToBitmapImageUniform(ms, outerSize));
				}
			}
			catch (Exception ex)
			{
				Debug.WriteLine("Failed to convert byte array to BitmapSource. {0}", ex);

				if (IsImageNotSupported(ex))
					throw new ImageNotSupportedException();

				throw;
			}
		}
Пример #15
0
		/// <summary>
		/// Convert byte array to BitmapSource.
		/// </summary>
		/// <param name="bytes">Byte array</param>
		/// <param name="targetWidth">Target width</param>
		/// <param name="willReadExif">Whether Exif metadata will be read from byte array</param>
		/// <param name="destinationProfile">Destination color profile for color management</param>
		/// <returns>BitmapSource</returns>
		internal static async Task<BitmapSource> ConvertBytesToBitmapSourceAsync(byte[] bytes, double targetWidth, bool willReadExif, ColorContext destinationProfile = null)
		{
			return await ConvertBytesToBitmapSourceAsync(bytes, targetWidth, 0D, willReadExif, destinationProfile).ConfigureAwait(false);
		}
Пример #16
0
        private ImageSource GetBitmapSource(SvgImageElement element, WpfDrawingContext context)
        {
            BitmapSource bitmapSource = this.GetBitmap(element, context);
            if (bitmapSource == null)
            {
                return bitmapSource;
            }

            SvgColorProfileElement colorProfile = (SvgColorProfileElement)element.ColorProfile;
            if (colorProfile == null)
            {
                return bitmapSource;
            }
            else
            {
                BitmapFrame bitmapSourceFrame   = BitmapFrame.Create(bitmapSource);
                ColorContext sourceColorContext = null;
                IList<ColorContext> colorContexts = bitmapSourceFrame.ColorContexts;
                if (colorContexts != null && colorContexts.Count != 0)
                {
                    sourceColorContext = colorContexts[0];
                }
                else
                {
                    sourceColorContext = new ColorContext(bitmapSource.Format);
                    //sourceColorContext = new ColorContext(PixelFormats.Default);
                }

                SvgUriReference svgUri = colorProfile.UriReference;
                Uri profileUri = new Uri(svgUri.AbsoluteUri);

                ColorContext destColorContext = new ColorContext(profileUri);
                ColorConvertedBitmap convertedBitmap = new ColorConvertedBitmap(bitmapSource,
                    sourceColorContext, destColorContext, bitmapSource.Format);

                return convertedBitmap;
            }
        }