一:基本的三角函数知识
同样根据a, b的值可以计算出角度θ值,称之为反三角函数,角度θ=atan2(a, b)
图像处理中应用三角函数常常把中心点设置为A点,任意像素点B到A的距离可以根据三
角函数来计算得出,常见的计算模型如下:
对待求像素点加以一定三角函数变化,可以实现很多意想不到的图形特效,中心像素点可以
通过以下计算获得
int centerX = width/2;
int centerY = height/2;
扫描到的像素点p(x, y)可以基于 中心像素点,角度θ,两点之间距离Radius可以通过如
下计算获得:
int trueX = col -centerX;
int trueY = row -centerY;
theta = Math.atan2((trueY),(trueX));
radius = Math.sqrt(trueX*trueX + trueY*trueY);
二:特效原理
实现的特效很简单,上述的三角几何中计算结果中,有两个可以改变其值再重新计算坐标
P(x,y)。一个是角度,另外一个是半径距离,分别对角度与距离加以一定权重值计算,得到
如下两种特效:
1. 哈哈镜效果,主要是改变半径值,计算方法如下:
double newRadius = Math.sqrt(radius) * factor;
newX = centerX + (newRadius * Math.cos(theta));
newY = centerY + (newRadius * Math.sin(theta));
其中factor为输入参数
2. 中心螺旋效果,主要是改变角度θ的值,计算方法如下:
newX = centerX + (radius * Math.cos(theta+degree * radius));
newY = centerY + (radius * Math.sin(theta+degree * radius));
其中degree为输入参数.
三:程序效果
哈哈镜效果:
螺旋效果
1. Magic Mirror
package com.process.blur.study; import java.awt.image.BufferedImage; public class MagicMirrorFilter extends AbstractBufferedImageOp { private double factor = 15.0d; // default value public MagicMirrorFilter() { } public MagicMirrorFilter(double factor) { this.factor = factor; } public double getFactor() { return factor; } public void setFactor(double factor) { this.factor = factor; } @Override public BufferedImage filter(BufferedImage src, BufferedImage dest) { int width = src.getWidth(); int height = src.getHeight(); if ( dest == null ) dest = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; getRGB( src, 0, 0, width, height, inPixels ); int index = 0, outIndex = 0; int centerX = width/2; int centerY = height/2; double theta, radius; double newX, newY; int offsetX = 0, offsetY = 0; for(int row=0; row<height; row++) { int ta = 0, tr = 0, tg = 0, tb = 0; for(int col=0; col<width; col++) { int trueX = col - centerX; int trueY = row - centerY; theta = Math.atan2((trueY),(trueX)); radius = Math.sqrt(trueX*trueX + trueY*trueY); double newRadius = Math.sqrt(radius) * factor; newX = centerX + (newRadius * Math.cos(theta)); newY = centerY + (newRadius * Math.sin(theta)); if (newX > 0 && newX < width) { offsetX = (int)newX; } else { newX = 0; } if (newY > 0 && newY < height) { offsetY = (int)newY; } else { newY = 0; } index = offsetY * width + offsetX; ta = (inPixels[index] >> 24) & 0xff; tr = (inPixels[index] >> 16) & 0xff; tg = (inPixels[index] >> 8) & 0xff; tb = inPixels[index] & 0xff; // use newX, newY and fill the pixel data now... outIndex = row * width + col; outPixels[outIndex] = (ta << 24) | (tr << 16) | (tg << 8) | tb; } } setRGB( dest, 0, 0, width, height, outPixels ); return dest; } }2. Swirl
package com.process.blur.study; import java.awt.image.BufferedImage; public class SwirlFilter extends AbstractBufferedImageOp{ // recommended scope is [0.1 ~ 0.001] private double degree = 0.02d; // default value, public SwirlFilter() { } public double getDegree() { return degree; } public void setDegree(double degree) { this.degree = degree; } @Override public BufferedImage filter(BufferedImage src, BufferedImage dest) { int width = src.getWidth(); int height = src.getHeight(); if ( dest == null ) dest = createCompatibleDestImage( src, null ); int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; getRGB( src, 0, 0, width, height, inPixels ); int index = 0, outIndex = 0; int centerX = width/2; int centerY = height/2; double theta, radius; double newX, newY; int offsetX = 0, offsetY = 0; for(int row=0; row<height; row++) { int ta = 0, tr = 0, tg = 0, tb = 0; for(int col=0; col<width; col++) { int trueX = col - centerX; int trueY = row - centerY; theta = Math.atan2((trueY),(trueX)); radius = Math.sqrt(trueX*trueX + trueY*trueY); // the top trick is to add (degree * radius), generate the swirl effect... newX = centerX + (radius * Math.cos(theta + degree * radius)); newY = centerY + (radius * Math.sin(theta + degree * radius)); if (newX > 0 && newX < width) { offsetX = (int)newX; } else { offsetX = col; } if (newY > 0 && newY < height) { offsetY = (int)newY; } else { offsetY = row; } index = offsetY * width + offsetX; ta = (inPixels[index] >> 24) & 0xff; tr = (inPixels[index] >> 16) & 0xff; tg = (inPixels[index] >> 8) & 0xff; tb = inPixels[index] & 0xff; // use newX, newY and fill the pixel data now... outIndex = row * width + col; outPixels[outIndex] = (ta << 24) | (tr << 16) | (tg << 8) | tb; } } setRGB( dest, 0, 0, width, height, outPixels ); return dest; } }转载文章请务必注明出处