圖像濾鏡藝術---PS圖層混合模式之明度模式


本文將介紹PS圖層混合模式中比較復雜 的“明度”模式的算法原理及代碼實現內容。
說到PS的圖層混合模式,計算公式都有,詳細代碼實現也能找到,可是,都沒有完整介紹全部圖層混合模式的代碼。比方“明度”模式。公式例如以下:
如果兩張圖的HSY顏色模式分別為: Hb,Sb,Yb---Hm,Sm,Ym
明度混合結果HSY = HbSbYm
這個公式非常easy,無非就是原圖的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下載鏈接: 點擊打開鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM