wpf图像控件样式及图像显示

Wpf图像显示

今天聊一聊wpf使用原生图像控件显示图像的那些事,作者也是找了很多资料,踩了很多坑,总结了以下几种方式。

前端样式

1. 图像背景小方格

图像背景方格是使用DrawingBrush来实现的,这样界面放大和缩小,方格块的大小不会变化,如果不想使用图像背景方格,用纯色甚至不设置背景都是可以的。

 <ResourceDictionary>
     <!--图像背景的小格子-->
     <DrawingBrush x:Key="ImageBackgroundIcon" Viewport="0,0,25,25" ViewportUnits="Absolute" TileMode="Tile">
         <DrawingBrush.Drawing>
             <DrawingGroup>
                 <DrawingGroup.Children>
                     <GeometryDrawing Brush="#D8D8D8">
                         <GeometryDrawing.Geometry>
                             <GeometryGroup>
                                 <RectangleGeometry Rect="0,0,100,100"/>
                                 <RectangleGeometry Rect="100,100,100,100" />
                             </GeometryGroup>
                         </GeometryDrawing.Geometry>
                     </GeometryDrawing>
                 </DrawingGroup.Children>
             </DrawingGroup>
         </DrawingBrush.Drawing>
     </DrawingBrush>
 </ResourceDictionary>

补充:DrawingBrush可以在控件的背景图上画线、画几何图形等,甚至Button的背景图片也可以使用DrawingBrush来实现

2.布局
 <Grid Background="#B0B0B0">
     <Border BorderBrush="{StaticResource ImageBackgroundIcon}" BorderThickness="3000"></Border>
     <Image Margin="10" Source="{Binding ImageProperty}" Stretch="Uniform" ></Image>
 </Grid>
3.效果

在这里插入图片描述

后端代码

采用MVVM的框架,ImageSource绑定到ViewModel里的WriteableBitmap类型

然后将本地图像根据路径转为WriteableBitmap类型,并通知界面显示。下面介绍如何将本地图像转为WriteableBitmap类型,主要介绍三种方法

方式一:
//方式一:
private WriteableBitmap GenImage1(string imagePath)
{
    //此方式对小图比较友好,大图加载比较慢
    Bitmap bitmap = new Bitmap(imagePath);
    WriteableBitmap wb = new WriteableBitmap(bitmap.Width, bitmap.Height, 96, 96, PixelFormats.Bgr24, null);
    wb.Lock();
    int width = wb.PixelWidth;
    int height = wb.PixelHeight;
    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            System.Drawing.Color pixel = bitmap.GetPixel(x, y);
            byte[] colorData = { pixel.B, pixel.G, pixel.R}; // B G R

            Int32Rect rect = new Int32Rect(x, y, 1, 1);
            int stride = wb.BackBufferStride;//单行像素数据中的字节数
            wb.WritePixels(rect, colorData, stride, 0);
        }
    }
    wb.Unlock();

    return wb;
}
方式二:
  //方式二:
  private WriteableBitmap GenImage2(string imagePath)
  {
      //
      Bitmap bitmap = new Bitmap(imagePath);
      MemoryStream stream = new MemoryStream();
      bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
      byte[] bytes = stream.GetBuffer();  //byte[]   bytes=   ms.ToArray(); 
      stream.Close();

      //
      WriteableBitmap wb = new WriteableBitmap(bitmap.Width, bitmap.Height, 96, 96, PixelFormats.Bgr24, null);
      unsafe
      {
          wb.Lock();
          Marshal.Copy(bytes, 0, wb.BackBuffer, bitmap.Width * bitmap.Height * 3);
          wb.AddDirtyRect(new Int32Rect(0, 0, bitmap.Width, bitmap.Height));
          wb.Unlock();
      }

      return wb;
  }

说明:stream.GetBuffer这种方式获得的图像数据上下颠倒的,显示的时候也是上下颠倒的,但是不影响使用,上下颠倒原因如下:

  • BMP图像文件中,图像数据是从最下面一行从左到右存放,然后是倒数第二行,一直到最上面一行。
  • 《Windows 图形编程》这本书里有解释原因,当时的设计者倾向于笛卡尔坐标系作为图像坐标系。

也可以使用自己的图像数据结构,这种方式显示的图像不会上下颠倒,我将图像的数据结构也放在下面,但是根据图像路径生成MyImage的方法要自己定义

 //方式二:
 private WriteableBitmap GenImage2(string imagePath)
 {
     //
     MyImage img = new MyImage(imagePath);
     WriteableBitmap wb = new WriteableBitmap(img.Width, img.Height, 96, 96, PixelFormats.Bgr24, null);
     unsafe
     {
         fixed (byte* pdata = img.Datas)
         {
             wb.Lock();
             Marshal.Copy(img.Datas, 0, wb.BackBuffer, img.Width * img.Height * 3);
             wb.AddDirtyRect(new Int32Rect(0, 0, img.Width, img.Height));
             wb.Unlock();
         }
     }
     return wb;
 }
 
 //图像数据结构
 public class MyImage
 {
     public int Width;
     public int Height;
     public byte[] Datas;
 }
方式三:
 //方式三:
 private WriteableBitmap GenImage3(string imagePath)
 {
     Bitmap bitmap= new Bitmap(imagePath);

     // 将Bitmap转换为MemoryStream
     System.IO.MemoryStream stream = new System.IO.MemoryStream();
     bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
     stream.Position = 0;

     // 创建WriteableBitmap
     BitmapImage bitmapImage = new BitmapImage();
     bitmapImage.BeginInit();
     bitmapImage.StreamSource = stream;
     bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
     bitmapImage.EndInit();

     // 将BitmapImage转换为WriteableBitmap
     WriteableBitmap writeableBitmap = new WriteableBitmap(bitmapImage);

     // 返回WriteableBitmap
     return writeableBitmap;
 }
效果

在这里插入图片描述

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值