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

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

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

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

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

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

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

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

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

這里主要需要用到 CroppedBitmap類,該類主要用于裁剪,可以對(duì) BitmapImage進(jìn)行裁剪。

微信聊天氣泡這種場景,它需要支持水平和垂直的方向的拉伸效果,我們可以利用 CroppedBitmap,將原始圖片裁剪成9張圖,渲染的時(shí)候,我們分別將9張圖渲染到對(duì)應(yīng)的位置。拉伸的區(qū)域就是9張圖中的上面中間位置,下面中間位置,左邊中間位置,右邊中間位置以及最中間的位置。這幾張圖片,都按1個(gè)像素進(jìn)行裁剪,這樣就不會(huì)出現(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>
        /// 按水平方向進(jìn)行裁剪的偏移量
        /// </summary>
        public double HorizontalPrecent { get; set; }
 
        /// <summary>
        /// 按垂直方向進(jìn)行裁剪的偏移量
        /// </summary>
        public double VerticalPrecent { get; set; }
 
        //繪制水平+垂直拉伸的方法
        protected override void OnRender(DrawingContext drawingContext)
        {
            //這個(gè)需要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));
        }
 
        //測(cè)量布局大小,這里要記得重寫下。這個(gè)版本不支持不同尺寸的分辨率,可以通過計(jì)算縮放比來實(shí)現(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;
        }

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

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

相關(guān)文章

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

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

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

    c# EPPlus秘籍之Excel實(shí)現(xiàn)圖表導(dǎo)出

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

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

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

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

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

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

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

    C#圖像識(shí)別 微信跳一跳機(jī)器人

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

    Unity中的Tilemap流程分析

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

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

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

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

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

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

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

最新評(píng)論

嘉义市| 荣成市| 惠来县| 视频| 东安县| 新宾| 中阳县| 珲春市| 三江| 仙居县| 沙河市| 哈巴河县| 得荣县| 宿迁市| 北川| 张家川| 乌鲁木齐县| 鄂温| 万年县| 肥乡县| 横山县| 三门县| 玉龙| 雅江县| 山东| 宁武县| 句容市| 锡林浩特市| 江永县| 清镇市| 胶州市| 杭锦后旗| 五华县| 南澳县| 富锦市| 隆德县| 文山县| 大同市| 湘阴县| 炎陵县| 古丈县|