java 图像特效之图像混合(溶图)

来源:互联网 发布:sql服务器名称 编辑:程序博客网 时间:2024/05/05 22:36

阅读本系列,请先看前言!谢谢

photoshop中的图层混合功能大家一定很熟悉。此功能可以根据指定模式,将2个图层进行混合,实现不同色彩风格的图像效果,也就是我们通常所说的溶图。 实现图像混合的原理其实很简单,就是将两张图像的重叠,分别取相同位置的两个像素点上的RGB值,通过特定的公式计算出新的RGB值,这样,不公的公式,将产生不同的色彩效果。

假设a[i]代表第一个像素点的RGB值中的一个值,相对应于b[i](代表另一个像素点的RGB值中的一个值),变暗效果的公式是a[i] < b[i] ? a[i] : b[i],这个公式很简单,就是比较2个值得大小。

除此之外,还有其他效果的算法可以供我们使用:

排除

a[i] + b[i] - 2 * a[i] * b[i] / 255

差值

Math.abs(a[i] - b[i])

实色混合

(b[i] < 128 ?    (b[i] == 0 ? 2 * b[i] : Math.max(0, (255 - ((255 - a[i]) << 8 ) / (2 * b[i])))) :    ((2 * (b[i] - 128)) == 255 ? (2 * (b[i] - 128)) : Math.min(255, ((a[i] << 8 ) / (255 - (2 * (b[i] - 128)) )))))    < 128 ?         0 : 255;

点光

Math.max(0, Math.max(2 * b[i] - 255, Math.min(b[i], 2 * a[i])))

线性光

Math.min(255, Math.max(0, (b[i] + 2 * a[i]) - 1))

亮光

b[i] < 128 ?    (b[i] == 0 ? 2 * b[i] : Math.max(0, (255 - ((255 - a[i]) << 8 ) / (2 * b[i])))) :    ((2 * (b[i] - 128)) == 255 ? (2 * (b[i] - 128)) : Math.min(255, ((a[i] << 8 ) / (255 - (2 * (b[i] - 128)) ))))

强光

(a[i] < 128) ? (2 * a[i] * b[i] / 255) : (255 - 2 * (255 - a[i]) * (255 - b[i]) / 255)

柔光

b[i] < 128 ?     (2 * (( a[i] >> 1) + 64)) * (b[i] / 255) : (255 - ( 2 * (255 - ( (a[i] >> 1) + 64 ) ) * ( 255 - b[i] ) / 255 ))

叠加

(b[i] < 128) ? (2 * a[i] * b[i] / 255) : (255 - 2 * (255 - a[i]) * (255 - b[i]) / 255)

线性减淡

Math.min(255, (a[i] + b[i]))

颜色减淡

(b[i] == 255) ? b[i] : Math.min(255, ((a[i] << 8 ) / (255 - b[i])))

滤色

255 - (((255 - a[i]) * (255 - b[i])) >> 8)

变亮

(b[i] > a[i]) ? b[i] : a[i]

线性加深

(a[i] + b[i] < 255) ? 0 : (a[i] + b[i] - 255)

颜色加深

b[i] == 0 ? b[i] : Math.max(0, Math.max(0, (255 - ((255 - a[i]) << 8 ) / b[i])))

正片叠底

a[i] * b[i] / 255
参考:图像混合(溶图)算法的javascript实现   


对于图片


给出上述一些效果的实现:

/* * a[i] * b[i] / 255 * 正片叠底 */public Image filter() {if(this.img.gray)return this.img;  // Grayscale images can not be processedfor (int y = 0; y < this.img.h; y++) {            for (int x = 0; x < this.img.w; x++) {                            int fr = this.img.red[x + y * this.img.w]*jb.red[x + y * this.img.w]/255;                  int fg = this.img.green[x + y * this.img.w]*jb.green[x + y * this.img.w]/255;                  int fb = this.img.blue[x + y * this.img.w]*jb.blue[x + y * this.img.w]/255;                                    this.img.data[x + y * this.img.w] = (255 << 24) | (math.st(fr) << 16) | (math.st(fg) << 8) | math.st(fb);                          }        }return this.img;}


/* * (a[i] + b[i] < 255) ? 0 : (a[i] + b[i] - 255) * 线性加深 */public Image linearDeep() {if(this.img.gray)return this.img;  // Grayscale images can not be processedfor (int y = 0; y < this.img.h; y++) {            for (int x = 0; x < this.img.w; x++) {                            int fr = (this.img.red[x + y * this.img.w]+jb.red[x + y * this.img.w])<255?0:(this.img.red[x + y * this.img.w]+jb.red[x + y * this.img.w]-255);                  int fg = (this.img.green[x + y * this.img.w]+jb.green[x + y * this.img.w])<255?0:(this.img.green[x + y * this.img.w]+jb.green[x + y * this.img.w]-255);                  int fb = (this.img.blue[x + y * this.img.w]+jb.blue[x + y * this.img.w])<255?0:(this.img.blue[x + y * this.img.w]+jb.blue[x + y * this.img.w]-255);                                    this.img.data[x + y * this.img.w] = (255 << 24) | (math.st(fr) << 16) | (math.st(fg) << 8) | math.st(fb);                          }        }return this.img;}


/* * (b[i] > a[i]) ? b[i] : a[i] * 变亮 */public Image max() {if(this.img.gray)return this.img;  // Grayscale images can not be processedfor (int y = 0; y < this.img.h; y++) {            for (int x = 0; x < this.img.w; x++) {                            int fr = this.img.red[x + y * this.img.w] > jb.red[x + y * this.img.w]?this.img.red[x + y * this.img.w]:jb.red[x + y * this.img.w];                int fg = this.img.green[x + y * this.img.w] > jb.green[x + y * this.img.w]?this.img.green[x + y * this.img.w]:jb.green[x + y * this.img.w];                int fb = this.img.blue[x + y * this.img.w] > jb.blue[x + y * this.img.w]?this.img.blue[x + y * this.img.w]:jb.blue[x + y * this.img.w];                                  this.img.data[x + y * this.img.w] = (255 << 24) | (math.st(fr) << 16) | (math.st(fg) << 8) | math.st(fb);                          }        }return this.img;}


/* * 255 - (((255 - a[i]) * (255 - b[i])) >> 8) * 滤色 */public Image ColorFilter() {if(this.img.gray)return this.img;  // Grayscale images can not be processedfor (int y = 0; y < this.img.h; y++) {            for (int x = 0; x < this.img.w; x++) {                            int fr = 255-((255-this.img.red[x + y * this.img.w])*(255-jb.red[x + y * this.img.w])>>8);                int fg = 255-((255-this.img.green[x + y * this.img.w])*(255-jb.green[x + y * this.img.w])>>8);                int fb = 255-((255-this.img.blue[x + y * this.img.w])*(255-jb.blue[x + y * this.img.w])>>8);                                  this.img.data[x + y * this.img.w] = (255 << 24) | (math.st(fr) << 16) | (math.st(fg) << 8) | math.st(fb);                          }        }return this.img;}


/* * Math.min(255, (a[i] + b[i])) * 线性减淡 */public Image LinearSub() {if(this.img.gray)return this.img;  // Grayscale images can not be processedfor (int y = 0; y < this.img.h; y++) {            for (int x = 0; x < this.img.w; x++) {                            int fr = 255>(this.img.red[x + y * this.img.w]+jb.red[x + y * this.img.w])?(this.img.red[x + y * this.img.w]+jb.red[x + y * this.img.w]):255;                int fg = 255>(this.img.green[x + y * this.img.w]+jb.green[x + y * this.img.w])?(this.img.green[x + y * this.img.w]+jb.green[x + y * this.img.w]):255;                int fb = 255>(this.img.blue[x + y * this.img.w]+jb.blue[x + y * this.img.w])?(this.img.blue[x + y * this.img.w]+jb.blue[x + y * this.img.w]):255;                                  this.img.data[x + y * this.img.w] = (255 << 24) | (math.st(fr) << 16) | (math.st(fg) << 8) | math.st(fb);                          }        }return this.img;}


/* * a[i] + b[i] - 2 * a[i] * b[i] / 255 * 排除 */public Image Exclude() {if(this.img.gray)return this.img;  // Grayscale images can not be processedfor (int y = 0; y < this.img.h; y++) {            for (int x = 0; x < this.img.w; x++) {                            int fr = this.img.red[x + y * this.img.w]+jb.red[x + y * this.img.w]-2*this.img.red[x + y * this.img.w]*jb.red[x + y * this.img.w]/255;                int fg = this.img.green[x + y * this.img.w]+jb.green[x + y * this.img.w]-2*this.img.green[x + y * this.img.w]*jb.green[x + y * this.img.w]/255;                int fb = this.img.blue[x + y * this.img.w]+jb.blue[x + y * this.img.w]-2*this.img.blue[x + y * this.img.w]*jb.blue[x + y * this.img.w]/255;                                  this.img.data[x + y * this.img.w] = (255 << 24) | (math.st(fr) << 16) | (math.st(fg) << 8) | math.st(fb);                          }        }return this.img;}


/* * Math.abs(a[i] - b[i]) * 差值 */public Image sub() {if(this.img.gray)return this.img;  // Grayscale images can not be processedfor (int y = 0; y < this.img.h; y++) {            for (int x = 0; x < this.img.w; x++) {                            int fr = Math.abs(this.img.red[x + y * this.img.w]-jb.red[x + y * this.img.w]);                int fg = Math.abs(this.img.green[x + y * this.img.w]-jb.green[x + y * this.img.w]);                int fb = Math.abs(this.img.blue[x + y * this.img.w]-jb.blue[x + y * this.img.w]);                                  this.img.data[x + y * this.img.w] = (255 << 24) | (math.st(fr) << 16) | (math.st(fg) << 8) | math.st(fb);                          }        }return this.img;}


以上


0 0