Programing

코드에서 WPF 이미지 소스 설정

lottogame 2020. 3. 11. 00:40
반응형

코드에서 WPF 이미지 소스 설정


코드에서 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" />


당신과 같은 문제가 있고 약간의 독서를 한 후에 솔루션 팩 URI를 발견했습니다 .

코드에서 다음을 수행했습니다.

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

    • AssemblyShortName : 참조 된 어셈블리의 짧은 이름입니다.
    • ; Version [선택 사항] : 리소스 파일이 포함 된 참조 된 어셈블리의 버전입니다. 짧은 이름이 동일한 둘 이상의 참조 된 어셈블리가로드 될 때 사용됩니다.
    • ; PublicKey [선택 사항] : 참조 된 어셈블리에 서명하는 데 사용 된 공개 키. 짧은 이름이 동일한 둘 이상의 참조 된 어셈블리가로드 될 때 사용됩니다.
    • ; component : 참조되는 어셈블리가 로컬 어셈블리에서 참조되도록 지정합니다.
    • / 경로 : 참조 된 어셈블리 프로젝트 폴더의 루트에 상대적인 경로를 포함한 리소스 파일의 이름.

세 개의 슬래시는 이후 application:에 쉼표로 교체해야합니다.

참고 : 팩 URI의 권한 구성 요소는 패키지를 가리키는 임베디드 URI이며 RFC 2396을 준수해야합니다. 또한 "/"문자는 ","문자 및 "%"와 같은 예약 문자로 바꿔야합니다. "?" 탈출해야합니다. 자세한 내용은 OPC를 참조하십시오.

물론 이미지의 빌드 작업을로 설정했는지 확인하십시오 Resource.


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

"WpfApplication1"이라는 어셈블리에서 "Build Action"이 "Resource"로 설정된 "Images"폴더에 "Untitled.png"라는 이미지가로드됩니다.


이것은 약간 적은 코드이며 한 줄로 수행 할 수 있습니다.

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

아주 쉽게:

메뉴 항목의 이미지를 동적으로 설정하려면 다음을 수행하십시오.

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

"icon.ico"는 어디에나있을 수 있으며 (현재 'Resources'디렉토리에 위치) Resource로 링크되어야합니다.


이것을 한 줄로 줄일 수도 있습니다. 이것은 메인 윈도우의 아이콘을 설정하는 데 사용한 코드입니다. .ico 파일이 내용으로 표시되어 출력 디렉토리로 복사되고 있다고 가정합니다.

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

가장 간단한 방법 :

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

시도해 보셨습니까?

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

이게 내 방법이야:

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"))

이미지 경로를 동적으로 설정하는 예는 다음과 같습니다 (이미지는 리소스로 빌드하지 않고 디스크 어딘가에 위치).

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;
}

아이콘에 대한 반사 ...

처음에는 Icon 속성에 이미지 만 포함될 수 있다고 생각했습니다. 그러나 실제로 무엇이든 포함 할 수 있습니다! 프로그래밍 방식으로 Image속성을 이미지 경로가있는 문자열 로 설정하려고 시도했을 때 우연히이 사실을 발견했습니다 . 결과는 이미지가 아니라 경로의 실제 텍스트입니다!

이로 인해 아이콘 이미지를 만들 필요는 없지만 간단한 "아이콘"을 표시하기 위해 기호 글꼴이있는 텍스트를 사용할 수 있습니다. 다음 예제에서는 "floppydisk"기호가 포함 된 Wingdings 글꼴사용합니다 . 이 기호는 실제로 문자 <이므로 XAML에서 특별한 의미를 가지므로 &lt;대신 인코딩 된 버전을 사용해야합니다 . 이것은 꿈처럼 작동합니다! 다음은 메뉴 항목에서 플로피 디스크 기호를 아이콘으로 나타냅니다.

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

이미지가 ResourceDictionary에 저장된 경우 한 줄의 코드만으로 이미지를 수행 할 수 있습니다.

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

더 간단한 방법도 있습니다. 이미지가 XAML에서 리소스로로드되고 해당 코드가 해당 XAML 콘텐츠의 코드 숨김 인 경우 :

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

VisualBrush에 프레임을 넣습니다.

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

brush.Visual = frame;

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

GeometryDrawing에 VisualBrush를 넣습니다

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;

이제 GeometryDrawing을 DrawingImage에 넣습니다.

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" };

더 간단한 방법도 있습니다. 이미지가 XAML에서 리소스로로드되고 해당 코드가 해당 XAML의 코드 숨김 인 경우 :

XAML 파일에 대한 리소스 사전은 다음과 같습니다. "PosterBrush"키가있는 ImageBrush 만 있으면됩니다. 나머지 코드는 컨텍스트를 표시하기위한 것입니다.

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

        </ResourceDictionary>
    </UserControl.Resources>

이제 코드 뒤에, 당신은 이것을 할 수 있습니다

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

리소스 아이콘 및 이미지에 포함 된 이미지를로드하는 방법 (수정 된 버전의 Arcturus) :

이미지가있는 버튼을 추가한다고 가정합니다. 어떻게해야합니까?

  1. 프로젝트 폴더 아이콘에 추가하고 이미지를 여기에 클릭하십시오. ClickMe.png
  2. 'ClickMe.png'의 속성에서 'BuildAction'을 'Resource'로 설정하십시오.
  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>
    

끝난.


WPF를 처음 사용하지만 .NET에는 없습니다.

.NET 3.5 (Visual Studio 2010)의 "WPF Custom Control Library Project"에 PNG 파일을 추가하고 이미지 상속 컨트롤의 배경으로 설정하는 데 5 시간을 보냈습니다.

URI와 관련된 것은 없습니다. IntelliSense를 통해 리소스 파일에서 URI를 가져 오는 방법이없는 이유를 상상할 수 없습니다.

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

나는 많은 URI를 시도하고 ResourceManager와 Assembly의 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;

이미 스트림이 있고 형식을 알고 있다면 다음과 같이 사용할 수 있습니다.

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

당신은 조금 놓쳤다.

어셈블리에서 임베디드 리소스를 얻으려면 여기에서 언급 한 것처럼 파일 이름으로 어셈블리 이름을 언급해야합니다.

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;

참고 URL : https://stackoverflow.com/questions/350027/setting-wpf-image-source-in-code

반응형