艺术效果水泡

通过对图像进行变形或叠加其他图片,能够实现许多有趣的艺术效果,本文介绍类似水泡效果的实现方式,下面先看一下实现的效果。

第一张为原始图像,第二张为叠加水泡效果的图像。

cat.jpg

cat_belb.jpg

算法原理

图像中的水泡效果,是由两个算法叠加而成。第一个为计算水泡上反射光照的效果,第二个为图像通过水泡折射后的形变计算。

(1)光照效果实现

通过设定光源的位置,及水泡上个点与光源的位置关系进行计算,下面是实现代码:

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)折射效果实现

通过背景图像图水泡中心的位置关系,计算简单的折射效果,代码如下:

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)两种效果的叠加

将两种效果进行叠加,就产生了水泡的效果,叠加代码如下:

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"));

}

java水泡_JAVA图像处理系列(八)——艺术效果:水泡相关推荐

  1. JAVA面试常考系列八

    转载自 JAVA面试常考系列八 题目一 JDBC是什么? JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系 ...

  2. java制作水效果_JAVA图像处理系列(十)——艺术效果:水纹

    艺术效果:水纹 与火焰效果一样,借鉴粒子系统的思想,我们也可以在图像中实现类似水纹的艺术效果. 粒子系统基本上都要通过循环迭代实现,下面先看看本文方法实现的水纹效果. 第一张为原始图像,第二张为循环迭 ...

  3. LIST函数JAVA特点_Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和性能分析)...

    java 集合系列目录: 第1部分 List概括 先回顾一下List的框架图 (01) List 是一个接口,它继承于Collection的接口.它代表着有序的队列. (02) AbstractLis ...

  4. 访问者模式的java语言_Java 设计模式系列(二三)访问者模式(Vistor)

    Java 设计模式系列(二三)访问者模式(Vistor) 访问者模式是对象的行为模式.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以 ...

  5. java 影像处理_java图像处理的方法

    java图像处理的方法 项目需要调整图片服务器的解决方案,这次调整使用fastdfs存储小文件,也就是图片,因为现在还没有fastdfs的.net版的客服端,所以理所当然把处理图片放到了java这块, ...

  6. 希尔排序的java算法_Java算法系列篇 【希尔排序】

    什么? 搞Java不会算法? 由于个人兴趣原因以及工作所需,最近了解Java算法的相关案例 及时分享 感兴趣的欢迎交流 希尔排序 描述: 基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直 ...

  7. matlab图像的腐蚀和膨胀_OpenCV图像处理系列八 --- 腐蚀与膨胀

    今天,我们一起来学习图像形态学操作中两种最基本的形态学操作,即腐蚀与膨胀. 一.理论 数学形态学(Mathematical morphology) 是一门建立在格论和拓扑学基础之上的图像分析学科,是数 ...

  8. 静态导入 java面试_Java面试系列【静态导入】-静态导入,基础篇

    import是学习Java的人最熟悉不过的语句了,我们通过import语句导入类.但实际上我们对于import还有其他用法. import static 看一段代码: import java.util ...

  9. Java刀_Java尖刀系列3:堆

    堆是一种特殊的二叉树,分两种:大堆和小堆. 现在我们以Lucene中的代码为例来讲解堆的Java实现. 代码来自:PriorityQueue.java package org.apache.lucen ...

最新文章

  1. Go 学习笔记(66)— Go 并发同步原语(sync.Mutex、sync.RWMutex、sync.Once)
  2. JS~对img标签进行优化,使用onerror进行默认图像显示
  3. 「12306奇葩验证码」反例背后的产品观
  4. sql数据库基础知识整理,常用函数及常用语法
  5. Java手机忘了密码怎么办_手机开机密码忘记了怎么办
  6. 二叉搜索树与双向链表的转换
  7. 如何生成javadoc文档(JDK帮助文档)
  8. Adobe Originals的可变字体
  9. JMeter代理录制手机app
  10. 三阶魔方还原教程最详细
  11. Windows Sqlserver Automatic Log Audit Via C/C++
  12. Windows10专业版系统“本地组策略编辑器”丢失解决方案
  13. python爬取拉钩网招聘信息
  14. jeecg-boot 官方文档v2.0快速开始之hello world 前端教程
  15. XSS-challenge
  16. 10047.GNU Make 使用手册中译版(转)
  17. 这个社交聊天 App 开源了!
  18. SafetyNet简要梳理
  19. 小米手机计算机无法归零,小米体脂秤不归零怎么调
  20. 【ChatGPT 中文版插件】无需注册体验 ChatGPT 的攻略

热门文章

  1. kotlin int最大值_Kotlin程序查找三个数字中的最大值
  2. 多线程循环输出abcc++_C ++循环| 查找输出程序| 套装5
  3. 如何安装_如何安装吸顶灯?吸顶灯安装注意事项
  4. job每分钟执行 oracle_Oracle Job 每个时间点执行示例
  5. stm32 ucosii消息队列 串口_STM32F1的UART4串口配置
  6. MySQL 精选 60 道面试题(含答案)
  7. 面试官:int和Integer有什么区别?为什么要有包装类?
  8. 缓存通用管理类 + 缓存 HttpContext.Current.Cache 和 HttpRuntime.Cache 的区别
  9. java 简单的加法 递归 从A加到B
  10. jdbc mysql user_tab_comments_MySQL学习(五)——使用JDBC完成用户表CRUD的操作