c# 9png实现(图片缩放)
跟据9png的实现原理自己写了个生成图片的函数,9png的原理是将图片切成9块如下
其中1、3、7、9不进行缩放,2,4,5,6,8进行缩放,这样就防止了放大后导致边界出现锯齿的问题
在实现过程中主要的就是找到4个关键点,如下
然后根据p1,p2,p3,p4将原图画到新大小的图上
具体代码如下
获得关键点
/// <summary> /// 获取4个关键坐标点左边1,2 上边1,2 /// </summary> /// <param name="bitmap">图片</param> /// <param name="backColor">背景色</param> /// <param name="intAalpha">透明度</param> /// <returns>0:左1 1:左2 2:上1 3:上2</returns> private Point[] GetIndex(Bitmap bitmap, Color? backColor = null, int intAalpha = 0) { int intTop = 0; int intRight = 0; int intBottom = 0; int intLeft = 0; Point ptop1 = Point.Empty, ptop2 = Point.Empty; Point pleft1 = Point.Empty, pleft2 = Point.Empty; Point pbottom1 = Point.Empty, pbottom2 = Point.Empty; Point pright1 = Point.Empty, pright2 = Point.Empty; #region 边界 //left for (int x = 0; x < bitmap.Width; x++) { for (int y = 0; y < bitmap.Height; y++) { Color c = bitmap.GetPixel(x, y); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } intLeft = x; x = int.MaxValue - 10; break; } } //right for (int x = bitmap.Width - 1; x >= 0; x--) { for (int y = 0; y < bitmap.Height; y++) { Color c = bitmap.GetPixel(x, y); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } intRight = x; x = -10; break; } } //top for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { Color c = bitmap.GetPixel(x, y); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } intTop = y; y = int.MaxValue - 10; break; } } //bottom for (int y = bitmap.Height - 1; y >= 0; y--) { for (int x = 0; x < bitmap.Width; x++) { Color c = bitmap.GetPixel(x, y); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } intBottom = y; y = -10; break; } } #endregion #region 顶点 bool blnGet1 = false; bool blnGet2 = false; //上1 下1 for (int x = 0; x < bitmap.Width; x++) { //上1 if (!blnGet1) { Color c = bitmap.GetPixel(x, intTop); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } ptop1 = new Point(x, intTop); blnGet1 = true; } //下1 if (!blnGet2) { Color c = bitmap.GetPixel(x, intBottom); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } pbottom1 = new Point(x, intBottom); blnGet2 = true; } if (blnGet1 && blnGet2) { break; } } blnGet1 = false; blnGet2 = false; //上2 下2 for (int x = bitmap.Width - 1; x >= 0; x--) { //上2 if (!blnGet1) { Color c = bitmap.GetPixel(x, intTop); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } ptop2 = new Point(x, intTop); blnGet1 = true; } //下2 if (!blnGet2) { Color c = bitmap.GetPixel(x, intBottom); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } pbottom2 = new Point(x, intBottom); blnGet2 = true; } if (blnGet1 && blnGet2) { break; } } blnGet1 = false; blnGet2 = false; //左1 右1 for (int y = 0; y < bitmap.Height; y++) { //左1 if (!blnGet1) { Color c = bitmap.GetPixel(intLeft, y); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } pleft1 = new Point(intLeft, y); blnGet1 = true; } //右1 if (!blnGet2) { Color c = bitmap.GetPixel(intRight, y); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } pright1 = new Point(intRight, y); blnGet2 = true; } if (blnGet1 && blnGet2) { break; } } blnGet1 = false; blnGet2 = false; //左2 右2 for (int y = bitmap.Height - 1; y >= 0; y--) { //左2 if (!blnGet1) { Color c = bitmap.GetPixel(intLeft, y); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } pleft2 = new Point(intLeft, y); blnGet1 = true; } //右2 if (!blnGet2) { Color c = bitmap.GetPixel(intRight, y); if (c.A <= intAalpha) continue; if (backColor.HasValue && c.ToArgb() == backColor.Value.ToArgb()) { continue; } pright2 = new Point(intRight, y); blnGet2 = true; } if (blnGet1 && blnGet2) { break; } } #endregion Point pRleft1, pRleft2; Point pRtop1, pRtop2; int intLeftMax = Math.Max(ptop1.X, pbottom1.X); int intRightMin = Math.Min(ptop2.X, pbottom2.X); int intTopMax = Math.Max(pleft1.Y, pright1.Y); int intBottomMin = Math.Min(pleft2.Y, pright2.Y); if (intRightMin - intLeftMax ==0) { intRightMin = intRightMin + 1; } else if (intRightMin - intLeftMax > 4) { intRightMin = intRightMin - 2; intLeftMax = intLeftMax + 2; } if (intBottomMin - intTopMax == 0) { intBottomMin = intBottomMin + 1; } else if (intBottomMin - intTopMax > 4) { intBottomMin = intBottomMin - 2; intTopMax = intTopMax + 2; } pRleft1 = new Point(intLeft, intTopMax); pRleft2 = new Point(intLeft, intBottomMin); pRtop1 = new Point(intLeftMax, intTop); pRtop2 = new Point(intRightMin, intTop); Point[] ps = new Point[4]; ps[0] = pRleft1; ps[1] = pRleft2; ps[2] = pRtop1; ps[3] = ptop2; return ps; }
画图
private Bitmap CreateBitmap(Bitmap bitmap, Point[] ps, Size size) { Bitmap _returnBitmap = new Bitmap(size.Width, size.Height); Graphics g = Graphics.FromImage(_returnBitmap); //左上角 Rectangle destRect = new Rectangle(new Point(0, 0), new Size(ps[2].X, ps[0].Y)); g.DrawImage(bitmap, destRect, 0, 0, ps[2].X, ps[0].Y, GraphicsUnit.Pixel); //右上角 destRect = new Rectangle(new Point(size.Width - (bitmap.Width - ps[3].X), ps[3].Y), new Size(bitmap.Width - ps[3].X, ps[0].Y)); g.DrawImage(bitmap, destRect, ps[3].X, ps[3].Y, bitmap.Width - ps[3].X, ps[0].Y, GraphicsUnit.Pixel); //左下角 destRect = new Rectangle(new Point(0, size.Height - (bitmap.Height - ps[1].Y)), new Size(ps[2].X, bitmap.Height - ps[1].Y)); g.DrawImage(bitmap, destRect, 0, ps[1].Y, ps[2].X, (bitmap.Height - ps[1].Y), GraphicsUnit.Pixel); //右下角 destRect = new Rectangle(new Point(size.Width - (bitmap.Width - ps[3].X), size.Height - (bitmap.Height - ps[1].Y)), new Size(bitmap.Width - ps[3].X, bitmap.Height - ps[1].Y)); g.DrawImage(bitmap, destRect, ps[3].X, ps[1].Y, bitmap.Width - ps[3].X, bitmap.Height - ps[1].Y, GraphicsUnit.Pixel); //上中 destRect = new Rectangle(new Point(ps[2].X, 0), new Size(size.Width - ps[2].X - (bitmap.Width - ps[3].X), ps[0].Y)); g.DrawImage(bitmap, destRect, ps[2].X, 0, ps[3].X - ps[2].X, ps[0].Y, GraphicsUnit.Pixel); //下中 destRect = new Rectangle(new Point(ps[2].X, size.Height - (bitmap.Height - ps[1].Y)), new Size(size.Width - ps[2].X - (bitmap.Width - ps[3].X), bitmap.Height - ps[1].Y)); g.DrawImage(bitmap, destRect, ps[2].X, ps[1].Y, ps[3].X - ps[2].X, bitmap.Height - ps[1].Y, GraphicsUnit.Pixel); //左中 destRect = new Rectangle(new Point(0, ps[0].Y), new Size(ps[2].X, size.Height - ps[0].Y - (bitmap.Height - ps[1].Y))); g.DrawImage(bitmap, destRect, 0, ps[0].Y, ps[2].X, ps[1].Y-ps[0].Y, GraphicsUnit.Pixel); //右中 destRect = new Rectangle(new Point(size.Width - (bitmap.Width - ps[3].X), ps[0].Y), new Size(bitmap.Width - ps[3].X, size.Height - ps[0].Y - (bitmap.Height - ps[1].Y))); g.DrawImage(bitmap, destRect, ps[3].X, ps[0].Y, bitmap.Width-ps[3].X, ps[1].Y - ps[0].Y, GraphicsUnit.Pixel); //中中 destRect = new Rectangle(new Point(ps[2].X, ps[0].Y), new Size(size.Width - ps[2].X - (bitmap.Width - ps[3].X), size.Height - ps[0].Y - (bitmap.Height - ps[1].Y))); g.DrawImage(bitmap, destRect, ps[2].X, ps[0].Y, ps[3].X - ps[2].X, ps[1].Y - ps[0].Y, GraphicsUnit.Pixel); g.Dispose(); return _returnBitmap; }
使用
string strPath = @"D:\work-hzh\code\cy_hcmzc_v10\Km.PosZC\Km.PosZC\Resources\internet+.png"; Bitmap bitmap = new Bitmap(strPath); Point[] ps = GetIndex(bitmap,Color.White); Bitmap br = CreateBitmap(bitmap, ps, new Size(400, 400)); br.Save("d:\\123.png");
测试原图(100*100)
放大后(400*400)
这个是随便找的图,一般在应用中,是纯色活渐变色的会比较好,中间有图案的话 效果就不是太好了
作者:冰封一夏
出处:http://www.cnblogs.com/bfyx/
HZHControls官网:http://www.hzhcontrols.cn
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,
且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git