कोड में WPF छवि स्रोत सेट करना


325

मैं कोड में एक WPF छवि स्रोत सेट करने की कोशिश कर रहा हूँ। छवि परियोजना में संसाधन के रूप में एम्बेडेड है। उदाहरणों को देखकर मैं नीचे दिए गए कोड के साथ आया हूं। किसी कारण से यह काम नहीं करता है - छवि दिखाई नहीं देती है।

डीबग करके मैं देख सकता हूं कि स्ट्रीम में छवि डेटा है। तो क्या गलत हुआ?

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
PngBitmapDecoder iconDecoder = new PngBitmapDecoder(iconStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
ImageSource iconSource = iconDecoder.Frames[0];
_icon.Source = iconSource;

आइकन को कुछ इस तरह परिभाषित किया गया है: <Image x:Name="_icon" Width="16" Height="16" />


यदि छवि एक स्थानीय ड्राइव पर है, <Image Source="some_fully_qualified_path">तो XAML में कभी भी विफल नहीं होता है।
लॉरी स्टर्न

@ लॉरीस्टार पूरे बिंदु यह है कि हम इसे निर्धारित करने के लिए पथ और आवश्यकता कोड नहीं जानते हैं। Windows GUI प्रोग्रामिंग में किसी नए के रूप में, मुझे यह स्वीकार करना होगा कि WinForms इस XAML बकवास की तुलना में अधिक आकर्षक लगता है।
एलेक्स जानसन

जवाबों:


416

आपके जैसी ही समस्या होने और कुछ पढ़ने के बाद, मैंने इसका हल खोजा - पैक यूआरआई

मैंने निम्नलिखित कोड में किया:

Image finalImage = new Image();
finalImage.Width = 80;
...
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png");
logo.EndInit();
...
finalImage.Source = logo;

या छोटा, एक और BitmapImage कंस्ट्रक्टर का उपयोग करके:

finalImage.Source = new BitmapImage(
    new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png"));

URI भागों में टूट गया है:

  • प्राधिकरण: application:///
  • पथ: एक संसाधन फ़ाइल का नाम जिसे एक संदर्भित असेंबली में संकलित किया गया है। पथ को निम्न प्रारूप के अनुरूप होना चाहिए:AssemblyShortName[;Version][;PublicKey];component/Path

    • विधानसभाशॉर्टनाम: संदर्भित विधानसभा का संक्षिप्त नाम।
    • ; संस्करण [वैकल्पिक]: संदर्भित फ़ाइल का संस्करण जिसमें संसाधन फ़ाइल होती है। इसका उपयोग तब किया जाता है जब समान नाम वाले दो या अधिक संदर्भित असेंबली लोड की जाती हैं।
    • ; पब्लिकके [वैकल्पिक]: संदर्भित कुंजी पर हस्ताक्षर करने के लिए उपयोग की जाने वाली सार्वजनिक कुंजी। इसका उपयोग तब किया जाता है जब समान नाम वाले दो या अधिक संदर्भित असेंबली लोड की जाती हैं।
    • ; घटक: निर्दिष्ट करता है कि जिस विधानसभा को संदर्भित किया जा रहा है वह स्थानीय विधानसभा से संदर्भित है।
    • / पथ: संदर्भित फ़ाइल के रूट फ़ोल्डर के रूट के सापेक्ष, इसके पथ सहित संसाधन फ़ाइल का नाम।

बाद में तीन स्लैशों application:को अल्पविराम से बदलना होगा:

नोट: एक पैक URI का प्राधिकरण घटक एक एम्बेडेड URI है जो एक पैकेज की ओर इशारा करता है और इसे RFC 2396 के अनुरूप होना चाहिए। इसके अलावा, "/" वर्ण को "," वर्ण और "%" जैसे आरक्षित वर्णों से बदलना होगा। तथा "?" बचना चाहिए। विवरण के लिए ओपीसी देखें।

और हां, सुनिश्चित करें कि आपने अपनी छवि पर बिल्ड एक्शन सेट किया है Resource


हां, यह वह समाधान था जो मैंने खुद को कुछ परीक्षण और त्रुटि के बाद पाया। पूरी तरह से स्पष्टीकरण के लिए धन्यवाद। उत्तर स्वीकृत!
Torbjørn

मुझे नहीं पता कि इसकी आवश्यकता क्यों थी, और अन्य जवाब मेरे लिए क्यों नहीं आए ...
Torbjørn

इस और अन्य सवालों के अन्य जवाब मेरे लिए भी काम नहीं किया। यह पूरी तरह से काम करता है। धन्यवाद।
थॉमस स्टॉक

9
ठीक है, लेकिन कुछ तरीका या वर्ग नहीं है जिसे XAML पार्सर सरल पथ स्ट्रिंग को एक छवि स्रोत में बदलने के लिए उपयोग करता है? क्या हम इसका इस्तेमाल नहीं कर सकते?
Qwertie

1
मैं अक्सर इस स्निपेट को अन्य पोस्टों में कॉपी करता देखता हूं, जहां लोग आमतौर पर BitmapImage(Uri)कंस्ट्रक्टर के अस्तित्व को नजरअंदाज कर देते हैं , जो बिगिनिट और एंडइनिट को कॉल करने की आवश्यकता से बचने में मदद करता है। मैंने इसे यहाँ जोड़ा है।
क्लेमेंस

175
var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative);
foo.Source = new BitmapImage(uriSource);

यह असेंबली में "Untitled.png" नामक एक छवि को "WpfApplication1" नामक एक असेंबली में "संसाधन" पर सेट अपने "बिल्ड एक्शन" के साथ "छवियाँ" नामक एक लोड करेगा।


16
उसके लिए धन्यवाद। एक मुद्दा जिसने मुझे wpf में एक noob के रूप में उलझा दिया, छवि को इस काम के लिए संसाधन के रूप में चिह्नित किया जाना चाहिए।
si618

4
इस समाधान ने मुझे एक अपवाद दिया, इसलिए मैंने जेरेड हार्ले के समाधान की कोशिश की और यह काम कर गया ...
संग्राम नंदखिले

2
सबसे महत्वपूर्ण बात "UriKind.RelativeOrAbsolute" है - अन्य उदाहरण हमेशा अपवादों को फेंकते हैं
स्वेन

9
var uriSource = new Uri("Images/Untitled.png", UriKind.Relative);पर्याप्त होगा
हम्जेह सोबोह

... और बहुत आसान है। धन्यवाद
हामज़ेह

74

यह थोड़ा कम कोड है और इसे एक ही लाइन में किया जा सकता है।

string packUri = "pack://application:,,,/AssemblyName;component/Images/icon.png";
_image.Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource;

8
यह निश्चित रूप से सबसे अच्छा जवाब है। .NET के खुद के कार्यान्वयन का उपयोग करते हुए
joshcomley

अगर हमें छवि की ऊँचाई और चौड़ाई सेट करने की आवश्यकता है, तो icon.png? क्योंकि _image.height और _image.width का उपयोग करके यह इमेज विंडो को वास्तविक इमेज यानी icon.png सेट नहीं करता है।
सचिवालय

41

बहुत आसान:

मेनू आइटम की छवि को गतिशील रूप से सेट करने के लिए, केवल निम्नलिखित कार्य करें:

MyMenuItem.ImageSource = 
    new BitmapImage(new Uri("Resource/icon.ico",UriKind.Relative));

... जबकि "icon.ico" हर जगह स्थित हो सकता है (वर्तमान में यह 'संसाधन' निर्देशिका में स्थित है) और संसाधन के रूप में जुड़ा होना चाहिए ...


2
कमतर = बेहतर। मुझे इसे @ "/ folder / image.png" के रूप में सेट करना था, लेकिन तब इसने ठीक काम किया। धन्यवाद!
19

3
जब मैं छवियों को असाइन करता हूं, तो यह केवल खाली दिखाई दे रहा है :(
हेलोमीडिया

@HaloMediaz का रास्ता गलत हो सकता है .... जैसे आपके पास संसाधन हैं, लेकिन आप इसे लिख सकते हैं संसाधन
रौज़ेह ज़ारंडी

यह मेरे लिए काम किया, और अन्य उत्तर में निरपेक्ष यूआरआई की तुलना में कहीं अधिक सीधा है।
Psiloc

16

आप इसे एक पंक्ति में भी घटा सकते हैं। यह वह कोड है जिसका उपयोग मैंने अपने मुख्य विंडो के लिए आइकन सेट करने के लिए किया था। यह मानता है कि .ico फ़ाइल को सामग्री के रूप में चिह्नित किया गया है और इसे आउटपुट निर्देशिका में कॉपी किया जा रहा है।

 this.Icon = new BitmapImage(new Uri("Icon.ico", UriKind.Relative));

16

सबसे सरल तरीका:

var uriSource = new Uri("image path here");
image1.Source = new BitmapImage(uriSource);

15

आपने कोशिश की है:

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
_icon.Source = bitmap;

13

यह मेरा तरीका है:

internal static class ResourceAccessor
{
    public static Uri Get(string resourcePath)
    {
        var uri = string.Format(
            "pack://application:,,,/{0};component/{1}"
            , Assembly.GetExecutingAssembly().GetName().Name
            , resourcePath
        );

        return new Uri(uri);
    }
}

उपयोग:

new BitmapImage(ResourceAccessor.Get("Images/1.png"))

8

यहाँ एक उदाहरण है जो छवि पथ को गतिशील रूप से सेट करता है (संसाधन के रूप में निर्माण के बजाय डिस्क पर कहीं स्थित छवि):

if (File.Exists(imagePath))
{
    // Create image element to set as icon on the menu element
    Image icon = new Image();
    BitmapImage bmImage = new BitmapImage();
    bmImage.BeginInit();
    bmImage.UriSource = new Uri(imagePath, UriKind.Absolute);
    bmImage.EndInit();
    icon.Source = bmImage;
    icon.MaxWidth = 25;
    item.Icon = icon;
}

आइकनों पर विचार ...

पहले सोचा था, आप सोचेंगे कि आइकन संपत्ति में केवल एक छवि हो सकती है। लेकिन इसमें वास्तव में कुछ भी हो सकता है! मुझे यह दुर्घटना से पता चला जब मैंने प्रोग्राम Imageको छवि के पथ के साथ सीधे एक स्ट्रिंग में संपत्ति सेट करने की कोशिश की । नतीजा यह था कि यह छवि नहीं दिखाती थी, लेकिन पथ का वास्तविक पाठ!

इससे आइकन के लिए एक छवि नहीं बनाने का विकल्प होता है, लेकिन एक साधारण "आइकन" प्रदर्शित करने के बजाय प्रतीक फ़ॉन्ट के साथ पाठ का उपयोग करें। निम्नलिखित उदाहरण विंग्ड्स फ़ॉन्ट का उपयोग करता है जिसमें "फ्लॉपीडिस्क" प्रतीक होता है। यह प्रतीक वास्तव में चरित्र है <, जिसका XAML में विशेष अर्थ है, इसलिए हमें &lt;इसके बजाय एन्कोडेड संस्करण का उपयोग करना होगा। यह एक सपने की तरह काम करता है! निम्नलिखित मेनू आइटम पर एक आइकन के रूप में एक फ्लॉपीडिस्क प्रतीक दिखाता है:

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
  <MenuItem.Icon>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings">&lt;</Label>
  </MenuItem.Icon>
</MenuItem>

प्रश्न: " छवि परियोजना में संसाधन के रूप में एम्बेडेड है ", उत्तर: " यहां एक उदाहरण है [एक छवि के लिए] संसाधन के रूप में निर्माण के बजाय डिस्क पर कहीं स्थित है "।
मिनट

7

यदि आपकी छवि रिसोर्स में संग्रहीत है, तो आप इसे केवल एक लाइन कोड के साथ कर सकते हैं:

MyImage.Source = MyImage.FindResource("MyImageKeyDictionary") as ImageSource;

6

इसका एक सरल तरीका भी है। यदि छवि को XAML में संसाधन के रूप में लोड किया गया है, और प्रश्न में कोड उस XAML सामग्री के लिए कोड-पीछे है:

Uri iconUri = new Uri("pack://application:,,,/ImageNAme.ico", UriKind.RelativeOrAbsolute);
NotifyIcon.Icon = BitmapFrame.Create(iconUri);

4

VisualBrush में फ़्रेम डालें:

VisualBrush brush = new VisualBrush { TileMode = TileMode.None };

brush.Visual = frame;

brush.AlignmentX = AlignmentX.Center;
brush.AlignmentY = AlignmentY.Center;
brush.Stretch = Stretch.Uniform;

VisualBrush को GeometryDrawing में रखें

GeometryDrawing drawing = new GeometryDrawing();

drawing.Brush = brush;

// Brush this in 1, 1 ratio
RectangleGeometry rect = new RectangleGeometry { Rect = new Rect(0, 0, 1, 1) };
drawing.Geometry = rect;

अब एक रेखांकन में ज्योमेट्रीवार्डिंग लगाएं:

new DrawingImage(drawing);

इसे छवि के अपने स्रोत पर रखें, और ध्वनि दें!

हालांकि आप इसे बहुत आसान कर सकते हैं:

<Image>
    <Image.Source>
        <BitmapImage UriSource="/yourassembly;component/YourImage.PNG"></BitmapImage>
    </Image.Source>
</Image>

और कोड में:

BitmapImage image = new BitmapImage { UriSource="/yourassembly;component/YourImage.PNG" };

जबरदस्त हंसी! जब आप पहली बार इसे आसान बना सकते हैं तो इसे आसान क्यों करें :) मैं आपके सरल समाधान की कोशिश करूंगा, हालांकि मैं इसे स्वीकार करता हूं ...
Torbjørn

वास्तव में इससे मुझे बिल्कुल मदद नहीं मिली। हो सकता है कि मैं बेवकूफ हूं :( अब और अधिक बारीकी से देखने के लिए समय नहीं है (पालतू परियोजना)। जब मैं इसे वापस लेने के लिए अधिक उत्तर चाहूंगा :)
Torbjørn

3

इसका एक सरल तरीका भी है। यदि छवि को XAML में एक संसाधन के रूप में लोड किया गया है, और प्रश्न में कोड उस XAML के लिए कोडबाइंड है:

यहाँ एक XAML फ़ाइल के लिए संसाधन शब्दकोश है - केवल एक लाइन जिसकी आपको परवाह है, वह है "PostBBush" कुंजी के साथ ImageBrush - बाकी कोड केवल संदर्भ दिखाने के लिए है

<UserControl.Resources>
        <ResourceDictionary>
            <ImageBrush x:Key="PosterBrush" ImageSource="..\Resources\Images\EmptyPoster.jpg" Stretch="UniformToFill"/>

        </ResourceDictionary>
    </UserControl.Resources>

अब, पीछे कोड में, आप बस ऐसा कर सकते हैं

ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"];

2

संसाधन आइकन और छवियों (आर्कटुरस का सही संस्करण) में एम्बेडेड से एक छवि को कैसे लोड करें:

मान लीजिए कि आप एक छवि के साथ एक बटन जोड़ना चाहते हैं। आपको क्या करना चाहिये?

  1. प्रोजेक्ट आइकन में जोड़ें और यहां ClickMe.png छवि डालें
  2. 'ClickMe.png' के गुणों में, 'BuildAction' को 'संसाधन' पर सेट करें
  3. मान लीजिए कि आपका संकलित असेंबली का नाम 'Company.ProductAssembly.dll' है।
  4. अब हमारी छवि को XAML में लोड करने का समय आ गया है

    <Button Width="200" Height="70">
      <Button.Content>
        <StackPanel>
          <Image Width="20" Height="20">
            <Image.Source>
              <BitmapImage UriSource="/Company.ProductAssembly;component/Icons/ClickMe.png"></BitmapImage>
              </Image.Source>
          </Image>
          <TextBlock HorizontalAlignment="Center">Click me!</TextBlock>
        </StackPanel>
      </Button.Content>
    </Button>

किया हुआ।


2

मैं WPF में एक नया हूँ, लेकिन .NET में नहीं।

मैंने .NET 3.5 (विज़ुअल स्टूडियो 2010) में एक "WPF कस्टम कंट्रोल लाइब्रेरी प्रोजेक्ट" में PNG फ़ाइल को जोड़ने और इसे एक छवि-विरासत नियंत्रण की पृष्ठभूमि के रूप में सेट करने में पाँच घंटे बिताए हैं।

URIs के सापेक्ष कुछ भी काम नहीं किया। मैं सोच भी नहीं सकता कि IntelliSense के माध्यम से संसाधन फ़ाइल से URI प्राप्त करने के लिए कोई तरीका क्यों नहीं है, शायद:

Properties.Resources.ResourceManager.GetURI("my_image");

मैंने बहुत सारे URI की कोशिश की है और ResourceManager, और असेंबली के GetManifest तरीकों से खेला है, लेकिन सभी अपवाद या NULL मान थे।

यहाँ मैंने उस कोड को पॉट किया है जो मेरे लिए काम करता है:

// Convert the image in resources to a Stream
Stream ms = new MemoryStream()
Properties.Resources.MyImage.Save(ms, ImageFormat.Png);

// Create a BitmapImage with the stream.
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = ms;
bitmap.EndInit();

// Set as source
Source = bitmap;

3
मुझे लगता है कि समस्या यह है कि WPF रेसक्स फ़ाइलों में संसाधन डालने के पारंपरिक दृष्टिकोण को "पसंद नहीं" करता है। इसके बजाय आप छवि को सीधे अपनी परियोजना में जोड़ने और संसाधन के लिए इसकी बिल्ड एक्शन संपत्ति सेट करने वाले हैं। मुझे नहीं पता कि दोनों दृष्टिकोणों के बीच अंतर क्या है (शब्द भौतिक फ़ाइल प्रारूप में)।
क्वर्टी

1
सुनिश्चित करें कि एक्शन बिल्ड कंटेंट है
जेरी निक्सन

1

यदि आपके पास पहले से ही एक स्ट्रीम है और प्रारूप को जानते हैं, तो आप कुछ इस तरह का उपयोग कर सकते हैं:

static ImageSource PngStreamToImageSource (Stream pngStream) {
    var decoder = new PngBitmapDecoder(pngStream,
        BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    return decoder.Frames[0];
}

1

तुम जरा चूक गए।

किसी भी विधानसभा से एक एम्बेडेड संसाधन प्राप्त करने के लिए, आपको अपनी फ़ाइल के नाम के साथ विधानसभा के नाम का उल्लेख करना होगा जैसा कि मैंने यहां बताया है:

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream(asm.GetName().Name + "." + "Desert.jpg");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
image1.Source = bitmap;

WPF में BeginInit () मौजूद नहीं है।
मियोसोटिस

यह नीचे दिए गए लिंक msdn.microsoft.com/en-us/library/… के
मौलिक कंसारा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.