2013-05-07 5 views
15

मैं एक संसाधन फ़ाइल में मौजूद छवि के लिए एक पैक यूआरआई कैसे बना सकता हूं?पैक यूआरआई को एक resx फ़ाइल में एम्बेडेड छवि के लिए

मैं इसे एक फ़ोल्डर छवियाँ कहा जाता है, तो एक संसाधन Assets.resx बुलाया फ़ाइल है में एक विधानसभा MyAssembly.Resources.dll कहा जाता है। इस संसाधन फ़ाइल में मेरी छवि है (MyImage.png कहा जाता है)। कोड मैं की लाइन है:

uri = new Uri("pack://application:,,,/MyAssembly.Resources,Culture=neutral,PublicKeyToken=null;component/Images/Assets/MyImage.png"); 

लेकिन जब मैं मैं संदेश के साथ एक IOException प्राप्त एक नया BitmapImage के निर्माता को यह यूआरआई की आपूर्ति करने की कोशिश

पता नहीं लगा सकता संसाधन 'छवियों/संपत्ति /myimage.png '।

नोट मैं एक ही विधानसभा जो मैं एक पैकेट यूआरआई का उपयोग कर ठीक प्राप्त कर सकते हैं में अन्य ढीली छवियां हैं, उन छवियों को उनके निर्माण कार्रवाई संसाधन के लिए सेट पर वे एक resx फ़ाइल में एम्बेडेड नहीं कर रहे हैं। क्या मुझे पथ में resx फ़ाइल का नाम शामिल करना चाहिए?

(मैं resx फ़ाइलों में छवियों को एम्बेड करने के लिए देख रहा हूं ताकि मैं सही छवि को पुनर्प्राप्त करने के लिए यूआई संस्कृति सेटिंग्स का लाभ उठा सकूं (छवि में टेक्स्ट है))।

+1

आपको क्या लगता है यह पैक: 'का उपयोग संभव है बनाता है: योजना

namespace MyAssembly.Resources { public class AssetsProxy : Images.Assets { public AssetsProxy() : base() { } } } 

ImageSource रूपांतरण के लिए बिटमैप? यह सामान्यीकृत ओपन पैकेजिंग सम्मेलन चश्मा से संबंधित है। तो यूरी अनुप्रयोग पैकेज के संसाधनों को इंगित करता है, न कि .NET एम्बेडेड संसाधनों के लिए। हालांकि यह एक और योजना/प्रोटोकॉल के साथ संभव हो सकता है (आप एम्बेडेड संसाधनों के लिए इस कस्टम प्रोटोकॉल को फिर से शुरू कर सकते हैं, जैसे 'नई उरी ("resx: // blabla") ')। –

+0

@ सिमोन मॉरीयर मैं सोच रहा था कि ऐसा करने का एक तरीका होना चाहिए क्योंकि आप XAML से रेक्स फ़ाइलों में तारों से लिंक कर सकते हैं, इसलिए यह संभावना नहीं होगी कि एक ही फ़ाइल में एम्बेडेड अन्य संसाधन प्रकारों तक पहुंचने का कोई तरीका न हो, और एक यूआरआई संसाधन के लिए पथ का वर्णन करने का एक तरीका है। यदि आपके पास कस्टम प्रोटोकॉल का उपयोग करने के बारे में कोई सुझाव है, तो मुझे यह सुनकर खुशी होगी। ढीली (गैर-पाठ) छवियों को सभी पैक यूआरआई का उपयोग करके संदर्भित किया जाता है, इसलिए यदि संभव हो तो मैं निरंतरता बनाए रखना चाहता था। आंतरिक के विस्तृत स्पष्टीकरण के लिए – slugster

उत्तर

15

मैं इसे "पैक" प्रोटोकॉल योजना का उपयोग कर सकता है नहीं लगता है। यह प्रोटोकॉल सामान्यीकृत ओपन पैकेजिंग सम्मेलन चश्मे से संबंधित है (पॉइंटर्स के लिए)। तो पैक यूरी अनुप्रयोग पैकेज के संसाधनों (या ओपीसी शर्तों में भागों) को इंगित करता है, न कि .NET एम्बेडेड संसाधनों के लिए।

हालांकि, आप अपनी खुद की योजना को परिभाषित कर सकते हैं, उदाहरण के लिए "resx" और WPF घटक uris में इसका उपयोग करें। ऐसे उपयोगों के लिए नई उरी योजनाओं को WebRequest.RegisterPrefix का उपयोग करके परिभाषित किया जा सकता है।

यहां एक उदाहरण है जो "WpfAplication1" नामक एक छोटी Wpf एप्लिकेशन प्रोजेक्ट पर आधारित है। इस एप्लिकेशन में संसाधन 1.resx फ़ाइल परिभाषित है (और संभवतः अन्य स्थानीयकृत संबंधित संसाधन 1 फ़ाइलें, उदाहरण के लिए फ्रेंच के लिए Resource1.fr-FR.resx जैसे)। इनमें से प्रत्येक ResX फ़ाइलें "img" नामक एक छवि संसाधन को परिभाषित करती हैं (ध्यान दें कि यह नाम उस छवि फ़ाइल नाम जैसा नहीं है जिस पर संसाधन आधारित है)। ,

resx://assembly name/resource set name/resource name 

और विधानसभा का नाम वैकल्पिक है तो

resx:///resource set name/resource name 

भी वैध और बिंदु है:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Image Source="resx:///WpfApplication1.Resource1/img" /> 
</Window> 

uri प्रारूप इस प्रकार है:

यहाँ MainWindow.xaml है मुख्य असेंबली में संसाधनों के लिए (मेरा नमूना इसका उपयोग करता है)

यह वह कोड है जो इसका समर्थन करता है, App.xaml में।

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     ResXWebRequestFactory.Register(); 
     base.OnStartup(e); 
    } 
} 

और योजना कार्यान्वयन:

public sealed class ResXWebRequestFactory : IWebRequestCreate 
{ 
    public const string Scheme = "resx"; 
    private static ResXWebRequestFactory _factory = new ResXWebRequestFactory(); 

    private ResXWebRequestFactory() 
    { 
    } 

    // call this before anything else 
    public static void Register() 
    { 
     WebRequest.RegisterPrefix(Scheme, _factory); 
    } 

    WebRequest IWebRequestCreate.Create(Uri uri) 
    { 
     return new ResXWebRequest(uri); 
    } 

    private class ResXWebRequest : WebRequest 
    { 
     public ResXWebRequest(Uri uri) 
     { 
      Uri = uri; 
     } 

     public Uri Uri { get; set; } 

     public override WebResponse GetResponse() 
     { 
      return new ResXWebResponse(Uri); 
     } 
    } 

    private class ResXWebResponse : WebResponse 
    { 
     public ResXWebResponse(Uri uri) 
     { 
      Uri = uri; 
     } 

     public Uri Uri { get; set; } 

     public override Stream GetResponseStream() 
     { 
      Assembly asm; 
      if (string.IsNullOrEmpty(Uri.Host)) 
      { 
       asm = Assembly.GetEntryAssembly(); 
      } 
      else 
      { 
       asm = Assembly.Load(Uri.Host); 
      } 

      int filePos = Uri.LocalPath.LastIndexOf('/'); 
      string baseName = Uri.LocalPath.Substring(1, filePos - 1); 
      string name = Uri.LocalPath.Substring(filePos + 1); 

      ResourceManager rm = new ResourceManager(baseName, asm); 
      object obj = rm.GetObject(name); 

      Stream stream = obj as Stream; 
      if (stream != null) 
       return stream; 

      Bitmap bmp = obj as Bitmap; // System.Drawing.Bitmap 
      if (bmp != null) 
      { 
       stream = new MemoryStream(); 
       bmp.Save(stream, bmp.RawFormat); 
       bmp.Dispose(); 
       stream.Position = 0; 
       return stream; 
      } 

      // TODO: add other formats 
      return null; 
     } 
    } 
} 
+0

आप हर दिन कुछ सीखते हैं :) – NSGaga

+0

धन्यवाद साइमन। मेरे पास कई फ़ॉलबैक विकल्प थे, लेकिन आपका विकल्प मुझे बहुत कुछ देता है जो मैं उम्मीद कर रहा था - इसका उपयोग करके मैं उस कोड के बिट में स्थिरता बनाए रख सकता हूं जिसके लिए इसकी आवश्यकता होती है, मुझे कोड को जटिल करने की आवश्यकता नहीं है कि यह एक है या नहीं लापरवाही पैक छवि या resx में एम्बेडेड। – slugster

4

असेंबली में संसाधन को "एम्बेड" करने के दो तरीके हैं। विंडोज फॉर्म Embedded Resource बिल्ड एक्शन का उपयोग करता है। डब्ल्यूपीएफ Resource बिल्ड एक्शन के साथ चिह्नित होने के लिए असेंबली में निहित संसाधनों की अपेक्षा करता है।

जब आप किसी छवि को जोड़ने के लिए विजुअल स्टूडियो में रेक्स संपादक का उपयोग करते हैं, तो यह इसे एंबेडेड संसाधन के रूप में चिह्नित करता है। इसके अलावा, यह इसे System.Drawing.Bitmap टाइप करता है। डब्ल्यूपीएफ System.Windows.Media.ImageSource प्रकार की उम्मीद करता है।

यदि आपके पास असंतुष्ट (जैसे ILSpy) है तो आप फ़ाइलों पर विभिन्न बिल्ड क्रियाओं को सेट करने के प्रभाव को देख सकते हैं।

नमूना ImagesLib परियोजना

यहाँ दो छवियों के साथ एक परियोजना का एक स्क्रीनशॉट है। यह नामों से स्पष्ट है, cat_embedded.jpgEmbedded Resource बिल्डिंग कार्रवाई का उपयोग कर रहा है और cat_resource.jpgResource बिल्ड क्रिया का उपयोग कर रहा है।

enter image description here

यह है कि वे क्या ILSpy में की तरह लग रही है।

enter image description here

देखें कैसे cat_resource.jpg फ़ाइल ImageLib.g.resources अनुभाग के भीतर है? यही वह जगह है जहां डब्ल्यूपीएफ संसाधनों की तलाश में है। फ़ाइल का पथ संसाधन नाम का हिस्सा है (images/cat_resource.jpg)। तो जब आप की तरह एक पथ का उपयोग करें:

var uri = new Uri("pack://application:,,,/ImageLib;component/Images/cat_resource.jpg"); 

आप शब्द ;component के बाद मिलान पथ निर्दिष्ट।

अन्य जेपीजी फ़ाइल असेंबली में एक अलग स्थान पर स्थित है, और नाम (ImageLib.Images.cat_embedded.jpg) में अवधि का उपयोग करती है।

आप cat_embedded.jpg छवि को आजमाने और प्राप्त करने के लिए उस स्ट्रिंग के कई क्रमपरिवर्तनों को आजमा सकते हैं, लेकिन WPF इसे नहीं ढूंढ पाएगा।

RESX संपादक

यहाँ एक और परियोजना, दो छवियों, एक एक संसाधन के रूप में चिह्नित है और एक resx संपादक से जोड़ा गया है है।

enter image description here

और यहाँ disassembled स्क्रीनशॉट है।

enter image description here

आप देख सकते हैं, resx छवि उसी URI स्थान पहले एम्बेडेड छवि उदाहरण के रूप में उपयोग कर रहा है। यह आपके मामले में प्रकट होता है, आप पैक यूआरआई का उपयोग कर resx फ़ाइल से छवियां प्राप्त करने में सक्षम नहीं होंगे।

स्थानीयकरण

क्या आप अपने प्रश्न में कहा से, क्या आप को पूरा करने के प्रयास कर रहे हैं सही छवियों का स्थानीयकरण है?

क्या आपने इस एमएसडीएन लेख को देखा है?

WPF Globalization and Localization Overview

+0

+1। –

2

मैं इस ब्लॉग पोस्ट में WPF में resx छवियों का उपयोग करने के लिए एक घटक वर्णित: http://wpfglue.wordpress.com/2012/05/31/localization-revisited/ सीएस या कहीं और, आप नई योजना रजिस्टर करने के लिए की जरूरत है। आपको http://wpfglue.wordpress.com/category/localization/

के तहत WPF में रेक्स संसाधनों का उपयोग करने के बारे में अधिक पोस्ट मिलेगी, इन पदों में, मैं पैक यूरिस का उपयोग नहीं करता, लेकिन मार्कअप एक्सटेंशन का उपयोग नहीं करता हूं।

3

जैसा कि वॉल्ट ने सही ढंग से कहा है, आप एक resx फ़ाइल से बाहर क्या प्राप्त करते हैं System.Drawing.Bitmap है। इसलिए इसे System.Windows.Media.ImageSource या उप प्रकार में परिवर्तित करने की आवश्यकता है।

मुझे यकीन नहीं है कि यह आपके लिए समय बर्बाद कर रहा है क्योंकि यह यूआरआई को नियोजित नहीं करता है, लेकिन यहां मैं अन्य लाइब्रेरी में resx फ़ाइलों से छवियां कैसे प्राप्त करता हूं। मैं a simple proxy का उपयोग करता हूं क्योंकि रेक्स डिजाइनर फ़ाइल केवल एक आंतरिक कन्स्ट्रक्टर का खुलासा करती है (भले ही कक्षा सार्वजनिक है), फिर वैल्यू कनवर्टर को परिभाषित करें जो ImageSource प्रदान करेगा।

enter image description here

<Window x:Class="WpfApplication1.MainWindow" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:local="clr-namespace:WpfApplication1" 
      xmlns:resx="clr-namespace:MyAssembly.Resources;assembly=MyAssembly.Resources" 
      Title="MainWindow" Height="350" Width="525"> 

    <Window.Resources> 
     <resx:AssetsProxy x:Key="Assets" /> 
     <resx:BitmapToImageSourceConverter x:Key="BitmapConverter" /> 
    </Window.Resources> 

    <Image Source="{Binding myimage, Source={StaticResource Assets}, Converter={StaticResource BitmapConverter}}" /> 
</Window> 

AssetsProxy:

using System; 
using System.Drawing.Imaging; 
using System.Globalization; 
using System.IO; 
using System.Windows.Data; 
using System.Windows.Media.Imaging; 

namespace MyAssembly.Resources 
{ 
    /// <summary> 
    /// Converts a BitmapImage, as provided by a resx resource, into an ImageSource/BitmapImage 
    /// </summary> 
    public class BitmapToImageSourceConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      BitmapImage bitmapImage = null; 
      if (value is System.Drawing.Image) 
      { 
       bitmapImage = ((System.Drawing.Image)value).ToBitmapImage(); 
      } 
      return bitmapImage; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public static class BitmapExtensions 
    { 
     /// <summary> 
     /// Converts the System.Drawing.Image to a System.Windows.Media.Imaging.BitmapImage 
     /// </summary> 
     public static BitmapImage ToBitmapImage(this System.Drawing.Image bitmap) 
     { 
      BitmapImage bitmapImage = null; 
      if (bitmap != null) 
      { 
       using (MemoryStream memory = new MemoryStream()) 
       { 
        bitmapImage = new BitmapImage(); 
        bitmap.Save(memory, ImageFormat.Png); 
        memory.Position = 0; 
        bitmapImage.BeginInit(); 
        bitmapImage.StreamSource = memory; 
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 
        bitmapImage.EndInit(); 
       } 
      } 
      return bitmapImage; 
     } 
    } 
} 
संबंधित मुद्दे