ImageSourceTypeConverter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Print / Reach / Serialization / ImageSourceTypeConverter.cs / 3 / ImageSourceTypeConverter.cs

                            /*++ 

    Copyright (C) 2004 - 2005 Microsoft Corporation
    All rights reserved.
 
    Module Name:
        ImageSourceTypeConverter.cs 
 
    Abstract:
        This file implements the ImageSourceTypeConverter 
        used by the Xps Serialization APIs for serializing
        images to a Xps package.

    Author: 
        [....] ([....]) 1-December-2004
 
    Revision History: 
--*/
 
using System;
using System.Net;
using System.Collections;
using System.Collections.Specialized; 
using System.Collections.Generic;
using System.ComponentModel; 
using System.IO; 
using System.IO.Packaging;
using System.Windows.Media; 
using System.Windows.Media.Imaging;
using System.Windows.Xps.Packaging;
using System.Security;
using System.Security.Permissions; 
using MS.Internal.ReachFramework;
using System.Windows.Markup; 
using MS.Internal.IO.Packaging; 

namespace System.Windows.Xps.Serialization 
{
    /// 
    /// This class implements a type converter for converting
    /// images to Uris.  It handles the writing of the image 
    /// to a Xps package and returns a package URI to the
    /// caller.  It also handles reading an image from a 
    /// Xps package given a Uri. 
    /// 
    public class ImageSourceTypeConverter : ExpandableObjectConverter 
    {
        #region Public overrides for ExpandableObjectConverted

        ///  
        /// Returns whether this converter can convert an object
        /// of the given type to the type of this converter. 
        ///  
        /// 
        /// An ITypeDescriptorContext that provides a format context. 
        /// 
        /// 
        /// A Type that represents the type you want to convert from.
        ///  
        /// 
        /// true if this converter can perform the conversion; 
        /// otherwise, false. 
        /// 
        public 
        override
        bool
        CanConvertFrom(
            ITypeDescriptorContext      context, 
            Type                        sourceType
            ) 
        { 
            return IsSupportedType(sourceType);
        } 

        /// 
        /// Returns whether this converter can convert the object
        /// to the specified type. 
        /// 
        ///  
        /// An ITypeDescriptorContext that provides a format context. 
        /// 
        ///  
        /// A Type that represents the type you want to convert to.
        /// 
        /// 
        /// true if this converter can perform the conversion; 
        /// otherwise, false.
        ///  
        public 
        override
        bool 
        CanConvertTo(
            ITypeDescriptorContext      context,
            Type                        destinationType
            ) 
        {
            return IsSupportedType(destinationType); 
        } 

        ///  
        /// Converts the given value to the type of this converter.
        /// 
        /// 
        /// An ITypeDescriptorContext that provides a format context. 
        /// 
        ///  
        /// The CultureInfo to use as the current culture. 
        /// 
        ///  
        /// The Object to convert.
        /// 
        /// 
        /// An Object that represents the converted value. 
        /// 
        public 
        override 
        object
        ConvertFrom( 
            ITypeDescriptorContext              context,
            System.Globalization.CultureInfo    culture,
            object                              value
            ) 
        {
            if( value == null ) 
            { 
                throw new ArgumentNullException("value");
            } 

            if (!IsSupportedType(value.GetType()))
            {
                throw new NotSupportedException(ReachSR.Get(ReachSRID.Converter_ConvertFromNotSupported)); 
            }
 
            throw new NotImplementedException(); 
        }
 
        /// 
        /// Converts the given value object to the specified type,
        /// using the arguments.
        ///  
        /// 
        /// An ITypeDescriptorContext that provides a format context. 
        ///  
        /// 
        /// A CultureInfo object. If null is passed, the current 
        /// culture is assumed.
        /// 
        /// 
        /// The Object to convert. 
        /// 
        ///  
        /// The Type to convert the value parameter to. 
        /// 
        ///  
        /// The Type to convert the value parameter to.
        /// 
        /// 
        /// Critical - 1)   Calls GetImageMimeType which is security critical 
        ///
        /// 
        ///            2)  Calls ReEncodeBitmap which is security critical 
        ///
        /// TreatAsSafe: 
        ///            1) MimeTypes demands Unrestriced registry access. Presumably
        ///               to discover registered bitmaps.  Registry information is not passed to caller.
        ///
        ///            2) Getting codecinfo data is OK (Direct quote from CodecInfo ) 
        ///
        ///            3) Uses the information to detrmine Bitmap Source type so it can be serialzied into stream with the same type. 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        public 
        override
        object
        ConvertTo(
            ITypeDescriptorContext              context, 
            System.Globalization.CultureInfo    culture,
            object                              value, 
            Type                                destinationType 
            )
        { 
            Toolbox.StartEvent(MS.Utility.EventTraceGuidId.DRXCONVERTIMAGEGUID);

            if( context == null )
            { 
                throw new ArgumentNullException("context");
            } 
            if (!IsSupportedType(destinationType)) 
            {
                throw new NotSupportedException(ReachSR.Get(ReachSRID.Converter_ConvertToNotSupported)); 
            }

            //
            // Check that we have a valid BitmapSource instance. 
            //
            BitmapSource bitmapSource = (BitmapSource)value; 
            if (bitmapSource == null) 
            {
                throw new ArgumentException(ReachSR.Get(ReachSRID.MustBeOfType, "value", "BitmapSource")); 
            }

            //
            // Get the current serialization manager. 
            //
            PackageSerializationManager manager = (PackageSerializationManager)context.GetService(typeof(XpsSerializationManager)); 
 
            //Get the image Uri if it has already been serialized
            Uri imageUri = GetBitmapSourceFromImageTable(manager, bitmapSource); 

            //
            // Get the current page image cache
            // 
            Dictionary currentPageImageTable = manager.ResourcePolicy.CurrentPageImageTable;
            if (imageUri != null) 
            { 
                int uriHashCode = imageUri.GetHashCode();
                if(!currentPageImageTable.ContainsKey(uriHashCode)) 
                {
                   //
                   // Also, add a relationship for the current page to this image
                   // resource.  This is needed to conform with Xps specification. 
                   //
                   manager.AddRelationshipToCurrentPage(imageUri, XpsS0Markup.ResourceRelationshipName); 
                   currentPageImageTable.Add(uriHashCode, imageUri); 
                }
            } 
            else
            {
                //
                // This image as never serialized before so we will do it now. 
                // Retrieve the image serialization service from the resource policy
                // 
                IServiceProvider resourceServiceProvider = manager.ResourcePolicy; 

                XpsImageSerializationService imageService = (XpsImageSerializationService)resourceServiceProvider.GetService(typeof(XpsImageSerializationService)); 
                if (imageService == null)
                {
                    throw new XpsSerializationException(ReachSR.Get(ReachSRID.ReachSerialization_NoImageService));
                } 

                // 
                // Obtain a valid encoder for the image. 
                //
                BitmapEncoder encoder = imageService.GetEncoder(bitmapSource); 
                string imageMimeType = GetImageMimeType(encoder);

                bool isSupportedMimeType = imageService.IsSupportedMimeType(bitmapSource);
 
                //
                // Acquire a writable stream from the serialization manager and encode 
                // and serialize the image into the stream. 
                //
                XpsResourceStream resourceStream = manager.AcquireResourceStream(typeof(BitmapSource), imageMimeType); 
                bool bCopiedStream = false;

                BitmapFrame bitmapFrame = bitmapSource as BitmapFrame;
 
                if (isSupportedMimeType &&
                    bitmapFrame != null && 
                    bitmapFrame.Decoder != null 
                    )
                { 
                    BitmapDecoder decoder = bitmapFrame.Decoder;
                    try
                    {
                        Uri sourceUri = new Uri(decoder.ToString()); 
                        Stream srcStream = MS.Internal.WpfWebRequestHelper.CreateRequestAndGetResponseStream(sourceUri);
                        CopyImageStream(srcStream, resourceStream.Stream); 
                        srcStream.Close(); 
                        bCopiedStream = true;
                    } 
                    catch (UriFormatException)
                    {
                        //the uri was not valid we will re-encode the image below
                    } 
                    catch (WebException)
                    { 
                        //Web Request failed we will re-encode the image below 
                    }
                } 

                if (!bCopiedStream)
                {
                    Stream stream = new MemoryStream(); 
                    ReEncodeImage(bitmapSource, encoder, stream);
                    stream.Position = 0; 
                    CopyImageStream(stream, resourceStream.Stream); 
                }
 
                //
                // Make sure to commit the resource stream by releasing it.
                //
                imageUri = resourceStream.Uri; 
                manager.ReleaseResourceStream(typeof(BitmapSource));
 
                AddBitmapSourceToImageTables(manager, imageUri); 
            }
 
            Toolbox.EndEvent(MS.Utility.EventTraceGuidId.DRXCONVERTIMAGEGUID);

            return imageUri;
        } 

        ///  
        /// Gets a collection of properties for the type of object 
        /// specified by the value parameter.
        ///  
        /// 
        /// An ITypeDescriptorContext that provides a format context.
        /// 
        ///  
        /// An Object that specifies the type of object to get the
        /// properties for. 
        ///  
        /// 
        /// An array of type Attribute that will be used as a filter. 
        /// 
        /// 
        /// A PropertyDescriptorCollection with the properties that are
        /// exposed for the component, or null if there are no properties. 
        /// 
        public 
        override 
        PropertyDescriptorCollection
        GetProperties( 
            ITypeDescriptorContext      context,
            object                      value,
            Attribute[]                 attributes
            ) 
        {
            throw new NotImplementedException(); 
        } 

        #endregion Public overrides for ExpandableObjectConverted 

        #region Private static helper methods

        ///  
        /// Looks up the type in a table to determine
        /// whether this type is supported by this 
        /// class. 
        /// 
        ///  
        /// Type to lookup in table.
        /// 
        /// 
        /// True is supported; otherwise false. 
        /// 
        private 
        static 
        bool
        IsSupportedType( 
            Type            type
            )
        {
            bool isSupported = false; 

            foreach (Type t in SupportedTargetTypes) 
            { 
                if (t.Equals(type))
                { 
                    isSupported = true;
                    break;
                }
            } 

            return isSupported; 
        } 

        private 
        static
        void
        CopyImageStream( Stream sourceStream, Stream destinationStream )
        { 
            byte[] buffer= new byte[_readBlockSize];
            int bytesRead = PackagingUtilities.ReliableRead( sourceStream, buffer, 0, _readBlockSize); 
            while( bytesRead > 0 ) 
            {
                destinationStream.Write(buffer, 0, bytesRead); 
                bytesRead = PackagingUtilities.ReliableRead( sourceStream, buffer, 0, _readBlockSize);
            }
        }
 
        /// 
        /// Critical - 1)  Asserts mediaAccessPermission for non site of origin data 
        ///  
        [SecurityCritical]
        private 
        static
        void
        ReEncodeImage(BitmapSource bitmapSource, BitmapEncoder encoder, Stream stream )
        { 
            BitmapFrame bitmapFrame = null;
            // 
            // The uri the BitmapFrame.Create will use is null since it is accessing  metadata at 
            // construction and its uri is still null
            // 
            CodeAccessPermission mediaAccessPermission = SecurityHelper.CreateMediaAccessPermission(null);

            if (mediaAccessPermission != null)
            { 
                mediaAccessPermission.Assert(); //BlessedAssert
            } 
            try 
            {
                bitmapFrame = BitmapFrame.Create(bitmapSource); 
            }
            finally
            {
                if (mediaAccessPermission != null) 
                {
                    CodeAccessPermission.RevertAssert(); 
                } 
            }
            encoder.Frames.Add(bitmapFrame); 


            if (mediaAccessPermission != null)
            { 
                mediaAccessPermission.Assert(); //BlessedAssert
            } 
            try 
            {
                encoder.Save(stream); 
            }
            finally
            {
                if (mediaAccessPermission != null) 
                {
                    CodeAccessPermission.RevertAssert(); 
                } 
            }
 
        }

        /// 
        /// Calculates a Crc32 value for a given BitmapSource. 
        /// 
        ///  
        /// BitmapSource containing image data to calculate 
        /// the Crc32 value for.
        ///  
        /// 
        /// A 32-bit unsigned integer Crc32 value.
        /// 
        ///  
        /// Critical: This code calls an inernal PresentationCore function CriticalCopyPixels
        /// TreatAsSafe: We just calcualte 32-bit CRC, image itself is not exposed 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private 
        static
        UInt32
        CalculateImageCrc32(
            BitmapSource    bitmapSource 
            )
        { 
            Crc32 crc32 = new Crc32(); 

            int width = bitmapSource.PixelWidth; 
            int height = bitmapSource.PixelHeight;
            int stride = (width * bitmapSource.Format.BitsPerPixel + 7) / 8;
            Int32Rect rect = new Int32Rect(0, 0, width, 1);
            byte[] pixels = new byte[stride]; 

 
            for (int i = 0; i < height; i += 1) 
            {
                bitmapSource.CriticalCopyPixels(rect, pixels, stride, 0); 
                rect.Y++;

                crc32.AddData(pixels);
            } 

            return crc32.Crc32Value; 
        } 

 
        /// 
        /// Critical - 1)   Asserts to access the registry.  May return path information which
        ///                 could disclose windows directory (ie. c:\windows\media\sound.wav)
        /// 
        ///            2)   Access unmanaged code, codecs
        /// 
        ///  
        [SecurityCritical]
        private 
        static
        string
        GetImageMimeType(
            BitmapEncoder encoder 
        )
        { 
            string mimetypes; 
            string imageMimeType = "image/unknown";
            // 
            // To determine the mime-type of the image we just grab
            // the first one supported by this encoder and use that.
            //
            PermissionSet permissions = new PermissionSet(null); 
            permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
            permissions.AddPermission(new RegistryPermission(PermissionState.Unrestricted)); 
            permissions.Assert(); 
            try
            { 
                mimetypes = encoder.CodecInfo.MimeTypes;
            }
            finally
            { 
                CodeAccessPermission.RevertAssert();
            } 
            int comma = mimetypes.IndexOf(','); 
            if (comma != -1)
            { 
                imageMimeType = mimetypes.Substring(0, comma);
            }
            else
            { 
                imageMimeType = mimetypes;
            } 
            return imageMimeType; 
        }
 

        private
        Uri
        GetBitmapSourceFromImageTable(PackageSerializationManager manager, BitmapSource bitmapSource) 
        {
            Uri imageUri = null; 
 
            //Initialize cache values
            _uriHashValue = 0; 
            _crc32HashValue = 0;

            BitmapFrame bitmapFrame = bitmapSource as BitmapFrame;
 
            //Use the Uri hash table if we have a bitmap with a Uri
            if (bitmapFrame != null && 
                bitmapFrame.Decoder != null) 
            {
                String sourceUri  = bitmapFrame.Decoder.ToString(); 
                if (sourceUri != null)
                {
                    _uriHashValue = sourceUri.GetHashCode();
 
                    Dictionary imageUriHashTable = manager.ResourcePolicy.ImageUriHashTable;
                    if (imageUriHashTable.ContainsKey(_uriHashValue)) 
                    { 
                        imageUri = imageUriHashTable[_uriHashValue];
                    } 
                }
            }

            //Checking the UriHash for zero tells us if the uri of the bitmap was checked and if it returned a valid Uri 
            if (_uriHashValue == 0)
            { 
                // 
                // Calculate the image Crc32 value.  This is used as a key
                // into the image cache. 
                //
                _crc32HashValue = CalculateImageCrc32(bitmapSource);

                // 
                // Get the current image cache
                // 
                Dictionary imageCrcTable = manager.ResourcePolicy.ImageCrcTable; 

                // 
                // The image has already been cached (and therefore serialized).
                // No need to serialize it again so we just return the Uri in the
                // package where the original was serialized. For that Uri returned
                // a relationship is only created if this has not been included on 
                // the current page before.
                // 
                if (imageCrcTable.ContainsKey(_crc32HashValue)) 
                {
                    imageUri = imageCrcTable[_crc32HashValue]; 
                }
            }

            return imageUri; 
        }
 
        private 
        void
        AddBitmapSourceToImageTables(PackageSerializationManager manager, Uri imageUri) 
        {
            if (_uriHashValue != 0)
            {
                manager.ResourcePolicy.ImageUriHashTable.Add(_uriHashValue,imageUri); 
                _uriHashValue = 0;
            } 
            else 
            {
                manager.ResourcePolicy.ImageCrcTable.Add(_crc32HashValue, imageUri); 
                _crc32HashValue = 0;
            }

            manager.ResourcePolicy.CurrentPageImageTable.Add(imageUri.GetHashCode(), imageUri); 
        }
 
        #endregion Private static helper methods 

        #region Private static data 

        /// 
        /// A table of supported types for this type converter
        ///  
        private static Type[] SupportedTargetTypes = {
            typeof(Uri) 
        }; 
        private static readonly int _readBlockSize = 1048576; //1MB
 
        /// 
        /// Cached hash values for image tables
        /// 
        private int _uriHashValue; 
        private UInt32 _crc32HashValue;
        #endregion Private static data 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK