RGB、HSV色彩空间模式的互相转换
文章来源:
https://www.wendangku.net/doc/b314890351.html,/1168000.html
在开发有关bitmap方面的程序时,经常需要将位图的颜色在RGB和HSV色彩空间之间转换,前段时间本人研究过,现在整理一下,希望对大家能有所帮助,该颜色转换由C++实现
在开发有关bitmap方面的程序时,经常需要将位图的颜色在RGB和HSV 色彩空间之间转换,前段时间本人研究过,现在整理一下,希望对大家能有所帮助,该颜色转换由C++实现:
RGB颜色空间转换为HSV空间颜色值:
void Rgb2Hsv(float R, float G, float B, float& H, float& S, float&V) {
// r,g,b values are from 0 to 1
// h = [0,360], s = [0,1], v = [0,1]
// if s == 0, then h = -1 (undefined)
float min, max, delta,tmp;
tmp = min(R, G);
min = min( tmp, B );
tmp = max( R, G);
max = max(tmp, B );
V = max; // v
delta = max - min;
if( max != 0 )
S = delta / max; // s
else
{
// r = g = b = 0 // s = 0, v is undefined
S = 0;
H = UNDEFINEDCOLOR;
return;
}
if( R == max )
H = ( G - B ) / delta; // between yellow & magenta
else if( G == max )
H = 2 + ( B - R ) / delta; // between cyan & yellow
else
H = 4 + ( R - G ) / delta; // between magenta & cyan
H *= 60; // degrees
if( H < 0 )
H += 360;
}
HSV颜色空间转换为RGB空间颜色值:
void Hsv2Rgb(float H, float S, float V, float &R, float &G, float & {
int i;
float f, p, q, t;
if( S == 0 )
{
// achromatic (grey)
R = G = B = V;
return;
}
H /= 60; // sector 0 to 5
i = floor( H );
f = H - i; // factorial part of h
p = V * ( 1 - S );
q = V * ( 1 - S * f );
t = V * ( 1 - S * ( 1 - f ) );
switch( i )
{
case 0:
R = V;
G = t;
B = p;
break;
case 1:
R = q;
G = V;
B = p;
break;
case 2:
R = p;
G = V;
B = t;
break;
case 3:
R = p;
G = q;
B = V;
break;
case 4:
R = t;
G = p;
B = V;
break;
default: // case 5:
R = V;
G = p;
B = q;
break;
}
}
s=max(r,g,b)-min(r,g,b)/max(r,g,b)
b=max(r,g,b)
脚本文件转存档
------------
抄来一个用Adobe Camera Raw 3.3版本打开30D的Raw文件的办法,试下来果然可以用。
方法如下:
1, 新建一个后缀为 .js的文本文件,比如"30d_hack.js"把下面的代码复制到这个文件。
2,在Photoshop CS2的菜单里选择File-> Scripts->Browse... 找到你刚做好的文件,执行一下。
3,根据提示找到Camera Raw.8bi这个Camera Raw插件的文件后确定。(一般在c:\program files\common files\adobe\plug-ins\CS2\File Formats文件夹里,如果在c:\program files\common files\adobe\plug-ins\CS2目录里还有个副本,那把上面的步骤做两次,把两个Camera Raw.8bi都破解一下)
4,破解完成,重新启动photoshop就可以了
如果要取消破解,重新执行一下这个.js文件就可以了
这个破解只是在ACR的插件的兼容型号里加一个30D的标签,不会有什么副作用
的。
以下是代码:
// Find the Official ACR plugin in the expected location or ask the user to help
var originalACR = File(Folder.startup + "/Plug-Ins/File Formats/Camera Raw.8bi");
if ( !originalACR.exists ) {
if ( Folder.fs == "Windows" ) {
originalACR = File.openDialog("Find and Select the 'Camera Raw.8bi' File", "Photoshop Plug-ins:*.8bi");
} else if ( Folder.fs == "Macintosh" ) {
originalACR = File.openDialog("Find and Select the 'Camera Raw.8bi' File", pluginFilter);
}
}
// Check if hack already exists and prompt the user asking what to do var bRemove = false;
var bProceed = false;
var newACR = File(originalACR.path + "/Camera Raw Unofficial Canon
30D.8bi");
if ( newACR.exists ) {
bRemove = confirm("Unofficial Canon 30D support already exists.\rDo you want to remove?");
if (bRemove) {
newACR.remove();
alert("Unofficial Canon 30D support has been successfully removed.\rYou should restart Photoshop.");
}
} else {
bProceed = confirm("Do you want to add Unofficial Canon 30D support?"); }
if ( bProceed ) {
// Create a backup copy of the original ACR file to work with. originalACR.copy(newACR);
// Read backup copy of ACR into memory
newACR.encoding = "BINARY";
newACR.open("r");
var memoryACR = newACR.read();
newACR.close();
// Perform some sanity checks to make sure this is the ACR plug-in var validACR = true;
if (!memoryACR.match(/Adobe/)) validACR = false;
if (!memoryACR.match(/Camera Raw/)) validACR = false;
if (!memoryACR.match(/Thomas Knoll/)) validACR = false;
if (!memoryACR.match(/Canon EOS-1D Mark II/)) validACR = false;
if ( validACR ) {
// Do the hack
var loc = memoryACR.search(/Canon EOS-1D Mark II/);
newACR.open("e");
newACR.seek(loc, 0);
newACR.write("Canon EOS 30D\0");
newACR.close();
alert("Unofficial Canon 30D support has been added! :-)\rYou need to restart Photoshop.");
} else {
alert("Official ACR Plug-in not found or incorrect version found. Cannot create Unofficial Canon 30D support. :-(");
}
}
//===============================
// Utility function to filter
// plugin files in dialog on Mac
// platform
//===============================
function pluginFilter(f) {
lcName = https://www.wendangku.net/doc/b314890351.html,;
lcName.toLowerCase();
if ( lcName.indexOf(".8bi") == (https://www.wendangku.net/doc/b314890351.html,.length - 4) ) {
return true;
} else if ( f instanceof Folder ) {
return true;
} else {
return false;
}
}
RGB —> HSV
var_R = ( R / 255 ) //RGB values = 0 ÷ 255
var_G = ( G / 255 )
var_B = ( B / 255 )
var_Min = min( var_R, var_G, var_B ) //Min. value of RGB
var_Max = max( var_R, var_G, var_B ) //Max. value of RGB
del_Max = var_Max - var_Min //Delta RGB value
V = var_Max
if ( del_Max == 0 ) //This is a gray, no chroma... {
H = 0 //HSV results = 0 ÷ 1
S = 0
}
else //Chromatic data...
{
S = del_Max / var_Max
del_R = ( ( ( var_Max - var_R ) / 6 ) + ( del_Max / 2 ) ) / del_Max del_G = ( ( ( var_Max - var_G ) / 6 ) + ( del_Max / 2 ) ) / del_Max del_B = ( ( ( var_Max - var_B ) / 6 ) + ( del_Max / 2 ) ) / del_Max
if ( var_R == var_Max ) H = del_B - del_G
else if ( var_G == var_Max ) H = ( 1 / 3 ) + del_R - del_B
else if ( var_B == var_Max ) H = ( 2 / 3 ) + del_G - del_R
if ( H < 0 ) ; H += 1
if ( H > 1 ) ; H -= 1
}
HSV —> RGB
if ( S == 0 ) //HSV values = 0 ÷ 1
{
R = V * 255
G = V * 255
B = V * 255
}
else
{
var_h = H * 6
if ( var_h == 6 ) var_h = 0 //H must be < 1
var_i = int( var_h ) //Or ... var_i = floor( var_h )
var_1 = V * ( 1 - S )
var_2 = V * ( 1 - S * ( var_h - var_i ) )
var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) )
if ( var_i == 0 ) { var_r = V ; var_g = var_3 ; var_b = var_1 } else if ( var_i == 1 ) { var_r = var_2 ; var_g = V ; var_b = var_1 } else if ( var_i == 2 ) { var_r = var_1 ; var_g = V ; var_b = var_3 } else if ( var_i == 3 ) { var_r = var_1 ; var_g = var_2 ; var_b = V } else if ( var_i == 4 ) { var_r = var_3 ; var_g = var_1 ; var_b = V } else { var_r = V ; var_g = var_1 ; var_b = var_2 }
R = var_r * 255 //RGB results = 0 ÷ 255
G = var_g * 255
B = var_b * 255
}
RGB —> HSV
H的转换比较麻烦一点(略)
S=[最大值(R,G,B)-最小值(R,G,B)]/[最大值(R,G,B)
V=最大值(R,G,B)
以上,与BB在2楼的几乎一样。V,BB用的是:B。
HSV —> RGB
转换比较麻烦,需要按语句一步步走。
比如:如果S=0时,
R = V * 255
G = V * 255
B = V * 255
后面(略)。
Adobe色彩系统RGB和CMYK相互转换原理
为了说明 adobe 的 RGB 转换 CMYK 的过程,不得不先涉及到一些色彩转换程序方面的东西。
CMYK_ADOBE_COLORSPACE:
r = (k*c)/maxval;
g = (k*m)/maxval;
b = (k*y)/maxval;
以上是 adobe 的 CMYK 到 RGB转换公式,下面再来看看 RGB 如何转换为CMYK
下面的语句是经过改写的适用于 Flash 的 actionscript
// RGB to CMY 色彩转换
function rgbtocmy () {
mycyan = 255 - myred;
mymagenta = 255 - mygreen;
myyellow = 255 - myblue;
correctCMYK();
}
// CMY to RGB 色彩转换
function cmytorgb () {
myred = 255 - mycyan;
mygreen = 255 - mymagenta;
myblue = 255 - myyellow;
correctCMYK();
}
// CMYK 色彩修正
function correctCMYK () {
if (rep_v != "ERR" {
var temp = Math.min(Math.min(mycyan, mymagenta), myyellow);
if (temp != 0) {
temp2 = Math.round((rep_v / 100) * temp);
rep_k = Math.round((temp2 / 255) * 100);
rep_c = Math.round(((mycyan - temp2) / 255) * 100);
rep_m = Math.round(((mymagenta - temp2) / 255) * 100);
rep_y = Math.round(((myyellow - temp2) / 255) * 100);
} else {
rep_c = Math.round((mycyan / 255) * 100);
rep_m = Math.round((mymagenta / 255) * 100);
rep_y = Math.round((myyellow / 255) * 100);
rep_k = 0;
}
}
}
我们知道, RGB 和 CMYK 并不能一一对应,这里面存在的问题是黑色部分的替换值的取值问题。
但是, RGB 所可以全部对应的,是CMY 格式,其最取值范围是0-255。从色轮上我们可以很容易的了解到这其中的补色计算关系。因此,CMY 和 RGB 的对换可以说是“无损,可逆转”的。
当从RGB 得到相应的CMY 之后,我们若要得到 CMYK 值,就必须定义一个“黑色替换值”,也就是说提取各色通道中的若干成分来形成黑色通道。CMYK 的取值是 0-100。
这个“黑色替换值”的取值不同,得到的CMYK分量分布也就不同。也就是我们在photoshop里面可以选择 CMYK 的分色方案为“UCR”或者“GCR”的不同。
“黑色替换值”越大,CMYK图像在印刷时的偏色几率就越小,但相应的状况是
图片彩墨分量在暗黑部位显薄,不够饱和。这种分色方式适用于印刷材质较薄或较粗糙,印刷精度不高的场合。
注:
为什么直接去色和直接转换灰度比 Lab 的 L 通道得到的灰度层次显得差?
我们还是来用色彩转换公式说话来比较:
L =
0.3R+0.59G+0.11B
Gray = (R+G+
/3
我们很容易就看出区别,平均取值的灰度和根据色彩明度增益比例混合的值是完全不同的。