最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

WPF實現(xiàn)圖片按像素拉伸

 更新時間:2024年11月04日 10:14:54   作者:冷眼Σ(-?_-??)  
這篇文章主要為大家詳細介紹了WPF實現(xiàn)圖片按像素拉伸的相關(guān)知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

WPF中的圖片組件,本身是支持不同的拉伸效果。具體如下:

  • None, 不做拉伸
  • Fill 完全填充(會變形)
  • Uniform 等比縮放,不會變形
  • UniformToFill 等比縮放,并完全填充。不會變形,但是長的部分會被裁剪

但是,如果我們要實現(xiàn)像QQ或者微信這樣子的聊天氣泡功能,直接使用圖片組件就無法滿足要求了。

我們可以觀察下微信的聊天氣泡,他的寬度和高度可以根據(jù)我們輸入的內(nèi)容自動調(diào)整,并且背景圖片也不會存在變形的問題。

今天我們就用WPF來實現(xiàn)這個功能!

要實現(xiàn)不變形的拉伸功能,我們可以針對1個像素來進行拉伸,這樣拉伸出來的圖片,除了拉伸區(qū)域的像素都是一樣的,其它區(qū)域還是保留了原來的圖片的外觀。

這里主要需要用到 CroppedBitmap類,該類主要用于裁剪,可以對 BitmapImage進行裁剪。

微信聊天氣泡這種場景,它需要支持水平和垂直的方向的拉伸效果,我們可以利用 CroppedBitmap,將原始圖片裁剪成9張圖,渲染的時候,我們分別將9張圖渲染到對應的位置。拉伸的區(qū)域就是9張圖中的上面中間位置,下面中間位置,左邊中間位置,右邊中間位置以及最中間的位置。這幾張圖片,都按1個像素進行裁剪,這樣就不會出現(xiàn)拉伸的圖片了。

關(guān)鍵代碼:

        //根據(jù)裁剪區(qū)域,獲取裁剪后的圖片。ImageSource指的是原始圖片
        private ImageSource GetCroppedBitmap(double x, double y, double width, double height)
        {
            return new CroppedBitmap(ImageSource, new Int32Rect((int)x, (int)y, (int)width, (int)height));
        }
 
        /// <summary>
        /// 獲取水平偏移像素值
        /// </summary>
        /// <returns></returns>
        private int GetHorizontalOffset()
        {
            return (int)(HorizontalPrecent * ImageSource.Width / 100);
        }
 
        /// <summary>
        /// 獲取垂直位置的偏移像素值
        /// </summary>
        /// <returns></returns>
        private int GetVerticalOffset()
        {
            return (int)(VerticalPrecent * ImageSource.Height / 100);
        }
 
        /// <summary>
        /// 獲取水平偏移像素值
        /// </summary>
        /// <returns></returns>
        private int GetStretchHeight()
        {
            return (int)(RenderSize.Height - ImageSource.Height);
        }
 
        /// <summary>
        /// 獲取垂直位置的偏移像素值
        /// </summary>
        /// <returns></returns>
        private int GetStretchWidth()
        {
            return (int)(RenderSize.Width - ImageSource.Width);
        }
 
        /// <summary>
        /// 水平拉伸是否可用
        /// </summary>
        private bool IsHorizontalStretchEnabled
        {
            get
            {
                if (HorizontalPrecent > 0 && HorizontalPrecent < 100)
                {
                    return true;
                }
                return false;
            }
        }
 
        /// <summary>
        /// 按水平方向進行裁剪的偏移量
        /// </summary>
        public double HorizontalPrecent { get; set; }
 
        /// <summary>
        /// 按垂直方向進行裁剪的偏移量
        /// </summary>
        public double VerticalPrecent { get; set; }
 
        //繪制水平+垂直拉伸的方法
        protected override void OnRender(DrawingContext drawingContext)
        {
            //這個需要9張圖
            //左上,左中,左下,右上,右中,右下,水平中,垂直中
            var horizontalOffset = GetHorizontalOffset();
            var verticalOffset = GetVerticalOffset();
            var leftTop = GetCroppedBitmap(0, 0, horizontalOffset, verticalOffset);
            var leftBottom = GetCroppedBitmap(0, verticalOffset + 1, horizontalOffset, ImageSource.Height - verticalOffset - 1);
            var rightTop = GetCroppedBitmap(horizontalOffset + 1, 0, ImageSource.Width - horizontalOffset - 1, ImageSource.Height - verticalOffset - 1);
            var rightBottom = GetCroppedBitmap(horizontalOffset + 1, verticalOffset + 1, ImageSource.Width - horizontalOffset - 1, ImageSource.Height - verticalOffset - 1);
            //最中間的
            var center = GetCroppedBitmap(horizontalOffset, verticalOffset, 1, 1);
            var leftCenter = GetCroppedBitmap(0, verticalOffset + 1, horizontalOffset, 1);
            var rightCenter = GetCroppedBitmap(horizontalOffset + 1, verticalOffset + 1, ImageSource.Width - horizontalOffset - 1, 1);
            var topCenter = GetCroppedBitmap(horizontalOffset + 1, 0, 1, verticalOffset);
            var bottomCenter = GetCroppedBitmap(horizontalOffset + 1, verticalOffset + 1, 1, ImageSource.Height - verticalOffset - 1);
            //------------------------------- 上面的邏輯是切圖,下面的邏輯是繪制 -----------------------------------
            var stretchHeight = GetStretchHeight();
            if (stretchHeight < 0) stretchHeight = 0;
            var stretchWidth = GetStretchWidth();
            if (stretchWidth < 0) stretchWidth = 0;
            drawingContext.DrawImage(leftTop, new Rect(0, 0, horizontalOffset, verticalOffset));
            drawingContext.DrawImage(rightTop, new Rect(horizontalOffset + stretchWidth, 0, ImageSource.Width - horizontalOffset - 1, ImageSource.Height - verticalOffset));
            //繪制水平方向的拉伸像素
            if (stretchHeight > 0)
            {
                drawingContext.DrawImage(leftCenter, new Rect(0, verticalOffset, horizontalOffset, stretchHeight));
                drawingContext.DrawImage(rightCenter, new Rect(horizontalOffset + stretchWidth, verticalOffset, ImageSource.Width - horizontalOffset - 1, stretchHeight));
            }
            //繪制垂直方向的拉伸像素
            if (stretchWidth > 0)
            {
                drawingContext.DrawImage(topCenter, new Rect(horizontalOffset, 0, stretchWidth, verticalOffset));
                drawingContext.DrawImage(bottomCenter, new Rect(horizontalOffset, verticalOffset + stretchHeight, stretchWidth, ImageSource.Height - verticalOffset - 1));
            }
            //繪制中間拉伸的像素
            if (stretchHeight > 0 && stretchWidth > 0)
            {
                drawingContext.DrawImage(center, new Rect(horizontalOffset, verticalOffset, stretchWidth, stretchHeight));
            }
 
            drawingContext.DrawImage(leftBottom, new Rect(0, verticalOffset + stretchHeight, horizontalOffset, ImageSource.Height - verticalOffset - 1));
            drawingContext.DrawImage(rightBottom, new Rect(horizontalOffset + stretchWidth, verticalOffset + stretchHeight, ImageSource.Width - horizontalOffset - 1, ImageSource.Height - verticalOffset - 1));
        }
 
        //僅支持水平方向拉伸
        protected override void OnRender(DrawingContext drawingContext)
        {
            var horizontalOffset = GetHorizontalOffset();
            var left = GetCroppedBitmap(0, 0, horizontalOffset, ImageSource.Height);
            var center = GetCroppedBitmap(horizontalOffset, 0, 1, ImageSource.Height);
            var right = GetCroppedBitmap(horizontalOffset + 1, 0, ImageSource.Width - horizontalOffset - 1, ImageSource.Height);
            drawingContext.DrawImage(left, new Rect(0, 0, horizontalOffset, ImageSource.Height));
            var stretchWidth = GetStretchWidth();
            if (stretchWidth > 0)
            {
                drawingContext.DrawImage(center, new Rect(horizontalOffset, 0, stretchWidth, ImageSource.Height));
            }
            else
            {
                stretchWidth = 0;
            }
            drawingContext.DrawImage(right, new Rect(horizontalOffset + stretchWidth, 0, ImageSource.Width - horizontalOffset - 1, ImageSource.Height));
        }
 
        //僅支持垂直方向拉伸
        protected override void OnRender(DrawingContext drawingContext)
        {
            var verticalOffset = GetVerticalOffset();
            var top = GetCroppedBitmap(0, 0, ImageSource.Width, verticalOffset);
            var center = GetCroppedBitmap(0, verticalOffset, ImageSource.Width, 1);
            var bottom = GetCroppedBitmap(0, verticalOffset + 1, ImageSource.Width, ImageSource.Height - verticalOffset - 1);
            drawingContext.DrawImage(top, new Rect(0, 0, ImageSource.Width, verticalOffset));
            var stretchHeight = GetStretchHeight();
            if (stretchHeight > 0)
            {
                drawingContext.DrawImage(center, new Rect(0, verticalOffset, ImageSource.Width, stretchHeight));
            }
            else
            {
                stretchHeight = 0;
            }
            drawingContext.DrawImage(bottom, new Rect(0, verticalOffset + stretchHeight, ImageSource.Width, ImageSource.Height - verticalOffset - 1));
        }
 
        //測量布局大小,這里要記得重寫下。這個版本不支持不同尺寸的分辨率,可以通過計算縮放比來實現(xiàn)
        private Size MeasureCore(Size size, ImageSource imgSource)
        {
            if (imgSource == null) return size;
 
            Size naturalSize;
 
            if (IsHorizontalStretchEnabled && IsVerticalStretchEnabled)
            {
                naturalSize = new Size(size.Width, size.Height);
            }
            else if (IsHorizontalStretchEnabled)
            {
                naturalSize = new Size(size.Width, imgSource.Height);
            }
            else if (IsVerticalStretchEnabled)
            {
                naturalSize = new Size(imgSource.Width, size.Height);
            }
            else
            {
                return size;
            }
 
            return naturalSize;
        }

以上代碼就可以實現(xiàn)水平拉伸,垂直拉伸或者水平+垂直拉伸的功能了。目前的測試代碼還不支持不同分辨率的圖片,demo中的計算是使用了ImageSource的寬高。如果需要支持任意分辨率,可以按渲染的寬高和圖片的實際寬高做個比例縮放運算即可。

到此這篇關(guān)于WPF實現(xiàn)圖片按像素拉伸的文章就介紹到這了,更多相關(guān)WPF圖片按像素拉伸內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#多線程系列之a(chǎn)sync和await用法詳解

    C#多線程系列之a(chǎn)sync和await用法詳解

    本文詳細講解了C#多線程中async和await的用法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • c# EPPlus秘籍之Excel實現(xiàn)圖表導出

    c# EPPlus秘籍之Excel實現(xiàn)圖表導出

    這篇文章主要為大家介紹了c# EPPlus秘籍之Excel實現(xiàn)圖表導出示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • C#的path.GetFullPath 獲取上級目錄實現(xiàn)方法

    C#的path.GetFullPath 獲取上級目錄實現(xiàn)方法

    這篇文章主要介紹了C#的path.GetFullPath 獲取上級目錄實現(xiàn)方法,包含了具體的C#實現(xiàn)方法以及ASP.net與ASP等的方法對比,非常具有實用價值,需要的朋友可以參考下
    2014-10-10
  • C#處理datagridview虛擬模式的方法

    C#處理datagridview虛擬模式的方法

    這篇文章主要介紹了C#處理datagridview虛擬模式的方法,實例分析了C#中datagridview的使用技巧,需要的朋友可以參考下
    2015-06-06
  • C#中圖片.BYTE[]和base64string的轉(zhuǎn)換方法

    C#中圖片.BYTE[]和base64string的轉(zhuǎn)換方法

    下面小編就為大家?guī)硪黄狢#中圖片.BYTE[]和base64string的轉(zhuǎn)換方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • C#圖像識別 微信跳一跳機器人

    C#圖像識別 微信跳一跳機器人

    這篇文章主要為大家詳細介紹了C#圖像識別,微信跳一跳機器人,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Unity中的Tilemap流程分析

    Unity中的Tilemap流程分析

    這篇文章給大家介紹Unity中的Tilemap流程分析,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-07-07
  • C#使用HtmlAgilityPack組件解析html文檔

    C#使用HtmlAgilityPack組件解析html文檔

    這篇文章介紹了C#使用HtmlAgilityPack組件解析html文檔的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • c#中生成隨機數(shù)的五種方法

    c#中生成隨機數(shù)的五種方法

    本文主要介紹了c#中生成隨機數(shù)的五種方法,包括Random類(、System.Random.Shared、RandomNumberGenerator、GUID、RNGCryptoServiceProvider,下面就來具體介紹一下每個的適用場景,感興趣的可以了解一下
    2025-07-07
  • C# Web應用調(diào)試開啟外部訪問步驟解析

    C# Web應用調(diào)試開啟外部訪問步驟解析

    本文主要介紹了C# Web應用調(diào)試開啟外部訪問的實現(xiàn)過程與方法。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01

最新評論

海淀区| 诸暨市| 凤凰县| 竹溪县| 婺源县| 肇庆市| 离岛区| 张掖市| 乐陵市| 定远县| 南澳县| 陆丰市| 永仁县| 米脂县| 三江| 苏州市| 承德市| 武邑县| 尚义县| 霸州市| 沁源县| 新乡县| 勐海县| 黄龙县| 台南市| 西林县| 南乐县| 富裕县| 鄂伦春自治旗| 无锡市| 天津市| 尼勒克县| 松潘县| 原阳县| 慈溪市| 色达县| 金沙县| 宕昌县| 太湖县| 麟游县| 唐山市|