扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
public interface IFilter { Bitmap Apply( Bitmap img ); } |
public Bitmap Apply( Bitmap srcImg ) { // get source image size int width = srcImg.Width; int height = srcImg.Height; PixelFormat fmt = ( srcImg.PixelFormat == PixelFormat.Format8bppIndexed ) ? PixelFormat.Format8bppIndexed : PixelFormat.Format24bppRgb; // lock source bitmap data BitmapData srcData = srcImg.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadOnly, fmt ); // create new image Bitmap dstImg = ( fmt == PixelFormat.Format8bppIndexed ) ? AForge.Imaging.Image.CreateGrayscaleImage( width, height ) : new Bitmap( width, height, fmt ); // lock destination bitmap data BitmapData dstData = dstImg.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadWrite, fmt ); // copy image Win32.memcpy( dstData.Scan0, srcData.Scan0, srcData.Stride * height ); // process the filter ProcessFilter( dstData, fmt ); // unlock both images dstImg.UnlockBits( dstData ); srcImg.UnlockBits( srcData ); return dstImg; } |
// Process the filter private unsafe void ProcessFilter( BitmapData data, PixelFormat fmt ) { int width = data.Width; int height = data.Height; int lineSize = width * ( ( fmt == PixelFormat.Format8bppIndexed ) ? 1 : 3 ); int offset = data.Stride - lineSize; // do the job byte * ptr = (byte *) data.Scan0.ToPointer( ); // invert for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < lineSize; x++, ptr ++ ) { // ivert each pixel *ptr = (byte)( 255 - *ptr ); } ptr += offset; } } |
public interface ITextureGenerator { /**//// <SUMMARY> /// Generate texture /// </SUMMARY> float[,] Generate( int width, int height ); /**//// <SUMMARY> /// Reset - regenerate internal random numbers /// </SUMMARY> void Reset( ); } |
private Math.PerlinNoise noise = new Math.PerlinNoise( 1.0 / 32, 0.05, 0.5, 8 ); |
// Constructors public WoodTexture( ) : this( 12.0 ) { } public WoodTexture( double rings ) { this.rings = rings; Reset( ); } |
// Generate texture public float[,] Generate( int width, int height ) { float[,] texture = new float[height, width]; int w2 = width / 2; int h2 = height / 2; for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) { double xv = (double) ( x - w2 ) / width; double yv = (double) ( y - h2 ) / height; texture[y, x] = Math.Max( 0.0f, Math.Min( 1.0f, (float) Math.Abs( Math.Sin(( Math.Sqrt( xv * xv + yv * yv ) + noise.Function2D( x + r, y + r ) ) * Math.PI * 2 * rings)) )); } } return texture; } |
public void Reset( ) { r = rand.Next( 5000 ); } |
public PerlinNoise( double initFrequency, double initAmplitude, double persistance, int octaves ) { this.initFrequency = initFrequency; this.initAmplitude = initAmplitude; this.persistance = persistance; this.octaves = octaves; } |
/**//// <SUMMARY> /// 1-D Perlin noise function /// </SUMMARY> public double Function( double x ) { double frequency = initFrequency; double amplitude = initAmplitude; double sum = 0; // octaves for ( int i = 0; i < octaves; i++ ) { sum += SmoothedNoise( x * frequency ) * amplitude; frequency *= 2; amplitude *= persistance; } return sum; } /**//// <SUMMARY> /// 2-D Perlin noise function /// </SUMMARY> public double Function2D( double x, double y ) { double frequency = initFrequency; double amplitude = initAmplitude; double sum = 0; // octaves for ( int i = 0; i < octaves; i++ ) { sum += SmoothedNoise( x * frequency, y * frequency ) * amplitude; frequency *= 2; amplitude *= persistance; } return sum; } |
/**//// <SUMMARY> /// Ordinary noise function /// </SUMMARY> protected double Noise( int x ) { int n = ( x << 13 ) ^ x; return ( 1.0 - ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 ); } protected double Noise( int x, int y ) { int n = x + y * 57; n = ( n << 13 ) ^ n ; return ( 1.0 - ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 ); }又一次证明了前面那段话,个人感觉这个x+y*57有点投影的意思。获取相应的噪点值。但噪点不是直接就能拿来用的 /**//// <SUMMARY> /// Smoothed noise /// </SUMMARY> protected double SmoothedNoise( double x ) { int xInt = (int) x; double xFrac = x - xInt; return CosineInterpolate( Noise( xInt ) , Noise( xInt + 1 ), xFrac ); } protected double SmoothedNoise( double x, double y ) { int xInt = (int) x; int yInt = (int) y; double xFrac = x - xInt; double yFrac = y - yInt; // get four noise values double x0y0 = Noise( xInt , yInt ); double x1y0 = Noise( xInt + 1, yInt ); double x0y1 = Noise( xInt , yInt + 1 ); double x1y1 = Noise( xInt + 1, yInt + 1) ; // x interpolation double v1 = CosineInterpolate( x0y0, x1y0, xFrac ); double v2 = CosineInterpolate( x0y1, x1y1, xFrac ); // y interpolation return CosineInterpolate( v1, v2, yFrac ); }平滑的噪点,这个称呼似乎有点不协调,通过余弦插值,而不是离散余弦来运算。什么是余弦插值呢? /**//// <SUMMARY> // Cosine interpolation /// </SUMMARY> protected double CosineInterpolate( double x1, double x2, double a ) { double f = ( 1 - Math.Cos( a * Math.PI ) ) * 0.5; return x1 * ( 1 - f ) + x2 * f; } |
// Invert image private void invertColorFiltersItem_Click(object sender, System.EventArgs e) { ApplyFilter(new Invert()); } // Apply filter on the image private void ApplyFilter(IFilter filter) { try { // set wait cursor this.Cursor = Cursors.WaitCursor; // apply filter to the image Bitmap newImage = filter.Apply(image); if (host.CreateNewDocumentOnChange) { // open new image in new document host.NewDocument(newImage); } else { if (host.RememberOnChange) { // backup current image if (backup != null) backup.Dispose(); backup = image; } else { // release current image image.Dispose(); } image = newImage; // update UpdateNewImage(); } } catch (ArgumentException) { MessageBox.Show("Selected filter can not be applied to the image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { // restore cursor this.Cursor = Cursors.Default; } }调用顺畅的话,多少代码都不会觉得乱,对于初学者来说,要善用region。 这里还有个DocumentsHost的概念,用它来承载图像文件,并将图像和窗体连接起来,很方便 /**//// /// IDocumentsHost interface /// Provides connectione between documents and the main widnow /// public interface IDocumentsHost { bool CreateNewDocumentOnChange{get;} bool RememberOnChange{get;} bool NewDocument(Bitmap image); bool NewDocument(ComplexImage image); Bitmap GetImage(object sender, String text, Size size, PixelFormat format); } |
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者