Laden...

Fehler beim Laden von BitmapImage aus Resouce

Erstellt von core vor 15 Jahren Letzter Beitrag vor 14 Jahren 9.982 Views
C
core Themenstarter:in
157 Beiträge seit 2008
vor 15 Jahren
Fehler beim Laden von BitmapImage aus Resouce

Hi Leute,

ich hab wieder einmal ein Problem, was sicherlich wieder ganz leicht zu lösen ist, an dem ich mir aber seit 2 Stunden die Zähne ausbeisse. Folgende Situation:

Ich habe ein Assembly-Projekt, in der eine .resx-Datei liegt, in der wiederum Bilder gespeichert sind. Nun möchte ich über den RessourceManager genau auf diese Bilder zugreifen und sie dann in meinem Applikation-Projekt einbinden. Im Augenblick habe ich es so realisiert:

Das ist meine Klasse in der Assembly, über die ich auf die Bilder, die in der Datei MyPictures.resx gespeichert sind zugreife:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Resources;

namespace MyRessources
{
    public class MyResourceManager
    {
        public BitmapImage getImage(string imageName) 
        {
            try
            {
                ResourceManager rm = new ResourceManager(this.GetType().Namespace + ".MyPictures", this.GetType().Assembly);
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage = (BitmapImage)rm.GetObject(imageName);
                bitmapImage.EndInit();
                return bitmapImage;
            }
            catch (Exception exception) 
            {
                MessageBox.Show(exception.ToString());
                return null;
            }
        }

        public String getString(string stringName)
        {
            try
            {
                ResourceManager rm = new ResourceManager(this.GetType().Namespace + "." + stringName, this.GetType().Assembly);
                return rm.GetString(stringName);
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.ToString());
                return null;
            }
        }
    }
}

Das ist eine Klasse in meiner Applikation, in der auf die Resourcen zugegriffen wird:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using MyRessources;

namespace MyApplication
{
    public partial class MyClass : Page
    {
        public MyClass()
        {
            InitializeComponent();
            loadImage();
        }

        public void loadImage()
        {
              // funktioniert nicht
              MyResourceManager myResouceManager = new MyResourceManager();
              this.MyImage.Source = myResouceManager.getImage("Bild.jpg");

              // funktioniert einwandfrei
              MessageBox.Show(myResouceManager.getString("TestString"));

        }
    }
}

Als Fehlermeldung wird mir "System.NullReferenceException: Object reference not set to an instance of an object. at MyRescources.MyResourceManager.getImage(String imageName)." ausgegeben.
Scheinbar wird das Bild nicht gefunden, aber warum? Über die Methode getString() rufe ich in einer anderen Resource-Datei Strings ab und das klappt wiederum ohne Probleme ?(

Was mache ich falsch? Kann mir einer von Euch bitte helfen?

582 Beiträge seit 2008
vor 15 Jahren

Probier es mal so



                BitmapImage bi = new BitmapImage();
                // BitmapImage.UriSource muss in einem BeginInit/EndInit Block stehen
                bi.BeginInit();
                // Bitmap mag nur Uri´s
                bi.UriSource = new Uri(path, UriKind.RelativeOrAbsolute);
                // Damit eine eigenständige Instanz erstellt wird, die unabhängig von der Resource ist
                bi.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
                bi.EndInit();
                // Zuordnung der Bitmap
                this.MyImage.Source = bi;

Damit erzeugst du eine eigenständiges Bitmap und kannst dieses auch direkt zu Ordnen

Ich habe mich zwar noch nie damit beschäftigt, aber für mich sieht der Zugriff unterschiedlich aus


ResourceManager rm = new ResourceManager(this.GetType().Namespace + ".MyPictures", this.GetType().Assembly);
ResourceManager rm = new ResourceManager(this.GetType().Namespace + "." + stringName, this.GetType().Assembly);
                

Gruß dat Tala

C
core Themenstarter:in
157 Beiträge seit 2008
vor 15 Jahren

Hi Taladan,

erst mal danke für deine Idee. Aber ich will die Images schon aus einer Resource und nicht aus dem Dateisystem laden.

Deine Hinweis

Ich habe mich zwar noch nie damit beschäftigt, aber für mich sieht der Zugriff unterschiedlich aus hatte mich dann auf eine Idee und dann auch ein ganzes Stück weiter gebracht.

Die Excepiton, die mir die Applikation ausgibt, wurde deshalb ausgegeben, weil ich zwar die richtige Resource angezapft hatte,


ResourceManager rm = new ResourceManager(this.GetType().Namespace + "." + stringName, this.GetType().Assembly);
return rm.GetString(stringName);

aber in der Resource das Image "Bild.jpg" gesucht habe. Dieses konnte der ResourceManager aber nicht finden und gab null zurück. Der entscheidende Fehler meinerseits war, dass ich die Datei-Endung nicht weggelassen habe. Folgender Code findet und läd das Image aus der Resource, ohne das ich etwas an der Assembly ändern musste.

Applikation:


public void loadImage()
{   
      MyResourceManager myResouceManager = new MyResourceManager();
      this.MyImage.Source = myResouceManager.getImage("Bild");
}

Nun habe ich aber schon wieder ein Problem. Das Image das mir der ResourceManager aus der Resource läd ist im Format System.Drawing.Bitmap. Ich brauche aber das Image im Format System.Windows.Media.ImageSource. Bisher sind alle meine versuche, das eine in das andere Format zu konvertiren gescheitert.

Ich habe auch schon im Netz recherchiert, aber alle Lösungsvorschläge, die ich dort gefunden habe funktionieren entweder nicht, oder lösen eine SecurityException aus.

kann mir bitte einer von Euch weiterhelfen!! 🤔

C
core Themenstarter:in
157 Beiträge seit 2008
vor 15 Jahren

Hi Leute,

ich habe entlich eine Lösung für mein Problem gefunden. Für alle von Euch, die es interessiert hier meine Lösung:


public BitmapImage getImage(string imageName, string imageType) 
{
           String resourcePath = this.GetType().Namespace + ".MyPicResources";
           Assembly resourceAssembly = this.GetType().Assembly;
           ResourceManager resourceManager = new ResourceManager(resourcePath, resourceAssembly);
           System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)resourceManager.GetObject(imageName);
           System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
           switch(imageType) 
           {
                 case "jpg" : bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                 break;
                 case "png": bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
                 break;
           }
           System.Windows.Media.Imaging.BitmapImage bitmapImage = new System.Windows.Media.Imaging.BitmapImage();
           bitmapImage.BeginInit();
           bitmapImage.StreamSource = new System.IO.MemoryStream(memoryStream.ToArray());
           bitmapImage.EndInit();
           return bitmapImage;
}

Sollte einer von Euch vieleicht noch eine bessere und einfachere Lösung haben, währe ich daran natülich immer noch interessiert.

Wie immer Danke an alle, die mir geholfen haben. 👍

6.862 Beiträge seit 2003
vor 15 Jahren

Müssen es wirklich *.resx Dateien sein? Diese Art von Ressourcen werden in WPF wie du merkst nur schmerzlich unterstützt. Die sind auf Windows Forms zugeschnitten.

Mit WPF gibts viel schönere Möglichkeiten. Im Prinzip brauchst du nur die Dateien die du magst der Solution hinzufügen und die Build Action auf Resource stellen, nicht auf embedded Resource, dann hat man die gleichen Probleme wie oben.

Wenn die Resourcen so hinzugefügt werden, kann man wie Taladan gezeigt hat, mit einer schönen Uri drauf zugreifen und muss sich absolut gar nicht um irgendwelche Resourcen Details kümmern. Angenommen du fügst der Solution einen Ordner Images hinzu und hast dort drin ein Bild1.jpg als Resource definiert. Dann kannst du innerhalb der Assembly mit einer Uri "Images/Bild1.jpg" jederzeit drauf zugreifen. Da du meintest du hast ne extra Assembly sieht der Zugriff ein wenig anders aus, da man halt die Assembly noch angeben muss.
Beispielsweise

img.Source = new BitmapImage(
new Uri("NameDerReferenziertenAssembly;component/Images/Bild1.jpg", UriKind.Relative));

Obwohl es aussieht wie ein Dateisystemzugriff, ist es keiner, es wird aus den Resoucen gelesen. URIs werden in WPF für so ziemlich jegliche Angabe einer Quelle verwendet weil sie sowohl auf Ziele im Dateisystem, UNC Pfade, Assembly Resourcen oder URLs verweisen können und damit sehr allgemein gehalten sind. Im Gegensatz zu Windows Forms spielt es bei WPF nur eine untergeordnete Rolle woher die Daten kommen.

Baka wa shinanakya naoranai.

Mein XING Profil.

P
1 Beiträge seit 2008
vor 15 Jahren

Klingt soweit alles sehr gut, gibt keine Exception, aber mein Bildchen wird trotzdem nicht angezeigt 😦

Daher die konkrete Frage: Was muß da als
NameDerReferenziertenAssembly
eingetragen werden?

Meine Solution heißt pv, und der zugehörige namespace pvWindow1

ich bin etwas ratlos, weil ich an dieser Stelle bei MSDN immer was von

pack://application,,,/Images/Bild1.jpg

lese http://msdn.microsoft.com/en-us/library/aa970069.aspx .

Gruß und Dank.

3.430 Beiträge seit 2007
vor 15 Jahren

Hallo pvWindow1,

willkommen im Forum...

Da ich annehmen, dass deine Bilder und die Solution in der gleichen Assembly liegen, brauchst du den NamenDerReferenzierteAssembly nicht angeben.

D.h. es funktioniert schon so


img.Source = new BitmapImage(new Uri("Images/Bild1.jpg", UriKind.Relative));

Natürlich musst du die BuildAction des Bilds noch auf Resource stellen, dann funktioniert es.

Aber das hat eigentlich alles schon Talla geschrieben.

Gruss
Michael

J
18 Beiträge seit 2008
vor 14 Jahren

Hallo zusammen!

Sorry für's grave digging, aber da dies auch mein Problem ist ...

Ich habe es genauso gemacht, wie Ihr beschrieben habt: Ich habe eine Ordner in der Solution names "Images" erstellt und da hinein eine jpg gelegt. Bei Buildvorgang war "Resource" bereits voreingestellt. Möchte ich nun auf das Bild per


ImageBrush texture = new ImageBrush();
texture.ImageSource = new BitmapImage(new Uri("Images/white.jpg", UriKind.Relative));

zugreifen, erhalte ich zur Laufzeit die Fehlermeldung: "Ein Teil des Pfades "MeinPfad\WPFTest\bin\Debug\Images\white.jpg" konnte nicht gefunden werden."

Ich habe dann auch "In Ausgabeverzeichnis kopieren" mit "immer kopieren" und "kopieren, wenn neuer" belegt, was aber auch keine (positiven) Auswirkungen hatte.

Ach ja, ich starte meine Applikation direkt aus Visual Studio heraus (F5). Das sollte ja aber trotzdem gehen, oder nicht?

Besten Dank im Voraus!

EDIT: Zumindest damit geht es:


ImageBrush texture = new ImageBrush();
texture.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Images/white.jpg"));