欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

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

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

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

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

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

微信聊天氣泡這種場景,它需要支持水平和垂直的方向的拉伸效果,我們可以利用 CroppedBitmap,將原始圖片裁剪成9張圖,渲染的時候,我們分別將9張圖渲染到對應的位置。拉伸的區(qū)域就是9張圖中的上面中間位置,下面中間位置,左邊中間位置,右邊中間位置以及最中間的位置。這幾張圖片,都按1個像素進行裁剪,這樣就不會出現(xià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的寬高。如果需要支持任意分辨率,可以按渲染的寬高和圖片的實際寬高做個比例縮放運算即可。

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

相關文章

  • C#使用Mutex簡單實現(xiàn)程序單實例運行的方法

    C#使用Mutex簡單實現(xiàn)程序單實例運行的方法

    這篇文章主要介紹了C#使用Mutex簡單實現(xiàn)程序單實例運行的方法,涉及C#實現(xiàn)單實例程序運行的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • 詳解C# FileStream類

    詳解C# FileStream類

    這篇文章主要介紹了詳解C# FileStream類的相關知識,文中講解的非常細致,代碼供大家參考和學習,感興趣的朋友可以了解下
    2020-06-06
  • C#使用RestSharp實現(xiàn)封裝常用的http請求方法

    C#使用RestSharp實現(xiàn)封裝常用的http請求方法

    這篇文章主要為大家詳細介紹了C#如何使用RestSharp實現(xiàn)封裝常用的http請求方法,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2024-02-02
  • C#中struct與class的區(qū)別詳解

    C#中struct與class的區(qū)別詳解

    本文主要介紹了C#中struct與class的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • C#異步編程幾點需要注意的地方

    C#異步編程幾點需要注意的地方

    這篇文章我們來討論下關于C#異步編程幾個不成文的建議,希望對你寫出高性能的異步編程代碼有所幫助
    2020-05-05
  • C#/VB.NET實現(xiàn)PPT或PPTX轉換為圖像功能

    C#/VB.NET實現(xiàn)PPT或PPTX轉換為圖像功能

    由于大多數(shù)便攜式設備支持瀏覽圖片而不支持瀏覽PowerPoint 文件,所以相比較而言,圖像對于用戶而言更加友好。本文將利用C#/VB.NET實現(xiàn)PPT或PPTX轉換為圖像功能,需要的可以參考一下
    2022-08-08
  • C#多線程異步執(zhí)行和跨線程訪問控件Helper

    C#多線程異步執(zhí)行和跨線程訪問控件Helper

    這篇文章介紹了C#多線程異步執(zhí)行和跨線程訪問控件Helper,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • C# winfrom 模擬ftp文件管理實現(xiàn)代碼

    C# winfrom 模擬ftp文件管理實現(xiàn)代碼

    從網(wǎng)上找到的非常好用的模擬ftp管理代碼,整理了一下,希望對需要的人有幫助
    2014-01-01
  • C#實現(xiàn)動態(tài)加載dll的方法

    C#實現(xiàn)動態(tài)加載dll的方法

    這篇文章主要介紹了C#實現(xiàn)動態(tài)加載dll的方法,涉及針對動態(tài)鏈接庫的靈活操作技巧,具有一定的參考借鑒價值,需要的朋友可以參考下
    2014-12-12
  • 使用mutex實現(xiàn)應用程序單實例運行代碼分享

    使用mutex實現(xiàn)應用程序單實例運行代碼分享

    本文主要介紹了使用Mutex實現(xiàn)應用程序單實例運行的方法,實現(xiàn)原理是在程序啟動時,請求一個互斥體,如果能獲取對指定互斥的訪問權,就繼續(xù)運行程序,否則就退出程序
    2014-01-01

最新評論