Exemplo n.º 1
0
        /// <summary>
        /// When overridden in the derived class, creates a new <see cref="GrhData"/> equal to this <see cref="GrhData"/>
        /// except for the specified parameters.
        /// </summary>
        /// <param name="newCategorization">The <see cref="SpriteCategorization"/> to give to the new
        /// <see cref="GrhData"/>.</param>
        /// <param name="newGrhIndex">The <see cref="GrhIndex"/> to give to the new
        /// <see cref="GrhData"/>.</param>
        /// <returns>
        /// A deep copy of this <see cref="GrhData"/>.
        /// </returns>
        protected override GrhData DeepCopy(SpriteCategorization newCategorization, GrhIndex newGrhIndex)
        {
            var copy = new StationaryGrhData(ContentManager, newGrhIndex, newCategorization, TextureName,
                                             AutomaticSize ? (Rectangle?)null : SourceRect);

            return(copy);
        }
        /// <summary>
        /// Creates the <see cref="StationaryGrhData"/> frames for this <see cref="AutomaticAnimatedGrhData"/>.
        /// </summary>
        /// <param name="directory">The directory containing the frames.</param>
        /// <returns>An array of the <see cref="StationaryGrhData"/> frames.</returns>
        StationaryGrhData[] CreateFrames(string directory)
        {
            // Find all the valid content files
            var allFiles = Directory.GetFiles(directory, "*" + ContentPaths.ContentFileSuffix, SearchOption.TopDirectoryOnly);

            // Filter out the files with invalid naming conventions, and sort them so we animate in the correct order
            var files = SortAndFilterFrameFiles(allFiles);

            // Build the individual frames
            var frames = new StationaryGrhData[files.Length];

            for (var i = 0; i < frames.Length; i++)
            {
                var contentAssetName = ContentAssetName.FromAbsoluteFilePath(files[i], ContentPaths.Build.Grhs).Value;
                var textureAssetName = new TextureAssetName(contentAssetName);
                var frameGrhData     = new StationaryGrhData(this, textureAssetName);
                frames[i] = frameGrhData;
            }

            if (frames.Length == 0)
            {
                throw new Exception("Animation has no frames");
            }

            return(frames);
        }
Exemplo n.º 3
0
        public static void Load(ContentPaths contentPath, IContentManager cm)
        {
            if (IsLoaded)
            {
                return;
            }

            _isLoaded = true;

            var path = GetGrhDataFilePath(contentPath);

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

            if (!File.Exists(path))
            {
                throw new FileNotFoundException("GrhData data file not found.", path);
            }

            _isLoading = true;

            try
            {
                // Create the GrhData DArray
                if (_grhDatas == null)
                {
                    _grhDatas = new DArray <GrhData>(256);
                }
                else
                {
                    _grhDatas.Clear();
                }

                _catDic.Clear();

                _grhDatas.ItemAdded -= AddHandler;
                _grhDatas.ItemAdded += AddHandler;

                _grhDatas.ItemRemoved -= RemoveHandler;
                _grhDatas.ItemRemoved += RemoveHandler;

                // Read and add the GrhDatas in order by their type
                var reader = GenericValueReader.CreateFromFile(path, _rootNodeName);

                LoadGrhDatas(reader, _nonAnimatedGrhDatasNodeName, x => StationaryGrhData.Read(x, cm));
                LoadGrhDatas(reader, _animatedGrhDatasNodeName, AnimatedGrhData.Read);
                LoadGrhDatas(reader, _autoAnimatedGrhDatasNodeName, x => AutomaticAnimatedGrhData.Read(x, cm));

                // Trim down the GrhData array, mainly for the client since it will never add/remove any GrhDatas
                // while in the Client, and the Client is what counts, baby!
                _grhDatas.Trim();
            }
            finally
            {
                _isLoading = false;
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// When overridden in the derived class, creates a new <see cref="GrhData"/> equal to this <see cref="GrhData"/>
        /// except for the specified parameters.
        /// </summary>
        /// <param name="newCategorization">The <see cref="SpriteCategorization"/> to give to the new
        /// <see cref="GrhData"/>.</param>
        /// <param name="newGrhIndex">The <see cref="GrhIndex"/> to give to the new
        /// <see cref="GrhData"/>.</param>
        /// <returns>
        /// A deep copy of this <see cref="GrhData"/>.
        /// </returns>
        protected override GrhData DeepCopy(SpriteCategorization newCategorization, GrhIndex newGrhIndex)
        {
            var copyArray = new StationaryGrhData[_frames.Length];

            Array.Copy(_frames, copyArray, _frames.Length);

            var copy = new AnimatedGrhData(newGrhIndex, newCategorization)
            {
                _frames = copyArray
            };

            copy.SetSpeed(Speed);

            return(copy);
        }
Exemplo n.º 5
0
        StationaryGrhData[] CreateFrames(IList <GrhIndex> frameIndices)
        {
            var frames = new StationaryGrhData[frameIndices.Count];

            for (var i = 0; i < frameIndices.Count; i++)
            {
                frames[i] = GrhInfo.GetData(frameIndices[i]) as StationaryGrhData;
                if (frames[i] == null)
                {
                    const string errmsg =
                        "Failed to load GrhData `{0}`. GrhData `{1}` needs it for frame index `{2}` (0-based), out of `{3}` frames total.";
                    var err = string.Format(errmsg, frames[i], this, i, frameIndices.Count);
                    throw new GrhDataException(this, err);
                }
            }

            return(frames);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Replaces an existing GrhData with a new <see cref="StationaryGrhData"/>.
        /// </summary>
        /// <param name="grhIndex">The index of the <see cref="GrhData"/> to convert.</param>
        /// <returns>The created <see cref="StationaryGrhData"/>, or null if the replacement failed.</returns>
        public static StationaryGrhData ReplaceExistingWithStationary(GrhIndex grhIndex)
        {
            var gd = GetData(grhIndex);

            if (gd == null)
            {
                return(null);
            }

            if (gd is StationaryGrhData)
            {
                return((StationaryGrhData)gd);
            }

            var newGD = new StationaryGrhData(GetContentManager(), gd.GrhIndex, gd.Categorization, null, null);

            Delete(gd);
            AddGrhData(newGD);

            return(newGD);
        }
Exemplo n.º 7
0
        static StationaryGrhData CreateGrhData(GrhIndex grhIndex, IContentManager contentManager,
                                               SpriteCategorization categorization, string texture, Vector2?pos, Vector2?size)
        {
            Debug.Assert(!grhIndex.IsInvalid);

            Rectangle?source;

            if (pos == null || size == null)
            {
                source = null;
            }
            else
            {
                source = new Rectangle(pos.Value.X, pos.Value.Y, size.Value.X, size.Value.Y);
            }

            var gd = new StationaryGrhData(contentManager, grhIndex, categorization, texture, source);

            AddGrhData(gd);
            return(gd);
        }
        /// <summary>
        /// Creates the <see cref="StationaryGrhData"/> frames for this <see cref="AutomaticAnimatedGrhData"/>.
        /// </summary>
        /// <param name="directory">The directory containing the frames.</param>
        /// <returns>An array of the <see cref="StationaryGrhData"/> frames.</returns>
        StationaryGrhData[] CreateFrames(string directory)
        {
            // Find all the valid content files
            var allFiles = Directory.GetFiles(directory, "*" + ContentPaths.ContentFileSuffix, SearchOption.TopDirectoryOnly);

            // Filter out the files with invalid naming conventions, and sort them so we animate in the correct order
            var files = SortAndFilterFrameFiles(allFiles);

            // Build the individual frames
            var frames = new StationaryGrhData[files.Length];
            for (var i = 0; i < frames.Length; i++)
            {
                var contentAssetName = ContentAssetName.FromAbsoluteFilePath(files[i], ContentPaths.Build.Grhs).Value;
                var textureAssetName = new TextureAssetName(contentAssetName);
                var frameGrhData = new StationaryGrhData(this, textureAssetName);
                frames[i] = frameGrhData;
            }

            if (frames.Length == 0)
                throw new Exception("Animation has no frames");

            return frames;
        }
        static string TryGetAbsoluteFilePath(StationaryGrhData gd, ContentPaths contentPath)
        {
            string ret = null;
            var isValid = true;

            try
            {
                ret = gd.TextureName.GetAbsoluteFilePath(contentPath);
                if (!File.Exists(ret))
                    isValid = false;
            }
            catch (ArgumentException)
            {
                isValid = false;
            }

            if (!isValid)
            {
                const string errmsg =
                    "Could not update the size of GrhData `{0}` since the file for the texture named `{1}`" +
                    " could not be found in the ContentPaths.Dev. Expected file: {2}";
                if (log.IsErrorEnabled)
                    log.ErrorFormat(errmsg, gd, gd.TextureName, ret ?? "[NULL]");
                return null;
            }
            else
                return ret;
        }
Exemplo n.º 10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ThreadPoolAsyncCallbackState"/> class.
 /// </summary>
 /// <param name="grhData">The <see cref="StationaryGrhData"/>.</param>
 /// <param name="callback">The callback to invoke when complete.</param>
 /// <param name="userState">The user state object.</param>
 /// <param name="wait">If true, performs a spin-wait. If false, generates the <see cref="Image"/> on the thread.</param>
 /// <param name="bitmap">The unscaled <see cref="Bitmap"/>. Only needed when <paramref name="wait"/> is false.</param>
 public ThreadPoolAsyncCallbackState(StationaryGrhData grhData, GrhImageListAsyncCallback callback, object userState,
                                     bool wait, Bitmap bitmap)
 {
     _grhData = grhData;
     _callback = callback;
     _userState = userState;
     _wait = wait;
     _bitmap = bitmap;
 }
Exemplo n.º 11
0
        /// <summary>
        /// Gets the image key for a <see cref="GrhData"/>.
        /// </summary>
        /// <param name="grhData">The <see cref="GrhData"/> to get the image key for.</param>
        /// <returns>The image key for the <paramref name="grhData"/>.</returns>
        protected virtual string GetImageKey(StationaryGrhData grhData)
        {
            if (grhData == null)
                return string.Empty;

            if (!grhData.GrhIndex.IsInvalid)
            {
                // For normal GrhDatas, we return the unique GrhIndex
                var grhIndex = grhData.GrhIndex;

                if (grhIndex.IsInvalid)
                    return string.Empty;

                return grhIndex.ToString();
            }
            else
            {
                // When we have a frame for a GrhData with an invalid GrhIndex, we prefix a "_" and the use the texture name
                var textureName = grhData.TextureName != null ? grhData.TextureName.ToString() : null;
                if (string.IsNullOrEmpty(textureName))
                    return string.Empty;
                else
                    return "_" + textureName;
            }
        }
Exemplo n.º 12
0
 /// <summary>
 /// Asynchronously gets the <see cref="Image"/> for the given argument.
 /// </summary>
 /// <param name="gd">The <see cref="StationaryGrhData"/> to get the <see cref="Image"/> for.</param>
 /// <param name="callback">The <see cref="GrhImageListAsyncCallback"/> to invoke when the operation has finished.</param>
 /// <param name="userState">The optional user state object to pass to the <paramref name="callback"/>.</param>
 public void GetImageAsync(StationaryGrhData gd, GrhImageListAsyncCallback callback, object userState)
 {
     GetImage(gd, true, callback, userState);
 }
Exemplo n.º 13
0
        /// <summary>
        /// Gets the <see cref="Image"/> for the given argument.
        /// </summary>
        /// <param name="gd">The <see cref="StationaryGrhData"/> to get the <see cref="Image"/> for.</param>
        /// <param name="async">If true, asynchronous mode will be used. This will return null immediately if the desired
        /// <see cref="Image"/> has not yet been created.</param>
        /// <param name="callback">When <see cref="async"/> is false, contains the callback method to invoke when the <see cref="Image"/>
        /// has been created.</param>
        /// <param name="userState">The optional user state object to pass to the <paramref name="callback"/>.</param>
        /// <returns>
        /// The <see cref="Image"/> for the <paramref name="gd"/>, or null if <paramref name="async"/> is set.
        /// </returns>
        Image GetImage(StationaryGrhData gd, bool async, GrhImageListAsyncCallback callback, object userState)
        {
            if (gd == null)
            {
                if (!async)
                {
                    // Return the ErrorImage directly
                    return ErrorImage;
                }
                else
                {
                    // Raise the callback and pass the ErrorImage
                    if (callback != null)
                        callback(this, gd, ErrorImage, userState);
                    return null;
                }
            }

            // Get the key
            var key = GetImageKey(gd);

            // Get the image from the cache
            Image img;
            lock (_imagesSync)
            {
                // Check if the image already exists
                if (!_images.TryGetValue(key, out img))
                {
                    // Image does not exist, so add the placeholder since we are about to create it. Placing the placeholder
                    // in there will make sure that no other threads try to create it at the same time.
                    img = null;
                    _images.Add(key, _placeholder);
                }
            }

            if (!async)
            {
                if (img != null)
                {
                    if (img == _placeholder)
                    {
                        // If we got the placeholder image, do a spin-wait until we get the actual image, then return the image. This will
                        // happen when another thread is creating the image.
                        return SpinWaitForImage(key);
                    }
                    else
                    {
                        // Any other non-null image means that the image was already created, so we can just return it immediately
                        return img;
                    }
                }
                else
                {
                    // Create it on this thread and return it when its done
                    return CreateAndInsertImage(key, gd);
                }
            }
            else
            {
                if (img != null)
                {
                    // When we get the placeholder image while in async mode, this is slightly more annoying since we have
                    // to create another thread to spin-wait on
                    if (img == _placeholder)
                    {
                        // Create the thread to spin-wait on... though only if we were given a callback method. Obviously does no
                        // good to wait for the image when there is no callback method.
                        if (callback != null)
                        {
                            var tpacs = new ThreadPoolAsyncCallbackState(gd, callback, userState, true, null);
                            ExecuteOnThreadPool(tpacs);
                        }
                    }
                    else
                    {
                        // But when we get the actual image, we can just invoke the callback directly from this thread. This is the
                        // once scenario where no threads are created in async mode.
                        if (callback != null)
                            callback(this, gd, img, userState);
                    }
                }
                else
                {
                    // NOTE: The asynchronous aspect is less than optimal due to this.
                    // When originally designing this, I was working under the assumption that SFML would be able to deal with the threading
                    // better. Turns out I was wrong. There are probably some other threading issues that would have to be taken into
                    // account, too, like that content can be disposed on the main thread. I could offload more onto the worker thread
                    // than just the rescaling, such as the generation of the original unscaled bitmap, but the biggest gains come from
                    // the ability to offload the actual image loading. I guess its helpful to have at least a little work offloaded
                    // than to be completely synchronous since that does mean multi-core CPUs can load a bit faster.
                    var bmp = CreateUnscaledBitmap(gd);
                    if (bmp == null)
                    {
                        // If the bitmap failed to be created for whatever reason, use the ErrorImage
                        if (callback != null)
                            callback(this, gd, ErrorImage, userState);

                        lock (_imagesSync)
                        {
                            Debug.Assert(_images[key] == _placeholder);
                            _images[key] = ErrorImage;
                        }
                    }
                    else
                    {
                        // Add the Image creation job to the thread pool
                        var tpacs = new ThreadPoolAsyncCallbackState(gd, callback, userState, false, bmp);
                        ExecuteOnThreadPool(tpacs);
                    }
                }

                // Async always returns null
                return null;
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Gets the tool tip text for a <see cref="StationaryGrhData"/>.
        /// </summary>
        /// <param name="grhData">The <see cref="StationaryGrhData"/>.</param>
        /// <returns>The tool tip text for a <see cref="StationaryGrhData"/>.</returns>
        static string GetToolTipTextStationary(StationaryGrhData grhData)
        {
            // Stationary
            var sb = new StringBuilder();

            sb.AppendLine("Grh: " + grhData.GrhIndex);
            sb.AppendLine("Texture: " + grhData.TextureName);

            var sourceRect = grhData.SourceRect;
            sb.AppendLine("Pos: (" + sourceRect.X + "," + sourceRect.Y + ")");
            sb.Append("Size: " + sourceRect.Width + "x" + sourceRect.Height);

            return sb.ToString();
        }
Exemplo n.º 15
0
        /// <summary>
        /// When overridden in the derived class, creates a new <see cref="GrhData"/> equal to this <see cref="GrhData"/>
        /// except for the specified parameters.
        /// </summary>
        /// <param name="newCategorization">The <see cref="SpriteCategorization"/> to give to the new
        /// <see cref="GrhData"/>.</param>
        /// <param name="newGrhIndex">The <see cref="GrhIndex"/> to give to the new
        /// <see cref="GrhData"/>.</param>
        /// <returns>
        /// A deep copy of this <see cref="GrhData"/>.
        /// </returns>
        protected override GrhData DeepCopy(SpriteCategorization newCategorization, GrhIndex newGrhIndex)
        {
            var copyArray = new StationaryGrhData[_frames.Length];
            Array.Copy(_frames, copyArray, _frames.Length);

            var copy = new AnimatedGrhData(newGrhIndex, newCategorization) { _frames = copyArray };
            copy.SetSpeed(Speed);

            return copy;
        }
Exemplo n.º 16
0
 void ShowGrhInfoForStationary(StationaryGrhData grhData)
 {
     // Stationary
     chkAutoSize.Checked = grhData.AutomaticSize;
     radioStationary.Checked = true;
     radioAnimated.Checked = false;
     var r = grhData.OriginalSourceRect;
     txtX.Text = r.X.ToString();
     txtY.Text = r.Y.ToString();
     txtW.Text = r.Width.ToString();
     txtH.Text = r.Height.ToString();
     txtTexture.ChangeTextToDefault(grhData.TextureName.ToString(), true);
 }
Exemplo n.º 17
0
 /// <summary>
 /// Sets the icon for a stationary <see cref="GrhData"/>.
 /// </summary>
 /// <param name="grhData">The <see cref="StationaryGrhData"/>.</param>
 void SetIconImageStationary(StationaryGrhData grhData)
 {
     _grhImageList.GetImageAsync(grhData, _asyncCallback, this);
 }
Exemplo n.º 18
0
        /// <summary>
        /// Callback for getting an <see cref="Image"/> asynchronously.
        /// We make this static and pass the <see cref="GrhTreeViewNode"/> as the <paramref name="userState"/> so we can
        /// just create a single delegate instance and pass that around, greatly reducing garbage and overhead of async operations.
        /// </summary>
        /// <param name="sender">The <see cref="GrhImageList"/> the callback came from.</param>
        /// <param name="gd">The <see cref="StationaryGrhData"/> that the <paramref name="image"/> is for. May be null if the
        /// <paramref name="image"/> is equal to <see cref="GrhImageList.ErrorImage"/> or null.</param>
        /// <param name="image">The <see cref="Image"/> that was created.</param>
        /// <param name="userState">The optional user state object that was passed to the method.</param>
        static void GrhImageListAsyncCallback(GrhImageList sender, StationaryGrhData gd, Image image, object userState)
        {
            var node = (GrhTreeViewNode)userState;

            var treeView = node.TreeView;
            if (treeView == null)
                return;

            // If the async callback was run on another thread, we will have to use Control.Invoke() to get it to the correct thread.
            // Unfortunately, this will result in a bit of overhead and create some garbage due to the parameter list, but
            // its the best we can do (as far as I can see) and GrhImageList avoids running a new thread when possible anyways so
            // it only really happens while loading.
            if (!treeView.InvokeRequired)
                SetNodeImage(node, image);
            else
                treeView.Invoke(_setNodeImage, node, image);
        }
Exemplo n.º 19
0
 /// <summary>
 /// Gets the <see cref="Image"/> for the given argument.
 /// </summary>
 /// <param name="gd">The <see cref="StationaryGrhData"/> to get the <see cref="Image"/> for.</param>
 /// <returns>
 /// The <see cref="Image"/> for the <paramref name="gd"/>.
 /// </returns>
 public Image GetImage(StationaryGrhData gd)
 {
     return GetImage(gd, false, null, null);
 }
Exemplo n.º 20
0
        /// <summary>
        /// Creates an <see cref="Image"/> for a <see cref="StationaryGrhData"/>, adds it to the cache, and returns it.
        /// Only call this if the image actually needs to be created, and never call this while in the <see cref="_imagesSync"/>
        /// lock!
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="gd">The <see cref="StationaryGrhData"/>.</param>
        /// <returns>The <see cref="Image"/>.</returns>
        Image CreateAndInsertImage(string key, StationaryGrhData gd)
        {
            Image img;

            // The image was null, so we are going to be the ones to create it
            try
            {
                // Try to create the image
                var tex = gd.GetOriginalTexture();
                if (tex == null)
                    img = ErrorImage;
                else
                    img = tex.ToBitmap(gd.OriginalSourceRect, ImageWidth, ImageHeight);
            }
            catch (Exception ex)
            {
                const string errmsg = "Failed to create GrhImageList image for `{0}`. Exception: {1}";
                if (log.IsErrorEnabled)
                    log.ErrorFormat(errmsg, gd, ex);
                if (!(ex is LoadingFailedException))
                    Debug.Fail(string.Format(errmsg, gd, ex));
                img = _errorImage;
            }

            if (log.IsDebugEnabled)
                log.DebugFormat("Created GrhImageList image for `{0}`.", img);

            // If we for some reason have the _placeholder or null image by this point, there is an error in the logic above. But to
            // avoid a deadlock (even though this should never happen), we will just set it to the ErrorImage if it somehow does.
            if (img == null || img == _placeholder)
            {
                const string errmsg = "Created image was either null or the placeholder image, which should never happen.";
                if (log.IsErrorEnabled)
                    log.Error(errmsg);
                Debug.Fail(errmsg);
                img = _errorImage;
            }

            // Add the image to the cache (it will either be the correct image, or the ErrorImage if it failed). Remember that we
            // have already inserted the placeholder image at the key. So we're just replacing the placeholder with the actual image.
            lock (_imagesSync)
            {
                Debug.Assert(_images[key] == _placeholder);
                _images[key] = img;
            }

            // Return the generated image
            return img;
        }
Exemplo n.º 21
0
        StationaryGrhData[] CreateFrames(IList<GrhIndex> frameIndices)
        {
            var frames = new StationaryGrhData[frameIndices.Count];
            for (var i = 0; i < frameIndices.Count; i++)
            {
                frames[i] = GrhInfo.GetData(frameIndices[i]) as StationaryGrhData;
                if (frames[i] == null)
                {
                    const string errmsg =
                        "Failed to load GrhData `{0}`. GrhData `{1}` needs it for frame index `{2}` (0-based), out of `{3}` frames total.";
                    var err = string.Format(errmsg, frames[i], this, i, frameIndices.Count);
                    throw new GrhDataException(this, err);
                }
            }

            return frames;
        }
Exemplo n.º 22
0
 /// <summary>
 /// When overridden in the derived class, creates a new <see cref="GrhData"/> equal to this <see cref="GrhData"/>
 /// except for the specified parameters.
 /// </summary>
 /// <param name="newCategorization">The <see cref="SpriteCategorization"/> to give to the new
 /// <see cref="GrhData"/>.</param>
 /// <param name="newGrhIndex">The <see cref="GrhIndex"/> to give to the new
 /// <see cref="GrhData"/>.</param>
 /// <returns>
 /// A deep copy of this <see cref="GrhData"/>.
 /// </returns>
 protected override GrhData DeepCopy(SpriteCategorization newCategorization, GrhIndex newGrhIndex)
 {
     var copy = new StationaryGrhData(ContentManager, newGrhIndex, newCategorization, TextureName,
         AutomaticSize ? (Rectangle?)null : SourceRect);
     return copy;
 }
Exemplo n.º 23
0
        /// <summary>
        /// Creates an unscaled <see cref="Bitmap"/> of a <see cref="StationaryGrhData"/>.
        /// </summary>
        /// <param name="gd">The <see cref="StationaryGrhData"/>.</param>
        /// <returns>The unscaled <see cref="Bitmap"/>, or null if an error occured.</returns>
        static Bitmap CreateUnscaledBitmap(StationaryGrhData gd)
        {
            Bitmap img;

            // The image was null, so we are going to be the ones to create it
            try
            {
                // Try to create the image
                var tex = gd.GetOriginalTexture();
                if (tex == null)
                    img = null;
                else
                    img = tex.ToBitmap(gd.OriginalSourceRect);
            }
            catch (Exception ex)
            {
                const string errmsg = "Failed to create GrhImageList image for `{0}`. Exception: {1}";
                if (log.IsErrorEnabled)
                    log.ErrorFormat(errmsg, gd, ex);
                if (!(ex is LoadingFailedException) && !(ex is OutOfMemoryException))
                    Debug.Fail(string.Format(errmsg, gd, ex));
                img = null;
            }

            return img;
        }