图像滤镜艺术---PS图层混合模式之明度模式

简介: 原文:图像滤镜艺术---PS图层混合模式之明度模式 本文将介绍PS图层混合模式中比较复杂 的“明度”模式的算法原理及代码实现内容。
原文: 图像滤镜艺术---PS图层混合模式之明度模式

本文将介绍PS图层混合模式中比较复杂 的“明度”模式的算法原理及代码实现内容。
说到PS的图层混合模式,计算公式都有,具体代码实现也能找到,但是,都没有完整介绍所有图层混合模式的代码,比如“明度”模式,公式如下:
假设两张图的HSY颜色模式分别为: Hb,Sb,Yb---Hm,Sm,Ym
明度混合结果HSY = HbSbYm
这个公式很简单,无非就是原图的H,S分量+混合图的Y分量而已,但是具体代码如何实现,却很少有人分享,今天,我将给大家分享本人的代码。
HSY模式是一种彩色传输模型,传输基本的色差和亮度信号。如果直接使用HSY颜色空间,这个颜色空间好像很少见,具体HSY计算公式如下:

Y = 0.299R + 0.587G + 0.114B;
Cr = R - Y;
Cb = B - Y;
H = arctan(Cr/Cb);
S = sqrt(Cr * Cr + Cb * Cb);

大家可以看到,这个公式中运算复杂,但是是基于Cr, Cb分量计算的,而且,明度图层混合模式结果中实际上只改变了Y分量,因此,我们这里可以使用YCbCr颜色空间来代替HSY颜色空间实现这个功能。
YCbCr与RGB转换公式如下:

Y   = 0.257*R+0.564*G+0.098*B+16
Cb = -0.148*R-0.291*G+0.439*B+128
Cr  = 0.439*R-0.368*G-0.071*B+128

R = 1.164*(Y-16)+1.596*(Cr-128)
G = 1.164*(Y-16)-0.392*(Cb-128)-0.813*(Cr-128)
B = 1.164*(Y-16)+2.017*(Cb-128)

因此,按照上面的公式我们编码实现如下:
#include"TRGB2YCbCr.h"
#include <stdlib.h>
#include <stdio.h>
#include "math.h"
#include <string.h>

const float YCbCrYRF = 0.299F;              // RGB转YCbCr的系数(浮点类型)
const float YCbCrYGF = 0.587F;
const float YCbCrYBF = 0.114F;
const float YCbCrCbRF = -0.168736F;
const float YCbCrCbGF = -0.331264F;
const float YCbCrCbBF = 0.500000F;
const float YCbCrCrRF = 0.500000F;
const float YCbCrCrGF = -0.418688F;
const float YCbCrCrBF = -0.081312F;

const float RGBRYF = 1.00000F;            // YCbCr转RGB的系数(浮点类型)
const float RGBRCbF = 0.0000F;
const float RGBRCrF = 1.40200F;
const float RGBGYF = 1.00000F;
const float RGBGCbF = -0.34414F;
const float RGBGCrF = -0.71414F;
const float RGBBYF = 1.00000F;
const float RGBBCbF = 1.77200F;
const float RGBBCrF = 0.00000F;

const int Shift = 20;
const int HalfShiftValue = 1 << (Shift - 1);

const int YCbCrYRI = (int)(YCbCrYRF * (1 << Shift) + 0.5);         // RGB转YCbCr的系数(整数类型)
const int YCbCrYGI = (int)(YCbCrYGF * (1 << Shift) + 0.5);
const int YCbCrYBI = (int)(YCbCrYBF * (1 << Shift) + 0.5);
const int YCbCrCbRI = (int)(YCbCrCbRF * (1 << Shift) + 0.5);
const int YCbCrCbGI = (int)(YCbCrCbGF * (1 << Shift) + 0.5);
const int YCbCrCbBI = (int)(YCbCrCbBF * (1 << Shift) + 0.5);
const int YCbCrCrRI = (int)(YCbCrCrRF * (1 << Shift) + 0.5);
const int YCbCrCrGI = (int)(YCbCrCrGF * (1 << Shift) + 0.5);
const int YCbCrCrBI = (int)(YCbCrCrBF * (1 << Shift) + 0.5);

const int RGBRYI = (int)(RGBRYF * (1 << Shift) + 0.5);              // YCbCr转RGB的系数(整数类型)
const int RGBRCbI = (int)(RGBRCbF * (1 << Shift) + 0.5);
const int RGBRCrI = (int)(RGBRCrF * (1 << Shift) + 0.5);
const int RGBGYI = (int)(RGBGYF * (1 << Shift) + 0.5);
const int RGBGCbI = (int)(RGBGCbF * (1 << Shift) + 0.5);
const int RGBGCrI = (int)(RGBGCrF * (1 << Shift) + 0.5);
const int RGBBYI = (int)(RGBBYF * (1 << Shift) + 0.5);
const int RGBBCbI = (int)(RGBBCbF * (1 << Shift) + 0.5);
const int RGBBCrI = (int)(RGBBCrF * (1 << Shift) + 0.5);

void RGBToYCbCr(int R, int G, int B, int*Y,int*Cb, int* Cr)
{
	*Y  = ((YCbCrYRI * R + YCbCrYGI * G + YCbCrYBI * B + HalfShiftValue) >> Shift);
    *Cb = (128 + ((YCbCrCbRI * R + YCbCrCbGI * G + YCbCrCbBI * B + HalfShiftValue) >> Shift));
    *Cr = (128 + ((YCbCrCrRI * R + YCbCrCrGI * G + YCbCrCrBI * B + HalfShiftValue) >> Shift));
}

void YCbCrToRGB(int Y, int Cb, int Cr, int*R,int*G, int* B)
{
    Cb = Cb - 128; Cr = Cr - 128;
    *R = Y + ((RGBRCrI * Cr + HalfShiftValue) >> Shift);
    *G = Y + ((RGBGCbI * Cb + RGBGCrI * Cr + HalfShiftValue) >> Shift);
    *B = Y + ((RGBBCbI * Cb + HalfShiftValue) >> Shift);
    if (*R > 255) *R = 255; else if (*R < 0) *R = 0;
    if (*G > 255) *G = 255; else if (*G < 0) *G = 0;   
    if (*B > 255) *B = 255; else if (*B < 0) *B = 0;
}
int ColorBlendModeBrightness(unsigned char* baseData, unsigned char* mixData, int width, int height, int stride)
{
	int i, j, pos;
	int bY, bCb, bCr, mY, mCb, mCr, br, bg, bb, mr, mg, mb;
	unsigned char* pBase = baseData;
	unsigned char* pMix = mixData;
	int offset = stride - width * 4;
	for(j = 0; j < height; j++)
	{
		for(i = 0; i < width; i++)
		{
			bb = pBase[0];
			bg = pBase[1];
			br = pBase[2];
			mb = pMix[0];
			mg = pMix[1];
			mr = pMix[2];
			RGBToYCbCr(mr,mg,mb,&mY,&mCb,&mCr);
			RGBToYCbCr(br,bg,bb,&bY,&bCb,&bCr);
			YCbCrToRGB((mY+bY)/2, bCb, bCr, &br,&bg,&bb);//(mY+bY)/2表示透明度为50%
			pBase[0] = bb;
			pBase[1] = bg;
			pBase[2] = br;
			pBase += 4;
			pMix  += 4;
		}
		pBase += offset;
		pMix  += offset;
	}
	return 0;

}
这个就是所有编码了,而且这个颜色空间转换的代码已经经过优化,大家可以直接使用,下面我给出效果图(该效果是按照明度图层混合模式50%透明度设置得到的):
大家可以看到,效果图和PS的效果图几乎一致,最后,给出一个DEMO下载链接: 点击打开链接
目录
相关文章
|
编解码
Portraiture2024免费ps人像滤镜插件
今天coco玛奇朵给大家带来了一款ps磨皮插件,超级简单好用。Portraiture 滤镜是一款 Photoshop,Lightroom 和 Aperture 插件,DobeLighttroom 的 Portraiture 消除了选择性掩蔽和逐像素处理的繁琐的手工劳动,以帮助您在肖像修整方面取得卓越的效果。它是一个强大的,但用户友好的插件照明.这是一个有效的工具,以平滑皮肤,同时保持纹理的现实效果-一个精细的线条,所有的肖像摄影师必须意识到。童鞋们可以按自己需求来找,都已经出了好几个版本,可以装在ps里,官方版可以一直更新,使用更方便。更详细的教程可以看下面这个,不仅介绍了portraitur
932 0
|
Windows
ps软件2023免费磨皮滤镜插件portraiture安装下载教程
Portraiture一款适用于Photoshop与Lightroom的智能磨皮滤镜插件,可智能识别人像的皮肤、头发、眉毛等区域,实现自动化的磨皮、美颜处理,再也不用研究那些晦涩难懂的磨皮教程了,一键磨皮走起! 接下来,一起来看看怎么安装激活这款插件吧。
4474 3
PS移动与变换、PS图层进阶
本文将简述 PS 中的移动工具的使用、对于对象的自由变换大小方向的操作方法、对于画布的更进阶的认识以及对于图层的正确认识。让我们开始吧!
230 0
|
人工智能 编解码 算法
Portraiture4最新版本ps磨皮滤镜插件
Portraiture3和Portraiture4这两个版本大家用的比较多,那是因为这两个版本是中文比较全的版本。portraiture是一款强大的64位PS磨皮滤镜,利用该PS滤镜插件可以对图片中的人物进行润色,磨皮等操作,处理皮肤材质、头发等。帮您消除了选择性遮蔽与逐像素处理的繁琐手工劳动,帮您实现卓越的人像修饰。不仅磨皮全面,并且还可以增强肤色的质感,是人物处理不可缺少的外挂滤镜,使用简单,小白也能立即刻手,分分钟去除脸上的痘痘、疤痕,可以平滑与去除缺陷,同时保留皮肤纹理与重要的人像细节,功能十分强大。全新4版本,升级AI算法,并独家支持多人及全身模式!
1031 0
|
前端开发
「趣学前端」filter滤镜,CSS的PS特技
CSS之filter赏析,来show一波CSS的PS特技。
153 1
|
编解码
PS2023神经元滤镜离线安装教程,解决PS神经滤镜灰色不可用!
PS2023神经元滤镜离线安装教程,解决PS神经滤镜灰色不可用!
PS2023神经元滤镜离线安装教程,解决PS神经滤镜灰色不可用!
Portraiture2022全新滤镜软件PS磨皮插件
Portraiture 5是一款PS磨皮滤镜,减少了人工选择图像区域的重复劳动。它能智能地对图像中的皮肤材质、头发、眉毛、睫毛等部位进行平滑和减少疵点处理,效果相当优秀;
2052 0
|
搜索推荐
Alien Skin Exposure永久免费版PS图片滤镜后期处理软件
Alien Skin Exposure一款非常专业的图片后期处理软件,内含500多种照片滤镜。是一款图片后期处理功能非常强大的软件。这款软件可以对图片的后期效果做很好的处理。
246 0
|
异构计算
Alien Skin Exposure最新版PS后期调色滤镜免费插件
Alien Skin Exposure这是一款一款PS后期调色滤镜,黑白,彩色,人像风,怀旧风,电影风,调色预设非常多,既可以独立应用, 也可以作为插件使用,很直观地能看到每一个效果,可以说是手残党的一个神器。
279 0
|
算法
图像滤镜艺术--PS平均(滤镜-模糊-平均)效果
原文:图像滤镜艺术--PS平均(滤镜-模糊-平均)效果 本文介绍PS中滤镜-模糊-平均模糊的效果实现: 这个效果很简单,原理如下: 1,统计全图像素的R,G,B值得和sumR,sumG,sumB; 2,计算平均R,G,B(R = sumR/(width*height)...); 3,用平均R,G,B代替全图所有像素即可。
1475 0