java水泡_JAVA图像处理系列(八)——艺术效果:水泡
藝術(shù)效果水泡
通過對圖像進(jìn)行變形或疊加其他圖片,能夠?qū)崿F(xiàn)許多有趣的藝術(shù)效果,本文介紹類似水泡效果的實(shí)現(xiàn)方式,下面先看一下實(shí)現(xiàn)的效果。
第一張為原始圖像,第二張為疊加水泡效果的圖像。
cat.jpg
cat_belb.jpg
算法原理
圖像中的水泡效果,是由兩個算法疊加而成。第一個為計(jì)算水泡上反射光照的效果,第二個為圖像通過水泡折射后的形變計(jì)算。
(1)光照效果實(shí)現(xiàn)
通過設(shè)定光源的位置,及水泡上個點(diǎn)與光源的位置關(guān)系進(jìn)行計(jì)算,下面是實(shí)現(xiàn)代碼:
public static void upLightPoint(BufferedImage image, int x, int y, double scale, double hall) {
Pixel pixel = new Pixel();
if (scale > 1)
scale = 1;
else if (scale < 0) {
if (hall == 0) {
scale = 0;
} else {
scale = scale / hall;
}
}
pixel.setRGB(image.getRGB(x, y));
if (scale >= 0) {
pixel.red = pixel.red + (int) ((255 - pixel.red) * scale);
pixel.green = pixel.green + (int) ((255 - pixel.green) * scale);
pixel.blue = pixel.blue + (int) ((255 - pixel.blue) * scale);
} else {
pixel.red = pixel.red + (int) (pixel.red * scale);
pixel.green = pixel.green + (int) (pixel.green * scale);
pixel.blue = pixel.blue + (int) (pixel.blue * scale);
}
image.setRGB(x, y, pixel.getRGB());
}
public static void drawBall(BufferedImage bimg, int x_center, int y_center, int radius, int x_lamp, int y_lamp) {
double z, z_lamp;
double distance;
for (int y = y_center - radius; y < y_center + radius; y++) {
for (int x = x_center - radius; x < x_center + radius; x++) {
distance = (x - x_center) * (x - x_center) + (y - y_center) * (y - y_center);
if (distance > radius * radius)
continue;
z = Math.sqrt(radius * radius - distance);
z_lamp = Math.sqrt(radius * radius - (x_lamp - x_center) * (x_lamp - x_center)
- (y_lamp - y_center) * (y_lamp - y_center));
distance = Math.sqrt(radius * radius * 2 - 2 * (x - x_center) * (x_lamp - x_center)
- 2 * (y - y_center) * (y_lamp - y_center) - 2 * z * z_lamp);
try {
upLightPoint(bimg, x, y, (1 - distance / radius / .5), 0);
} catch (Exception e) {
}
}
}
}
(2)折射效果實(shí)現(xiàn)
通過背景圖像圖水泡中心的位置關(guān)系,計(jì)算簡單的折射效果,代碼如下:
public static void belbImage(BufferedImage image, BufferedImage bimg, int x_center, int y_center, int radius) {
double scale = radius * Math.PI / 2;
double x1 = 0;
double y1 = 0;
for (int y = y_center - radius; y < y_center + radius; y++) {
for (int x = x_center - radius; x < x_center + radius; x++) {
double distance = Math.sqrt((x - x_center) * (x - x_center) + (y - y_center) * (y - y_center));
if (distance > radius)
continue;
double hu = Math.asin(distance / radius);
double v = hu * scale * 4.14 / 180.0;
x1 = x_center + (x - x_center) * v;
y1 = y_center + (y - y_center) * v;
try {
if (x1 > image.getWidth())
x1 = image.getWidth() * 2 - x1;
else if (x1 < 0)
x1 = -x1;
if (y1 > image.getHeight())
y1 = image.getHeight() * 2 - y1;
else if (y1 < 0)
y1 = -y1;
bimg.setRGB(x, y, image.getRGB((int) x1, (int) y1));
} catch (Exception e) {
}
}
}
}
(3)兩種效果的疊加
將兩種效果進(jìn)行疊加,就產(chǎn)生了水泡的效果,疊加代碼如下:
public static BufferedImage drawBallImage(BufferedImage image, int x, int y, int radius) {
BufferedImage bimg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bimg.createGraphics();
g2.drawImage(image, 0, 0, null);
int r = radius, x_lamp, y_lamp;
x_lamp = x - (int) (r / 2.0);
y_lamp = y - (int) (r / 2.0);
belbImage(image, bimg, x, y, r);
drawBall(bimg, x, y, r, x_lamp, y_lamp);
g2 = bimg.createGraphics();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f));
g2.drawImage(image, 0, 0, null);
g2.dispose();
return bimg;
}
代碼中使用到的輔助類Pixel代碼如下:
import java.awt.image.*;
public class Pixel {
public int red;
public int green;
public int blue;
public int alpha=0xFF;
public double hue;
public double saturation;
public double luminosity;
private int rgb;
public Pixel() {
}
public void setRGB(int rgb) {
red = (rgb & 0x00FF0000) / 0x00010000;
green = (rgb & 0x0000FF00) / 0x00000100;
blue = rgb & 0x000000FF;
alpha = (rgb >> 24)&0x0ff;
this.rgb = rgb;
}
public int getRGB() {
rgb = alpha<<24 | 0x00010000 * red | 0x00000100 * green | blue;
return this.rgb;
}
public static void setRgb(BufferedImage image, int x, int y, int red, int green, int blue) {
int rgb = 0xFF000000 | red * 0x00010000 | green * 0x00000100 | blue;
image.setRGB(x, y, rgb);
}
public static int pixelIntensity(int rgb) {
int red = (rgb&0x00FF0000)/0x00010000;
int green = (rgb&0x0000FF00)/0x00000100;
int blue = rgb&0x000000FF;
return (int) (0.299 * red + 0.587 * green + 0.114 * blue + 0.5);
}
}
測試代碼
本文上的效果圖片使用了下面的測試代碼:
public static void main(String[] argv) throws IOException {
BufferedImage img = read(new File("cat.jpg"));
BufferedImage img2 =drawBallImage(img, 100, 300, 80);
ImageIO.write(img2, "jpeg", new File("cat_belb.jpg"));
}
總結(jié)
以上是生活随笔為你收集整理的java水泡_JAVA图像处理系列(八)——艺术效果:水泡的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 运行python 看不到异常
- 下一篇: thinkphp5 两个控制器传参数_t