private void Alpha3DImage(Image image, T3Direction direction) { if (image == null) { return; } var temp = image.Clone() as Bitmap; if (alpha.Size != temp.Size) { temp = BitmapHelper.CutBitmap(temp, alpha.Bounds); } var iCenter = false; switch (MDirection) { case TMDirection.T3DLeftToRight: case TMDirection.T3DRightToLeft: case TMDirection.T3DUpToDown: case TMDirection.T3DDownToUp: iCenter = true; break; } temp = BitmapHelper.TrapezoidTransformation(temp, 0.8 + color * 0.2 / 255, color * 1.0 / 255, direction, iCenter); alpha.BackgroundImage = temp; }
private void T3D(T3Direction d1, T3Direction d2) { if (d1 != T3Direction.None && i3d && color > intervel) { color -= intervel; switch (MDirection) { case TMDirection.T3DLeftToRight: case TMDirection.T3DRightToLeft: case TMDirection.T3DUpToDown: case TMDirection.T3DDownToUp: if (color > intervel) { color -= intervel; } break; } Alpha3DImage(TranImage, d1); } else if (d2 != T3Direction.None) { if (!i3d) { if (color < 255 - intervel) { switch (MDirection) { case TMDirection.T3DLeftToRight: case TMDirection.T3DRightToLeft: case TMDirection.T3DUpToDown: case TMDirection.T3DDownToUp: if (color < 255 - intervel) { color += intervel; } break; } Alpha3DImage(TranLaterImage, d2); } else { color = 255; } } else { color = 0; Alpha3DImage(TranLaterImage, d2); } i3d = false; if (color == 255) { Reset(); } } else { Reset(); } }
/// <summary> /// 矩形图片变换成梯形图片,用于QQ的3D翻转特效 /// </summary> /// <param name="src">原图</param> /// <param name="compressH">纵向缩放的比例</param> /// <param name="compressW">横向缩放的比例</param> /// <param name="direction">缩放位置</param> /// <param name="isCenter">是否水平居中</param> /// <returns></returns> public static Bitmap TrapezoidTransformation(Bitmap src, double compressH, double compressW, T3Direction direction, bool isCenter = true) { var rect = new Rectangle(0, 0, src.Width, src.Height); using (var resultH = new Bitmap(rect.Width, rect.Height)) { var resultW = new Bitmap(rect.Width, rect.Height); #region 指针算法,高速 //LockBits将Bitmap锁定到内存中 var srcData = src.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); var resultHData = resultH.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); var resultWData = resultW.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); switch (direction) { case T3Direction.Left: case T3Direction.Right: #region 左右 unsafe { //指向地址(分量顺序是BGRA) var srcP = (byte *)srcData.Scan0; //原图地址 var resultHP = (byte *)resultHData.Scan0; //侧面压缩结果图像地址 var resultWP = (byte *)resultWData.Scan0; //纵向压缩 var dataW = srcData.Stride; //每行的数据量 var changeY = (1.0 - compressH) * rect.Height / 2 / rect.Width; //Y变化率 for (var y = 0; y < rect.Height; y++) { for (var x = 0; x < rect.Width; x++) { double h = 0; double nH = 0; switch (direction) { case T3Direction.Left: if (y >= changeY * (rect.Width - x)) { h = rect.Height - 2.0 * changeY * (rect.Width - x); //变化之后的每竖像素高度 nH = y - changeY * (rect.Width - x); //当前像素在变化之后的高度 } break; case T3Direction.Right: if (y >= changeY * x) { h = rect.Height - 2.0 * changeY * x; //变化之后的每竖像素高度 nH = y - changeY * x; //当前像素在变化之后的高度 } break; } var p = 1.0 * nH / h; //当前像素在变化之后的位置高度百分比 var nY = (int)(rect.Height * p); //变化之后像素在原图片中的Y轴位置 if (nY < rect.Height && nY > -1) { var sp = srcP + nY * dataW + x * 4; //原图的像素偏移的数据位置 resultHP[0] = sp[0]; resultHP[1] = sp[1]; resultHP[2] = sp[2]; resultHP[3] = sp[3]; } resultHP += 4; } // x } // y resultHP = (byte *)resultHData.Scan0; //重置地址 //纵向压缩 var offsetX = 0; //居中偏移 if (isCenter) { offsetX = (int)((rect.Width - compressW * rect.Width) / 2); } else if (direction == T3Direction.Right) { offsetX = (int)(rect.Width - compressW * rect.Width); } for (var y = 0; y < rect.Height; y++) { for (var x = 0; x < rect.Width; x++) { var nX = (int)(1.0 * x / compressW); //纵向压缩后像素在原图片中的X轴位置 if (nX > -1 && nX < rect.Width) { var hp = resultHP + nX * 4 + dataW * y; var wp = resultWP + offsetX * 4; wp[0] = hp[0]; wp[1] = hp[1]; wp[2] = hp[2]; wp[3] = hp[3]; } resultWP += 4; } } src.UnlockBits(srcData); //从内存中解除锁定 resultH.UnlockBits(resultHData); resultW.UnlockBits(resultWData); } #endregion break; case T3Direction.Up: case T3Direction.Down: #region unsafe { //指向地址(分量顺序是BGRA) var srcP = (byte *)srcData.Scan0; //原图地址 var resultHP = (byte *)resultHData.Scan0; //侧面压缩结果图像地址 var resultWP = (byte *)resultWData.Scan0; //纵向压缩 var dataW = srcData.Stride; //每行的数据量 var changeX = (1.0 - compressH) * rect.Width / 2 / rect.Height; //X变化率 for (var y = 0; y < rect.Height; y++) { for (var x = 0; x < rect.Width; x++) { double w = 0; double nW = 0; switch (direction) { case T3Direction.Left: case T3Direction.Up: if (x >= changeX * (rect.Height - y)) { w = rect.Width - 2.0 * changeX * (rect.Height - y); //变化之后的每横像素高度 nW = x - changeX * (rect.Height - y); //当前像素在变化之后的宽度 } break; case T3Direction.Right: case T3Direction.Down: if (x >= changeX * y) { w = rect.Width - 2.0 * changeX * y; //变化之后的每横像素高度 nW = x - changeX * y; //当前像素在变化之后的宽度 } break; } var p = 1.0 * nW / w; //当前像素在变化之后的位置宽度百分比 var nX = (int)(rect.Width * p); //变化之后像素在原图片中的X轴位置 if (nX < rect.Width && nX > -1) { var sp = srcP + nX * 4 + y * dataW; //原图的像素偏移的数据位置 resultHP[0] = sp[0]; resultHP[1] = sp[1]; resultHP[2] = sp[2]; resultHP[3] = sp[3]; } resultHP += 4; } // x } // y resultHP = (byte *)resultHData.Scan0; //重置地址 //横向压缩 var offsetY = 0; //居中偏移 if (isCenter) { offsetY = (int)((rect.Height - compressW * rect.Height) / 2); } else if (direction == T3Direction.Down) { offsetY = (int)(rect.Height - compressW * rect.Height); } for (var y = 0; y < rect.Height; y++) { for (var x = 0; x < rect.Width; x++) { var nY = (int)(1.0 * y / compressW); //横向压缩后像素在原图片中的Y轴位置 if (nY > -1 && nY < rect.Height) { var hp = resultHP + nY * dataW + x * 4; var wp = resultWP + offsetY * dataW; wp[0] = hp[0]; wp[1] = hp[1]; wp[2] = hp[2]; wp[3] = hp[3]; } resultWP += 4; } } src.UnlockBits(srcData); //从内存中解除锁定 resultH.UnlockBits(resultHData); resultW.UnlockBits(resultWData); } #endregion break; } #endregion return(resultW); } }