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

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ì)變形,但是長(zhǎng)的部分會(huì)被裁剪

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

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

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

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

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

微信聊天氣泡這種場(chǎng)景,它需要支持水平和垂直的方向的拉伸效果,我們可以利用 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è)量布局大小,這里要記得重寫(xiě)下。這個(gè)版本不支持不同尺寸的分辨率,可以通過(guò)計(jì)算縮放比來(lái)實(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)文章

最新評(píng)論