Search code examples
c#iconsesri

BitmapImage load difference between pack:// and c:\ uri


I've got a strange bug when trying to load image from file instead of pack://

I'm using a ESRI map in accelerated mode and want user to be able to use own map icons (copying them to Icons directory).

I've made an icon manager helper, loading icons at program start:

            public static void Reload()
            {
                _icons = new Dictionary<string, BitmapImage>();

                // read pack://
                var asm = Assembly.GetEntryAssembly();
                var resName = asm.GetName().Name + ".g.resources";
                using (var stream = asm.GetManifestResourceStream(resName))
                    if (stream != null)
                        using (var reader = new System.Resources.ResourceReader(stream))
                        {
                            var regex = new Regex(@"images\/(.+\.png)");
                            foreach (DictionaryEntry entry in reader)
                            {
                                var name = string.Empty;
                                var matched = regex.Match(entry.Key.ToString());
                                if (matched.Groups.Count == 2)
                                {
                                    name = matched.Groups[1].Value;
                                }

                                BitmapImage image = null;
                                try
                                {
                                    image = new BitmapImage();
                                    image.BeginInit();
                                    image.UriSource =
                                        new Uri(@"pack://application:,,,/Client;component/Images/" + matched.Groups[1].Value, UriKind.RelativeOrAbsolute);
                                    image.EndInit();
                                }
                                catch(Exception e)
                                {
                                    Logger.Log(e);
                                    image = null;
                                }

                                if ((name != string.Empty) && (image != null)) 
                                    _icons.Add(@"resource\" + name, image);
                            }
                        }

                // read directory
                var fregex = new Regex(@"\\(.+\.png)$");
                string[] files = null;
                try { files = Directory.GetFiles(Settings.Default.ExternalIconsPath, "*.png", SearchOption.AllDirectories); }
                    catch (Exception e) { Logger.Log(e); }

                if (files != null)
                    foreach (var file in files)
                    {
                        var name = string.Empty;
                        BitmapImage image = null;
                        try
                        {
                            image = new BitmapImage;
                            image.BeginInit();
                            image.UriSource = new Uri(file, UriKind.RelativeOrAbsolute);
                            image.EndInit();

                            var match = fregex.Match(file);
                            if (match.Groups.Count == 2) name = match.Groups[1].Value;
                        }
                        catch (Exception e)
                        {
                            Logger.Log(e); 
                            image = null; 
                        }

                        if ((name == string.Empty) || (image == null)) continue;
                        if (!_icons.ContainsKey(name)) _icons.Add(name, image);
                    }
            }

public static BitmapImage GetImageByName(string name)
        {
            var defaultImage = new BitmapImage(new Uri(@"pack://application:,,,/Client;component/Images/_default_icon_32_32.png", UriKind.RelativeOrAbsolute));
            if ((name == null) || (_icons == null)) return defaultImage;

            BitmapImage image;
            var res = _icons.TryGetValue(name, out image);
            return res ? image : defaultImage;
        }

Later in code i'm use it like this:

        cameraGraphic.Symbol = new PictureMarkerSymbol
            {
                OffsetX = 12, 
                OffsetY = 12, 
                //Source = IconManager.GetImageByName("resource\\blue_eye_buble2_24_24.png"),
                Source = IconManager.GetImageByName("blue_eye_buble2_24_24.png"),
                Width = 24, 
                Height = 24
            };

It works without any problem, but when I set UseAcceleratedDisplay="True" (DirectX acceleration) to ESRI map layer I got an System.NullReferenceException when use icons from file (I tried same icons). Icons from pack:// works good in accelerated and non accelerated modes.

What is the difference ? Should I use another way to load icons from file ?


Solution

  • I beat it. It's all about relative and absolute paths. This works just fine:

    image.UriSource = new Uri("file:///" + baseDir + file, UriKind.Absolute);