图像处理概述
本主题介绍 Microsoft Windows Presentation Foundation Imaging Component。 借助 WPF Imaging,开发人员可以显示、转换图像和设置图像的格式。
本主题包括下列各节。
- WPF 图像处理组件
- WPF 图像格式
- 在 WPF 中显示图像
- 图像元数据
- 编解码器扩展性
- 相关主题
WPF 图像处理组件
WPF Imaging使得 Microsoft Windows 内的图像处理功能得到了极大改进。 以前,图像处理功能(例如在公共控件上显示位图或使用图像)依赖于 Microsoft Windows Graphics Device Interface (GDI) 或 Microsoft Windows GDI+ 库。 这些 API 提供了基线图像处理功能,但缺乏诸如编解码器扩展性支持和高保真图像支持之类的功能。 WPF Imaging 旨在克服 GDI 和 GDI+ 的缺点,并提供一组新的 API,用以在应用程序内显示和使用图像。
有两种方式可以访问 WPF Imaging API:托管组件和非托管组件。 非托管组件提供以下功能。
适用于新的或专用图像格式的扩展性模型。
对包括bitmap (BMP)、Joint Photographics Experts Group (JPEG)、Portable Network Graphics (PNG)、Tagged Image File Format (TIFF)、Microsoft Windows Media Photo、Graphics Interchange Format (GIF) 和图标 (.ico) 在内的本机图像格式增强了性能和安全性。
高位深图像数据的保留最多 8 位/通道(32 位/像素)。
非破坏性图像缩放、裁切和旋转。
简化的颜色管理
支持文件内的专用元数据。
托管组件利用非托管基础结构提供图像与其他 WPF 功能(如user interface (UI)、动画和图形)的无缝集成。 托管组件还可以从 Windows Presentation Foundation (WPF) 图像处理编解码器扩展性模型获益,利用该模型可以自动识别 WPF 应用程序中的新图像格式。
大部分托管的 WPF Imaging API 驻留在 System.Windows.Media.Imaging 命名空间中,不过,几个重要的类型(如 ImageBrush 和 ImageDrawing)都驻留在 System.Windows.Media 命名空间,Image 驻留在 System.Windows.Controls 命名空间。
本主题提供有关托管组件的其他信息。 有关非托管 API 的更多信息,请参见非托管 WPF 图像处理组件文档。
WPF 图像格式
编解码器用于对特定媒体格式进行解码或编码。 WPF Imaging包括一个适用于BMP、JPEG、PNG、TIFF、Windows Media Photo、GIF 和图标图像格式的编解码器。 利用上述每个编解码器,应用程序可以对其各自的图像格式进行解码(ICON 除外)和编码。
BitmapSource 是一个重要的类,用于对图像进行解码和编码。 它是 WPF Imaging管线的基本构造块,表示具有特定大小和分辨率的单个不变的像素集。 BitmapSource 可以是多个帧图像中的单个帧,或者可以是在 BitmapSource 上执行转换的结果。 它是 WPF 图像处理中使用的许多主要类(如 BitmapFrame)的父级。
BitmapFrame 用于存储图像格式的实际位图数据。 许多图像格式仅支持单一 BitmapFrame,不过 GIF 和 TIFF 等格式的图像支持每个图像有多个帧。 帧由解码器用作输入数据,并传递到编码器以创建图像文件。
下面的示例演示如何从 BitmapSource 创建一个 BitmapFrame 并将其添加到 TIFF 图像。
Dim image5 As BitmapSource = System.Windows.Media.Imaging.BitmapSource.Create(width, height, 96, 96, PixelFormats.Indexed1, BitmapPalettes.WebPalette, pixels, stride)
Dim stream5 As New FileStream("palette.tif", FileMode.Create)
Dim encoder5 As New TiffBitmapEncoder()
encoder5.Frames.Add(BitmapFrame.Create(image5))
encoder5.Save(stream5)
BitmapSource image5 = BitmapSource.Create(
width,
height,
96,
96,
PixelFormats.Indexed1,
BitmapPalettes.WebPalette,
pixels,
stride);
FileStream stream5 = new FileStream("palette.tif", FileMode.Create);
TiffBitmapEncoder encoder5 = new TiffBitmapEncoder();
encoder5.Frames.Add(BitmapFrame.Create(image5));
encoder5.Save(stream5);
图像格式解码
图像解码是指将某种图像格式转换为可以由系统使用的图像数据。 然后,此图像数据可以用于显示、处理或编码为其他格式。 解码器的选择是基于图像格式做出的。 编解码器的选择是自动做出的,除非指定了特定的解码器。 在 WPF 中显示图像小节中的示例演示了自动解码。 使用非托管 WPF Imaging界面开发并向系统注册的自定义格式解码器会自动加入到解码器选择队列。 这将使得自定义格式可以自动显示在 WPF 应用程序中。
下面的示例演示使用位图解码器对 BMP 格式的图像进行解码。
' Open a Uri and decode a BMP image
Dim myUri As New Uri("tulipfarm.bmp", UriKind.RelativeOrAbsolute)
Dim decoder2 As New BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default)
Dim bitmapSource2 As BitmapSource = decoder2.Frames(0)
' Draw the Image
Dim myImage2 As New Image()
myImage2.Source = bitmapSource2
myImage2.Stretch = Stretch.None
myImage2.Margin = New Thickness(20)
// Open a Uri and decode a BMP image
Uri myUri = new Uri("tulipfarm.bmp", UriKind.RelativeOrAbsolute);
BmpBitmapDecoder decoder2 = new BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource2 = decoder2.Frames[0];
// Draw the Image
Image myImage2 = new Image();
myImage2.Source = bitmapSource2;
myImage2.Stretch = Stretch.None;
myImage2.Margin = new Thickness(20);
// Open a Uri and decode a BMP image
System::Uri^ myUri = gcnew System::Uri("tulipfarm.bmp", UriKind::RelativeOrAbsolute);
BmpBitmapDecoder^ decoder2 = gcnew BmpBitmapDecoder(myUri, BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);
BitmapSource^ bitmapSource2 = decoder2->Frames[0];
// Draw the Image
Image^ myImage2 = gcnew Image();
myImage2->Source = bitmapSource2;
myImage2->Stretch = Stretch::None;
myImage2->Margin = System::Windows::Thickness(20);
图像格式编码
图像编码是指将图像数据转换为特定图像格式的过程。 然后,已编码的图像数据可以用于创建新图像文件。 WPF Imaging为上面介绍的每种图像格式提供编码器。
下面的示例演示使用编码器保存一个新创建的位图图像。
Dim stream As New FileStream("new.bmp", FileMode.Create)
Dim encoder As New BmpBitmapEncoder()
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString()
encoder.Frames.Add(BitmapFrame.Create(image))
encoder.Save(stream)
FileStream stream = new FileStream("new.bmp", FileMode.Create);
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
FileStream^ stream = gcnew FileStream("new.bmp", FileMode::Create);
BmpBitmapEncoder^ encoder = gcnew BmpBitmapEncoder();
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);
在 WPF 中显示图像
可以通过多种方式在 Windows Presentation Foundation (WPF) 应用程序中显示图像。 可以使用 Image 控件显示图像、使用 ImageBrush 在可视图面上绘制图像或使用 ImageDrawing 绘制图像。
使用 Image 控件
Image 是一个框架元素,是在应用程序中显示图像的主要方式。 在 XAML 中,有两种方式可以使用 Image:特性语法或属性语法。 下面的示例演示如何使用特性语法或属性标记语法来呈现 200 像素宽的图像。 有关特性语法或属性语法的更多信息,请参见依赖项属性概述。
<!-- Simple image rendering. However, rendering an image this way may not
result in the best use of application memory. See markup below which
creates the same end result but using less memory. -->
<Image Width="200"
Source="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg"/>
<Image Width="200">
<Image.Source>
<!-- To save significant application memory, set the DecodePixelWidth or
DecodePixelHeight of the BitmapImage value of the image source to the desired
height and width of the rendered image. If you don't do this, the application will
cache the image as though it were rendered as its normal size rather then just
the size that is displayed. -->
<!-- Note: In order to preserve aspect ratio, only set either DecodePixelWidth
or DecodePixelHeight but not both. -->
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>
许多示例使用 BitmapImage 对象引用图像文件。 BitmapImage是一个为加载 Extensible Application Markup Language (XAML) 而优化的专用 BitmapSource,并且是一种将图像显示为 Image 控件的 Source 的简便方式。
下面的示例演示如何使用代码呈现 200 像素宽的图像。
注意 |
---|
BitmapImage 实现 ISupportInitialize 接口,以对多个属性的初始化进行优化。只能在对象初始化过程中进行属性更改。调用 BeginInit 以表示初始化开始;调用 EndInit 以表示初始化结束。初始化一旦开始之后,将忽略所做的属性更改。 |
' Create Image Element
Dim myImage As New Image()
myImage.Width = 200
' Create source
Dim myBitmapImage As New BitmapImage()
' BitmapImage.UriSource must be in a BeginInit/EndInit block
myBitmapImage.BeginInit()
myBitmapImage.UriSource = New Uri("C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg")
' To save significant application memory, set the DecodePixelWidth or
' DecodePixelHeight of the BitmapImage value of the image source to the desired
' height or width of the rendered image. If you don't do this, the application will
' cache the image as though it were rendered as its normal size rather then just
' the size that is displayed.
' Note: In order to preserve aspect ratio, set DecodePixelWidth
' or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200
myBitmapImage.EndInit()
'set image source
myImage.Source = myBitmapImage
// Create Image Element
Image myImage = new Image();
myImage.Width = 200;
// Create source
BitmapImage myBitmapImage = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg");
// To save significant application memory, set the DecodePixelWidth or
// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
//set image source
myImage.Source = myBitmapImage;
旋转、转换和裁切图像
通过 WPF,用户可以使用 BitmapImage 的属性或使用其他 BitmapSource 对象(如 CroppedBitmap 或 FormatConvertedBitmap)来转换图像。 上述图像转换可以缩放或旋转图像、更改图像的像素格式或裁切图像。
可以使用 BitmapImage 的 Rotation 属性来执行图像旋转。 旋转只能以 90 度的增量来进行。 在下面的示例中,图像旋转了 90 度。
<Image Width="150" Margin="5" Grid.Column="0" Grid.Row="1">
<Image.Source>
<TransformedBitmap Source="/sampleImages/watermelon.jpg" >
<TransformedBitmap.Transform>
<RotateTransform Angle="90"/>
</TransformedBitmap.Transform>
</TransformedBitmap>
</Image.Source>
</Image>
' Create Image element.
Dim rotated90 As New Image()
rotated90.Width = 150
' Create the TransformedBitmap to use as the Image source.
Dim tb As New TransformedBitmap()
' Create the source to use as the tb source.
Dim bi As New BitmapImage()
bi.BeginInit()
bi.UriSource = New Uri("sampleImages/watermelon.jpg", UriKind.RelativeOrAbsolute)
bi.EndInit()
' Properties must be set between BeginInit and EndInit calls.
tb.BeginInit()
tb.Source = bi
' Set image rotation.
Dim transform As New RotateTransform(90)
tb.Transform = transform
tb.EndInit()
' Set the Image source.
rotated90.Source = tb
// Create Image element.
Image rotated90 = new Image();
rotated90.Width = 150;
// Create the TransformedBitmap to use as the Image source.
TransformedBitmap tb = new TransformedBitmap();
// Create the source to use as the tb source.
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(@"sampleImages/watermelon.jpg", UriKind.RelativeOrAbsolute);
bi.EndInit();
// Properties must be set between BeginInit and EndInit calls.
tb.BeginInit();
tb.Source = bi;
// Set image rotation.
RotateTransform transform = new RotateTransform(90);
tb.Transform = transform;
tb.EndInit();
// Set the Image source.
rotated90.Source = tb;
可以使用 FormatConvertedBitmap 将图像转换为不同的像素格式,如灰度。 在下面的示例中,图像转换为 Gray4。
<!-- Grayscale XAML Image -->
<Image Width="200" Grid.Column="0" Grid.Row="1">
<Image.Source>
<FormatConvertedBitmap Source="/sampleImages/rocks.jpg" DestinationFormat="Gray4" />
</Image.Source>
</Image>
'Create Image Element
Dim grayImage As New Image()
grayImage.Width = 200
grayImage.Margin = New Thickness(5)
'Create source using xaml defined resource.
Dim fcb As New FormatConvertedBitmap(CType(Me.Resources("masterImage"), BitmapImage), PixelFormats.Gray4, Nothing, 0)
'set image source
grayImage.Source = fcb
//Create Image Element
Image grayImage = new Image();
grayImage.Width = 200;
grayImage.Margin = new Thickness(5);
//Create source using xaml defined resource.
FormatConvertedBitmap fcb = new FormatConvertedBitmap(
(BitmapImage)this.Resources["masterImage"],PixelFormats.Gray4,null,0);
//set image source
grayImage.Source = fcb;
若要裁切图像,可以使用 Image 或 CroppedBitmap 的 Clip 属性。 通常情况下,如果您只想调整图像的一部分,则应使用 Clip。 如果需要编码和保存裁切过的图像,应使用 CroppedBitmap。 下面的示例使用 EllipseGeometry 和 Clip 属性来裁切图像。
<!-- Cropping an Image using Clip -->
<Image Width="200" Grid.Column="0" Grid.Row="5" Margin="5"
Source="/sampleImages/gecko.jpg">
<Image.Clip>
<EllipseGeometry Center="75,50" RadiusX="50" RadiusY="25" />
</Image.Clip>
</Image>
' Create the image for clipping
Dim clipImage As New Image()
clipImage.Width = 200
clipImage.Margin = New Thickness(5)
'Create & Set source
Dim bi As New BitmapImage()
' BitmapImage properties must be in a BeginInit/EndInit block
bi.BeginInit()
bi.UriSource = New Uri("pack://application:,,/sampleImages/gecko.jpg")
bi.EndInit()
clipImage.Source = bi
' Clip the using an EllipseGeometry
Dim clipGeometry As New EllipseGeometry(New System.Windows.Point(75, 50), 50, 25)
clipImage.Clip = clipGeometry
//Create the image for clipping
Image clipImage = new Image();
clipImage.Width = 200;
clipImage.Margin = new Thickness(5);
//Create & Set source
BitmapImage bi = new BitmapImage();
//BitmapImage.UriSource must be in a BeginInit/EndInit block
bi.BeginInit();
bi.UriSource = new Uri("pack://application:,,/sampleImages/gecko.jpg");
bi.EndInit();
clipImage.Source = bi;
//Clip the using an EllipseGeometry
EllipseGeometry clipGeometry = new EllipseGeometry(new Point(75, 50), 50, 25);
clipImage.Clip = clipGeometry;
拉伸图像
Stretch 属性控制如何拉伸一个图像以使其填充容器。 Stretch 属性接受以下值(是由 Stretch 枚举定义的):
None:不会拉伸图像以填充输出区域。 如果图像比输出区域大,则图像将绘制到输出区域,而无法容纳的内容将被剪裁掉。
Fill:会拉伸图像以适应输出区域。 由于图像的高度和宽度是独立进行缩放的,因此图像的原始长宽比可能不会保留。 也就是说,为了完全填充输出容器,图像可能会扭曲。
Uniform:图像进行缩放,以便其完全适应输出区域。 图像的长宽比会保留。
UniformToFill:图像会进行缩放,以便在保留图像原始长宽比的同时完全填充输出区域。
下面的示例将每个可用的 Stretch 枚举应用于 Image。
下面的图像显示示例的输出,演示了不同的 Stretch 设置在应用到图像时的效果。
不同的拉伸设置
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" >
<DockPanel>
<Border DockPanel.Dock="Top" Background="Black">
<TextBlock Foreground="White" HorizontalAlignment="Stretch" FontSize="20">
Stretching an Image
</TextBlock>
</Border>
<Grid Name="simpleGrid" Background="{StaticResource CheckeredBrushResource}"
Margin="10"
ShowGridLines="True"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="175" />
<ColumnDefinition Width="175" />
<ColumnDefinition Width="175" />
<ColumnDefinition Width="175" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="200"/>
</Grid.RowDefinitions>
<!-- Labels -->
<TextBlock Style="{StaticResource Header1}"
Grid.Column="0" Grid.Row="0">None</TextBlock>
<TextBlock Style="{StaticResource Header1}"
Grid.Column="1" Grid.Row="0">Uniform</TextBlock>
<TextBlock Style="{StaticResource Header1}"
Grid.Column="2" Grid.Row="0">UniformToFill</TextBlock>
<TextBlock Style="{StaticResource Header1}"
Grid.Column="3" Grid.Row="0">Fill</TextBlock>
<Border Grid.Column="0" Grid.Row="1" BorderThickness="1" BorderBrush="Black">
<!-- None: Image is not scaled. If image is larger than the
output area, the image will be cropped to the size of the output area.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="None" />
</Border>
<Border Grid.Column="1" Grid.Row="1" BorderThickness="1" BorderBrush="Black">
<!-- Uniform: Scale to fit output area.
Aspect ratio is preserved.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="Uniform" />
</Border>
<Border Grid.Column="2" Grid.Row="1" BorderThickness="1" BorderBrush="Black">
<!-- UniformToFill: Scale to completely fill output area.
Aspect ratio is preserved. Cropping may occur.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="UniformToFill" />
</Border>
<Border Grid.Column="3" Grid.Row="1" BorderThickness="1" BorderBrush="Black">
<!-- Fill: Scale to completely fill output area.
Aspect ratio may not be preserved.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="Fill" />
</Border>
</Grid>
</DockPanel>
</Page>
绘制图像
您还可以利用 Brush 进行绘制,从而在应用程序中显示图像。 利用画笔,您可以利用任意内容(从简单的纯色到复杂的图案和图像集)绘制 UI 对象。 若要绘制图像,请使用 ImageBrush。 ImageBrush 是一种 TileBrush 类型,用于将其内容定义为位图图像。 ImageBrush 显示由其 ImageSource 属性指定的单个图像。 您可以控制图像的拉伸、对齐和平铺方式,从而可以防止失真并生成图案和其他效果。 下图显示了利用 ImageBrush 可以达到的几种效果。
图像的画笔可以填充形状、控件、文本等
下面的示例演示如何使用 ImageBrush 绘制带图像的按钮的背景。
<!-- Sets the button's Background property with an ImageBrush. The resulting
button has an image as its background. -->
<Button Grid.Row="3" Grid.Column="2"
Height="75" Width="100" Foreground="White" FontWeight="Bold"
HorizontalAlignment="Left">
A Button
<Button.Background>
<ImageBrush ImageSource="sampleImages\blueberries.jpg" />
</Button.Background>
</Button>
有关 ImageBrush 和绘制图像的更多信息,请参见使用图像、绘图和 Visual 进行绘制。
图像元数据
某些图像文件包含用于描述文件的内容或特征的元数据。 例如,大多数数码相机创建的图像中包含用于捕获该图像的照相机的品牌和型号的元数据。 每个图像格式处理元数据的方式不同,但 WPF Imaging提供一种统一的方式来为每个支持的图像格式存储和检索元数据。
对元数据的访问是通过 BitmapSource 对象的 Metadata 属性提供的。 Metadata 返回一个 BitmapMetadata 对象,其中包含该图像所包含的所有元数据。 此数据可以位于一个元数据架构中或位于不同方案的组合中。 WPF Imaging支持以下图像元数据架构:Exchangeable image file (Exif)、tEXt(PNG 文本数据)、image file directory (IFD)、International Press Telecommunications Council (IPTC) 和Extensible Metadata Platform (XMP)。
为了简化读取元数据的过程,BitmapMetadata 提供易于访问的若干命名属性(如 Author、Title 和 CameraModel)。 许多命名属性还可以用于编写元数据。 元数据查询读取器提供对读取元数据的其他支持。 GetQuery 方法用于检索元数据查询读取器,这是通过提供字符串查询(如 "/app1/exif/")来实现的。 在下面的示例中,GetQuery 用于获取存储在 "/Text/Description" 位置中的文本。
' Add the metadata of the bitmap image to the text block.
Dim myTextBlock As New TextBlock()
myTextBlock.Text = "The Description metadata of this image is: " + pngInplace.GetQuery("/Text/Description").ToString()
// Add the metadata of the bitmap image to the text block.
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "The Description metadata of this image is: " + pngInplace.GetQuery("/Text/Description").ToString();
// Add the metadata of the bitmap image to the text block.
TextBlock^ myTextBlock = gcnew TextBlock();
myTextBlock->Text = "The Description metadata of this image is: " + pngInplace->GetQuery("/Text/Description")->ToString();
若要编写元数据,请使用元数据查询编写器。 SetQuery 包含查询编写器并设置所需的值。 在下面的示例中,SetQuery 用于编写存储在 "/Text/Description" 位置中的文本。
Dim pngStream As New System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
Dim pngDecoder As New PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default)
Dim pngFrame As BitmapFrame = pngDecoder.Frames(0)
Dim pngInplace As InPlaceBitmapMetadataWriter = pngFrame.CreateInPlaceBitmapMetadataWriter()
If pngInplace.TrySave() = True Then
pngInplace.SetQuery("/Text/Description", "Have a nice day.")
End If
pngStream.Close()
Stream pngStream = new System.IO.FileStream("smiley.png", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
PngBitmapDecoder pngDecoder = new PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapFrame pngFrame = pngDecoder.Frames[0];
InPlaceBitmapMetadataWriter pngInplace = pngFrame.CreateInPlaceBitmapMetadataWriter();
if (pngInplace.TrySave() == true)
{ pngInplace.SetQuery("/Text/Description", "Have a nice day."); }
pngStream.Close();
Stream^ pngStream = gcnew FileStream("smiley.png", FileMode::Open, FileAccess::ReadWrite, FileShare::ReadWrite);
PngBitmapDecoder^ pngDecoder = gcnew PngBitmapDecoder(pngStream, BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);
BitmapFrame^ pngFrame = pngDecoder->Frames[0];
InPlaceBitmapMetadataWriter^ pngInplace = pngFrame->CreateInPlaceBitmapMetadataWriter();
if (pngInplace->TrySave() == true)
{
pngInplace->SetQuery("/Text/Description", "Have a nice day.");
}
pngStream->Close();
编解码器扩展性
WPF Imaging的核心功能是用于新图像编解码器的扩展性模型。 通过这些非托管的接口,编解码器开发人员可以将编解码器与 WPF 集成,这样 WPF 应用程序就可以自动使用新的图像格式。
有关可扩展性 API 的示例,请参见 Win32 Sample Codec(Win32 示例编解码器)。 此示例演示如何为自定义图像格式创建解码器和编码器。
注意 |
---|
编解码器必须进行数字签名,以便于系统识别。 |