珂珂的个人博客 - 一个程序猿的个人网站

WPF九宫格切图

   在做界面的时候,有时是很小的一张图片,我们不能直接将其放大,而是需要九宫格处理,所以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;
        }
    }
}



上一篇:wordpress3.6 修改的地方

下一篇:个人代码全部开源


0 评论

查看所有评论

给个评论吧