在做界面的时候,有时是很小的一张图片,我们不能直接将其放大,而是需要九宫格处理,所以android就原生支持.
这是网上找的一段代码,自己经过一些修改。
一个帮助类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace FYJ.Winui.Util
{
public class DrawingHelper
{
#region 分割图片
private static ImageSource SplitImage(BitmapSource source, Int32Rect clipRect)
{
ImageSource results = null;
var stride = clipRect.Width * ((source.Format.BitsPerPixel + 7) / 8);
var pixelsCount = clipRect.Width * clipRect.Height;//tileWidth * tileHeight;
var tileRect = new Int32Rect(0, 0, clipRect.Width, clipRect.Height);
var pixels = new int[pixelsCount];
//var copyRect = new Int32Rect(col * tileWidth, row * tileHeight, tileWidth, tileHeight);
source.CopyPixels(clipRect, pixels, stride, 0);
var wb = new WriteableBitmap(
clipRect.Width,
clipRect.Height,
source.DpiX,
source.DpiY,
source.Format,
source.Palette);
wb.Lock();
wb.WritePixels(tileRect, pixels, stride, 0);
wb.Unlock();
results = wb;
return results;
}
private static ImageSource[] Get9CellImageSource(BitmapSource source, Int32Rect clipRect)
{
ImageSource[] results = new ImageSource[9];
Int32Rect rect = Int32Rect.Empty;
int rightSideWidth = (int)(source.PixelWidth - clipRect.X - clipRect.Width);
//top-left
rect.Width = clipRect.X;
rect.Height = clipRect.Y;
results[0] = SplitImage(source, rect);
//return results;
//top-middle
rect.X += rect.Width;
rect.Width = clipRect.Width;
results[1] = SplitImage(source, rect);
//top-right
rect.X += rect.Width;
rect.Width = rightSideWidth;
results[2] = SplitImage(source, rect);
//left side
rect = Int32Rect.Empty;
rect.Y = clipRect.Y;
rect.Width = clipRect.X;
rect.Height = clipRect.Height;
results[3] = SplitImage(source, rect);
//middle
rect.X += rect.Width;
rect.Width = clipRect.Width;
results[4] = SplitImage(source, rect);
//right side
rect.X += rect.Width;
rect.Width = rightSideWidth;
results[5] = SplitImage(source, rect);
//bottom-left
rect = Int32Rect.Empty;
rect.Y = clipRect.Y + clipRect.Height;
// rect.X = clipRect.X;
rect.Height = source.PixelHeight - clipRect.Height - clipRect.Y;
rect.Width = clipRect.X;
results[6] = SplitImage(source, rect);
//bottom-middle
rect.X += rect.Width;
rect.Width = clipRect.Width;
results[7] = SplitImage(source, rect);
//bottom-right
rect.X += rect.Width;
rect.Width = rightSideWidth;
results[8] = SplitImage(source, rect);
return results;
}
#endregion
/// <summary>
/// 创建平铺的图片
/// </summary>
/// <param name="source">源图片</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <returns></returns>
public static BitmapSource CreateTileImage(BitmapSource source, int width, int height)
{
RenderTargetBitmap composeImage = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
Brush bc = new SolidColorBrush(Colors.Blue);
drawingContext.DrawRectangle(bc,null,new Rect(0,0,width,height));
//int i = width/(int)source.Width;
//int j = height/(int)source.Height;
for(int i=0;i<=width/(int)source.Width;i++)
{
for(int j=0;j<=height/(int)source.Height;j++)
{
drawingContext.DrawImage(source, new Rect(i * source.Width, j*source.Height, source.Width, source.Height));
}
}
drawingContext.Close();
composeImage.Render(drawingVisual);
return composeImage;
}
}
}实现类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace FYJ.Winui.Controls
{
/// <summary>
/// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
///
/// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
/// 元素中:
///
/// xmlns:MyNamespace="clr-namespace:FYJ.Winui.Controls"
///
///
/// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
/// 元素中:
///
/// xmlns:MyNamespace="clr-namespace:FYJ.Winui.Controls;assembly=FYJ.Winui.Controls"
///
/// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
/// 并重新生成以避免编译错误:
///
/// 在解决方案资源管理器中右击目标项目,然后依次单击
/// “添加引用”->“项目”->[浏览查找并选择此项目]
///
///
/// 步骤 2)
/// 继续操作并在 XAML 文件中使用控件。
///
/// <MyNamespace:Image9Cell/>
///
/// </summary>
public class Image9Cell : Image
{
static Image9Cell()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Image9Cell), new FrameworkPropertyMetadata(typeof(Image9Cell)));
}
public Int32Rect ContentRect
{
get;
set;
}
public bool DrawImageWith9Cells
{
get;
set;
}
private BitmapSource SplitImage(BitmapSource source, Int32Rect clipRect)
{
BitmapSource results = null;
var stride = clipRect.Width * ((source.Format.BitsPerPixel + 7) / 8);
var pixelsCount = clipRect.Width * clipRect.Height;
var tileRect = new Int32Rect(0, 0, clipRect.Width, clipRect.Height);
var pixels = new int[pixelsCount];
source.CopyPixels(clipRect, pixels, stride, 0);
var wb = new WriteableBitmap(
clipRect.Width,
clipRect.Height,
source.DpiX,
source.DpiY,
source.Format,
source.Palette);
wb.Lock();
wb.WritePixels(tileRect, pixels, stride, 0);
wb.Unlock();
results = wb;
return results;
}
private Int32Rect[] Get9Int32Rect(BitmapSource source, Int32Rect contentRect)
{
Int32Rect[] results = new Int32Rect[9];
results[0] = new Int32Rect(0, 0, contentRect.X, contentRect.Y);
results[1] = new Int32Rect(contentRect.X, 0, contentRect.Width, contentRect.Y);
results[2] = new Int32Rect(contentRect.X + contentRect.Width, 0, source.PixelWidth - contentRect.Width - contentRect.X, contentRect.Y);
results[3] = new Int32Rect(0, contentRect.Y, contentRect.X, contentRect.Height);
results[4] = new Int32Rect(contentRect.X, contentRect.Y, contentRect.Width, contentRect.Height);
results[5] = new Int32Rect(contentRect.X + contentRect.Width, contentRect.Y, source.PixelWidth - contentRect.Width - contentRect.X, contentRect.Height);
results[6] = new Int32Rect(0, contentRect.Y + contentRect.Height, contentRect.X, source.PixelHeight - contentRect.Y - contentRect.Height);
results[7] = new Int32Rect(contentRect.X, contentRect.Y + contentRect.Height, contentRect.Width, source.PixelHeight - contentRect.Y - contentRect.Height);
results[8] = new Int32Rect(contentRect.X + contentRect.Width, contentRect.Y + contentRect.Height, source.PixelWidth - contentRect.Width - contentRect.X, source.PixelHeight - contentRect.Y - contentRect.Height);
return results;
}
private BitmapSource[] Get9CellImageSource(BitmapSource source, Int32Rect contentRect)
{
BitmapSource[] results = new BitmapSource[9];
Int32Rect[] rects = Get9Int32Rect(source, contentRect);
for (int i = 0; i < results.Length; i++)
{
results[i] = SplitImage(source, rects[i]);
}
return results;
}
protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
if (DrawImageWith9Cells == false)
{
base.OnRender(dc);
return;
}
BitmapSource image = (BitmapSource)this.Source;
BitmapSource resultImage = this.Create9CellImage(image, new Int32Rect(5, 31, image.PixelWidth - 10, image.PixelHeight - 31 - 34), (int)this.Width, (int)this.Height);
dc.DrawImage(resultImage,new Rect(0,0,this.Width,this.Height));
}
/// <summary>
/// 创建平铺的图片
/// </summary>
/// <author>fangyj</author>
/// <param name="source">源图片</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <returns></returns>
private BitmapSource CreateTileImage(BitmapSource source, int width, int height)
{
RenderTargetBitmap composeImage = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
ImageBrush brush = new ImageBrush();
brush.ImageSource = source;
brush.TileMode = TileMode.Tile;
drawingContext.DrawRectangle(brush, null, new Rect(0, 0, width, height));
drawingContext.Close();
composeImage.Render(drawingVisual);
return composeImage;
}
/// <summary>
/// 创建9宫格图片
/// </summary>
/// <param name="source"></param>
/// <param name="contentRect"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
public BitmapSource Create9CellImage(BitmapSource source, Int32Rect contentRect, int width, int height)
{
BitmapSource[] images = Get9CellImageSource(source, contentRect);
RenderTargetBitmap composeImage = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
// Brush bc = new SolidColorBrush(Colors.Blue);
// drawingContext.DrawRectangle(bc, null, new Rect(0, 0, width, height));
drawingContext.DrawImage(images[0],new Rect(0,0,contentRect.X,contentRect.Y));
//横行平铺
drawingContext.DrawImage(CreateTileImage(images[1], width - images[0].PixelWidth - images[2].PixelWidth, contentRect.Y), new Rect(contentRect.X, 0, width - images[0].PixelWidth - images[2].PixelWidth, contentRect.Y));
drawingContext.DrawImage(images[2], new Rect(width - images[2].PixelWidth, 0, images[2].PixelWidth, images[2].PixelHeight));
drawingContext.DrawImage(images[3], new Rect(0, contentRect.Y, images[3].PixelWidth,height- images[0].PixelHeight-images[6].PixelHeight));
//两边平铺
drawingContext.DrawImage(CreateTileImage(images[4], width - images[3].PixelWidth - images[5].PixelWidth, height - images[1].PixelHeight - images[7].PixelHeight), new Rect(contentRect.X, contentRect.Y, width - images[0].PixelWidth - images[2].PixelWidth, height - images[1].PixelHeight - images[7].PixelHeight));
drawingContext.DrawImage(images[5], new Rect(width - images[5].PixelWidth, contentRect.Y, images[5].PixelWidth, height - images[0].PixelHeight - images[6].PixelHeight));
drawingContext.DrawImage(images[6], new Rect(0, height - images[6].PixelHeight, images[6].PixelWidth, images[6].PixelHeight));
//横向拉伸
drawingContext.DrawImage(CreateTileImage(images[7], width - images[6].PixelWidth - images[8].PixelWidth, images[7].PixelHeight), new Rect(contentRect.X, height - images[6].PixelHeight, width - images[6].PixelWidth - images[8].PixelWidth, images[7].PixelHeight));
drawingContext.DrawImage(images[8], new Rect(width-images[8].PixelWidth, height - images[6].PixelHeight, images[8].PixelWidth, images[8].PixelHeight));
drawingContext.Close();
composeImage.Render(drawingVisual);
return composeImage;
}
}
}
珂珂的个人博客 - 一个程序猿的个人网站