目录
代码
如何使用代码
样本结果。
代码该代码使用不安全代码来加速不透明渐变的创建,因此必须在启用不安全标志的情况下编译代码。
代码大部分是不言自明的。
using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; namespace BitmapTools { public static class BitmapExtensions { public struct Pixel { public byte B; public byte G; public byte R; public byte A; } ////// Creates a bitmap with the original (bm) image on top and under that /// a reflected image. //////original image///Percentage of height of the original image /// that the reflection must be.///Angle that the reflection must shear. /// Positive to the left.///If true then the reflection get a little blur.///public static Bitmap ReflectImage(Bitmap bm, float verticalCompress, int offsetAngle, bool colorBlur = true) { // calculating the size of the resulting bitmap and the reflected image. int reflectionHeight = (int)(bm.Height - (bm.Height * verticalCompress / 100)); int newwidth = bm.Width; int newheight = bm.Height + reflectionHeight; int offset; offset = (int)(Math.Sin(offsetAngle * Math.PI / 180) * reflectionHeight); newwidth = bm.Width + Math.Abs(offset); Bitmap resultBitmap = new Bitmap(newwidth, newheight, PixelFormat.Format32bppArgb); resultBitmap.SetResolution(bm.VerticalResolution, bm.HorizontalResolution); // create the bitmap with a positive of the original Bitmap reflectionSrc = new Bitmap(bm.Width, reflectionHeight, PixelFormat.Format32bppArgb); using (Graphics g = Graphics.FromImage(reflectionSrc)) { g.DrawImage(bm, new Rectangle(0, 0, bm.Width, reflectionHeight), 0, 0, bm.Width, bm.Height, GraphicsUnit.Pixel); } // now flip the image to get a mirror image. reflectionSrc.RotateFlip(RotateFlipType.RotateNoneFlipY); // now fade to transparent. Can be done with managed code but too slow. // add conditionally add some blur. BitmapData bmd = reflectionSrc.LockBits( new Rectangle(Point.Empty, reflectionSrc.Size), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); unsafe { unchecked { Pixel* ps = (Pixel*)bmd.Scan0.ToPointer(); for (int y = 0; y < reflectionSrc.Height; y++) { int alpha = (int)((float)(1 - (y / (float)reflectionHeight)) * (float)0xFF); for (int x = 0; x < reflectionSrc.Width; x++, ps++) { ps->A = (byte)alpha; if (colorBlur) { ps->R = (byte)((ps->R * 3 + ps->G * 2 + ps->B * 2) / 7); ps->G = (byte)((ps->R * 2 + ps->G * 3 + ps->B * 2) / 7); ps->B = (byte)((ps->R * 2 + ps->G * 2 + ps->B * 3) / 7); } } } } } reflectionSrc.UnlockBits(bmd); // now create the canvas to draw the original and the flipped image with // the shear factor using (Graphics gr = Graphics.FromImage(resultBitmap)) { // draw original on top of the result image gr.DrawImage(bm, offset <= 0 ? 0 : offset, 0, bm.Width, bm.Height); float shearFactor = (float)(offsetAngle * Math.PI / 180); if (offsetAngle != 0) { Matrix matrix = new Matrix(); matrix.Shear(-shearFactor, 0); gr.Transform = matrix; } // remember shear translates coordinates like x' = x + (Sx * y) and y' = y + (Sy * x) // Sy = 0 in this case. gr.DrawImage(reflectionSrc, new Rectangle((offset <= 0 ? 0 : offset) + (int)(shearFactor * (float)bm.Height), bm.Height, newwidth, reflectionHeight), 0, 0, newwidth, reflectionHeight, GraphicsUnit.Pixel); gr.ResetTransform(); } reflectionSrc.Dispose(); return resultBitmap; } } }
这是一个小示例:
private void Form1_Paint(object sender, PaintEventArgs e) { Bitmap loadedImage = new Bitmap(@"Some Image.jpg"); using (Bitmap bm = BitmapExtensions.ReflectImage(loadedImage, 50, 12, true)) { e.Graphics.DrawImage(bm, 5, 5); } }
可以将生成的图像保存为JPG的透明度,但官方JPG不支持透明度,因此最好保存为PNG。
Bitmap loadedImage = new Bitmap(@"Some Image.jpg"); using (Bitmap bm = BitmapExtensions.ReflectImage(loadedImage, 50, 12, true)) { bm.Save(@"Some Image.png", ImageFormat.Png); }
https://www.codeproject.com/Tips/5329500/Reflected-Image-in-Csharp-with-GDI-and-Unchecked-C