怎样把RGB颜色转为LAB颜色,急!!!(100分)

  • 主题发起人 主题发起人 1001
  • 开始时间 开始时间
1

1001

Unregistered / Unconfirmed
GUEST, unregistred user!
如上,先谢了
 
lable.color:=rgb(128,255,255);
 
LAB不知道是什么色,嘻嘻
我以前做ACI转RGB是抓图下来,再取出颜色值,再转换的:
function Aci2Rgb(color:integer):tcolor; //ACI色转换到RGB色
begin
case color of
1,10:result:=rgb(255,0,0);
11:result:=rgb(255,125,123);
12:result:=rgb(206,0,0);
13:result:=rgb(206,101,99);
14:result:=rgb(156,0,0);
15:result:=rgb(156,77,74);
16:result:=rgb(123,0,0);
17:result:=rgb(123,60,57);
18:result:=rgb(74,0,0);
....
end;
end;
 

#define BLACK 20.0
#define YELLOW 70.0

void RGB2Lab(float R, float G, float B,
float *L, float *a, float *b)
{
float X, Y, Z, fX, fY, fZ;

X = 0.412453*R + 0.357580*G + 0.180423*B;
Y = 0.212671*R + 0.715160*G + 0.072169*B;
Z = 0.019334*R + 0.119193*G + 0.950227*B;

X /= (255 * 0.950456);
Y /= 255;
Z /= (255 * 1.088754);

if (Y > 0.008856)
{
fY = pow(Y, 1.0/3.0);
*L = 116.0*fY - 16.0;
}
else
{
fY = 7.787*Y + 16.0/116.0;
*L = 903.3*Y;
}

if (X > 0.008856)
fX = pow(X, 1.0/3.0);
else
fX = 7.787*X + 16.0/116.0;

if (Z > 0.008856)
fZ = pow(Z, 1.0/3.0);
else
fZ = 7.787*Z + 16.0/116.0;

*a = 500.0*(fX - fY);
*b = 200.0*(fY - fZ);

if (*L < BLACK) {
*a *= exp((*L - BLACK) / (BLACK / 4));
*b *= exp((*L - BLACK) / (BLACK / 4));
*L = BLACK;
}
if (*b > YELLOW)
*b = YELLOW;

/*printf("RGB=(%d,%d,%d) ==> Lab(%d,%d,%d)/n",(int)R,(int)G,(int)B,
(int)*L,(int)*a,(int)*b); */
}


void Lab2RGB(float L, float a, float b,
float *R, float *G, float *B)
{
float X, Y, Z, fX, fY, fZ;
float RR, GG, BB;

fY = pow((L + 16.0) / 116.0, 3.0);
if (fY < 0.008856)
fY = L / 903.3;
Y = fY;

if (fY > 0.008856)
fY = pow(fY, 1.0/3.0);
else
fY = 7.787 * fY + 16.0/116.0;

fX = a / 500.0 + fY;
if (fX > 0.206893)
X = pow(fX, 3.0);
else
X = (fX - 16.0/116.0) / 7.787;

fZ = fY - b /200.0;
if (fZ > 0.206893)
Z = pow(fZ, 3.0);
else
Z = (fZ - 16.0/116.0) / 7.787;

X *= (0.950456 * 255);
Y *= 255;
Z *= (1.088754 * 255);

RR = 3.240479*X - 1.537150*Y - 0.498535*Z;
GG = -0.969256*X + 1.875992*Y + 0.041556*Z;
BB = 0.055648*X - 0.204043*Y + 1.057311*Z;

*R = (float)(RR < 0 ? 0 : RR > 255 ? 255 : RR);
*G = (float)(GG < 0 ? 0 : GG > 255 ? 255 : GG);
*B = (float)(BB < 0 ? 0 : BB > 255 ? 255 : BB);

/*printf("Lab=(%f,%f,%f) ==> RGB(%f,%f,%f)/n",L,a,b,*R,*G,*B);*/
}
 
用PHotoshop
我就知道这个,细细
 

L = pow((Y/WHITE_Y0), 1.0/3.0) - 16.0;
a = 500.0*(pow((X/WHITE_X0), 1.0/3.0) - pow((Y/WHITE_Y0), 1.0/3.0));
b = 200.0*(pow((Y/WHITE_Y0), 1.0/3.0) - pow((Z/WHITE_Z0), 1.0/3.0));
WHITE_X0, WHITE_Y0, WHITE_Z0, 为白光(R=255, G=255,B=255)时的
x,y,z表色系统的值,与所采用的光源有关。
 
看看这个:

Lab 模式
在 Photoshop 的 Lab 模式中(名称中去掉了星号),亮度分量 (L) 范围可从 0 到 1
00。a 分量(绿-红轴)和 b 分量(蓝-黄轴)范围可从 +120 到 -120。
您可以使用 Lab 模式处理 Photo CD 图像,独立编辑图像中的亮度和颜色值,在不同系
统之间移动图像并将其打印到 PostScript? Level 2 和 Level 3 打印机。要将 Lab 图
像打印到其它彩色 PostScript 设备,应首先将其转换为 CMYK。
Lab 颜色是 Photoshop 在不同颜色模式之间转换时使用的中间颜色模式。
L*a*b 模型
L*a*b 颜色模型是在 1931 年国际照明委员会 (CIE) 制定的颜色度量国际标准模型的基
础上建立的。1976 年,该模型经过重新修订并命名为 CIE L*a*b。
L*a*b 颜色与设备无关,无论使用何种设备(如显示器、打印机、计算机或扫描仪)创
建或输出图像,这种模型都能生成一致的颜色。
L*a*b 颜色由亮度或光亮度分量 (L) 和两个色度分量组成:a 分量(从绿色到红色)和
b 分量(从蓝色到黄色)。
HSB 模型
HSB 模型以人类对颜色的感觉为基础,描述了颜色的 3 种基本特性:
色相是从物体反射或透过物体传播的颜色。在 0 到 360 度的标准色轮上,按位置度量
色相。在通常的使用中,色相由颜色名称标识,如红色、橙色或绿色。
饱和度(有时称为彩度)是指颜色的强度或纯度。饱和度表示色相中灰色分量所占的比
例,它使用从 0%(灰色)至 100%(完全饱和)的百分比来度量。在标准色轮上,饱和
度从中心到边缘递增。

亮度是颜色的相对明暗程度,通常使用从 0%(黑色)至 100%(白色)的百分比来度量

RGB 模型
绝大多数可视光谱可用红色、绿色和蓝色 (RGB) 三色光的不同比例和强度的混合来表示
。在这三种颜色的重叠处产生青色、洋红、黄色和白色。
由于 RGB 颜色合成可以产生白色,因此也称它们为加色。将所有颜色加在一起可产生白
色-即所有光都被反射回眼睛。加色用于光照、视频和显示器。例如,显示器通过红色
、绿色和蓝色荧光粉发射光产生颜色。
CMYK 模型
CMYK 模型以打印在纸上的油墨的光线吸收特性为基础。当白光照射到半透明油墨上时,
色谱中的一部分被吸收,而另一部分被反射回眼睛。
理论上,纯青色 (C)、洋红 (M) 和黄色 (Y) 色素合成,吸收所有颜色并生成黑色。这
些颜色因此称为减色。由于所有打印油墨都包含一些杂质,因此这三种油墨实际生成土
灰色,必须与黑色 (K) 油墨合成才能生成真正的黑色。(为避免与蓝色混淆,黑色用
K 而非 B 表示。)将这些油墨混合重现颜色的过程称为四色印刷。

减色 (CMY) 和加色 (RGB) 是互补色。每对减色产生一种加色,反之亦然。
 
RGB-->XYZ

///------------------CIE Trans
// X = (2.7689*R+1.7517*G+1.1302*B);
// Y = (1.0000*R+4.5907*G+0.0601*B);
// Z = (0.0000*R+0.0565*G+5.5943*B);

/// ----------------PAL Trans
X = (0.607*R+0.174*G+0.201*B);
Y = (0.299*R+0.587*G+0.114*B);
Z = (0.000*R+0.066*G+1.117*B);
 
To: amakusa
photoshop是怎样将RGB转为Lab值的?用你的公式跟它的不同.
 
我看了 Photoshop 的效果,但是我在网上找到的所有资料,几乎都是这么算的.具体就不太清楚了.我也只是一个小功能用到了 RGB2LAB.以下是我转成的 delphi 的.和 PhotoShop 有很大出入.

const BLACK = 20.0;
const YELLOW = 70.0;

procedure RGB2Lab(R1, G1, B1: Integer; L, a, b: PInteger);
var
X, Y, Z, fX, fY, fZ: Double;
begin
X := 0.412453 * R1 + 0.357580 * G1 + 0.180423 * B1;
Y := 0.212671 * R1 + 0.715160 * G1 + 0.072169 * B1;
Z := 0.019334 * R1 + 0.119193 * G1 + 0.950227 * B1;

X := X / (255 * 0.950456);
Y := Y / 255;
Z := Z / (255 * 1.088754);

if (Y > 0.008856) then
begin
fY := power(Y, 1.0 / 3.0);
L^ := Round(116.0 * fY - 16.0 + 0.5);
end
else
begin
fY := 7.787 * Y + 16.0 / 116.0;
L^ := Round(903.3 * Y + 0.5);
end;

if (X > 0.008856) then
fX := power(X, 1.0 / 3.0)
else
fX := 7.787 * X + 16.0 / 116.0;

if (Z > 0.008856) then
fZ := power(Z, 1.0 / 3.0)
else
fZ := 7.787 * Z + 16.0 / 116.0;

a^ := Round(500.0 * (fX - fY) + 0.5);
b^ := Round(200.0 * (fY - fZ) + 0.5);
end;
 
unit HSLUtils;

interface

uses
Windows, Graphics;

var
HSLRange: integer = 240;

// convert a HSL value into a RGB in a TColor
// HSL values are 0.0 to 1.0 double
function HSLtoRGB (H, S, L: double): TColor;

// convert a HSL value into a RGB in a TColor
// SL values are 0 to the HSLRange variable
// H value is to HSLRange-1
function HSLRangeToRGB (H, S, L : integer): TColor;

// convert a RGB value (as TColor) into HSL
// HSL values are 0.0 to 1.0 double
procedure RGBtoHSL (RGB: TColor; var H, S, L : double);

// convert a RGB value (as TColor) into HSL
// SL values are 0 to the HSLRange variable
// H value is to HSLRange-1
procedure RGBtoHSLRange (RGB: TColor; var H, S, L : integer);

implementation

function HSLtoRGB (H, S, L: double): TColor;
var
M1, M2: double;

function HueToColourValue (Hue: double) : byte;
var
V : double;
begin
if Hue < 0 then
Hue := Hue + 1
else
if Hue > 1 then
Hue := Hue - 1;

if 6 * Hue < 1 then
V := M1 + (M2 - M1) * Hue * 6
else
if 2 * Hue < 1 then
V := M2
else
if 3 * Hue < 2 then
V := M1 + (M2 - M1) * (2/3 - Hue) * 6
else
V := M1;
Result := round (255 * V)
end;

var
R, G, B: byte;
begin
if S = 0 then
begin
R := round (255 * L);
G := R;
B := R
end else begin
if L <= 0.5 then
M2 := L * (1 + S)
else
M2 := L + S - L * S;
M1 := 2 * L - M2;
R := HueToColourValue (H + 1/3);
G := HueToColourValue (H);
B := HueToColourValue (H - 1/3)
end;

Result := RGB (R, G, B)
end;

function HSLRangeToRGB (H, S, L : integer): TColor;
begin
Result := HSLToRGB (H / (HSLRange-1), S / HSLRange, L / HSLRange)
end;

// Convert RGB value (0-255 range) into HSL value (0-1 values)

procedure RGBtoHSL (RGB: TColor; var H, S, L : double);

function Max (a, b : double): double;
begin
if a > b then
Result := a
else
Result := b
end;

function Min (a, b : double): double;
begin
if a < b then
Result := a
else
Result := b
end;

var
R, G, B, D, Cmax, Cmin: double;
begin
R := GetRValue (RGB) / 255;
G := GetGValue (RGB) / 255;
B := GetBValue (RGB) / 255;
Cmax := Max (R, Max (G, B));
Cmin := Min (R, Min (G, B));

// calculate luminosity
L := (Cmax + Cmin) / 2;

if Cmax = Cmin then // it's grey
begin
H := 0; // it's actually undefined
S := 0
end else begin
D := Cmax - Cmin;

// calculate Saturation
if L < 0.5 then
S := D / (Cmax + Cmin)
else
S := D / (2 - Cmax - Cmin);

// calculate Hue
if R = Cmax then
H := (G - B) / D
else
if G = Cmax then
H := 2 + (B - R) /D
else
H := 4 + (R - G) / D;

H := H / 6;
if H < 0 then
H := H + 1
end
end;

procedure RGBtoHSLRange (RGB: TColor; var H, S, L : integer);
var
Hd, Sd, Ld: double;
begin
RGBtoHSL (RGB, Hd, Sd, Ld);
H := round (Hd * (HSLRange-1));
S := round (Sd * HSLRange);
L := round (Ld * HSLRange);
end;

end.
 
unit uLabRgb;

interface

type
TVector3 = array[1..3] of Double;

function LabToRgb(Lab: TVector3): TVector3;
function RgbToLab(Rgb: TVector3): TVector3;

implementation

type
TMatrix3 = array[1..3, 1..3] of Double;

var
RgbXyz: TMatrix3 = ((1, 0, 0), (0, 1, 0), (0, 0, 1));
XyzRgb: TMatrix3 = ((1, 0, 0), (0, 1, 0), (0, 0, 1));

{ CCIR recommended values }
PhosphorX: TVector3 = (0.64, 0.30, 0.15);
PhosphorY: TVector3 = (0.33, 0.60, 0.06);
WhitePoint: TVector3 = (0.95, 1.0000, 1.09);
Gamma: Double = 1 / 0.45;

function MultiplyMatrix3ByVector3(const M: TMatrix3;
const V: TVector3): TVector3;
var
I: Integer;
J: Integer;
begin
for I := 1 to 3 do begin
Result := 0.0;
for J := 1 to 3 do
Result := Result + M[I, J] * V[J] end end;

function MultiplyMatrix3ByMatrix3(const M1, M2: TMatrix3): TMatrix3;
var
I: Integer;
J: Integer;
K: Integer;
begin
for I := 1 to 3 do
for J := 1 to 3 do begin
Result[I, J] := 0.0;
for K := 1 to 3 do
Result[I, J] := Result[I, J] + M1[I, K] * M2[K, J] end end;

function InvertMatrix3(const M: TMatrix3): TMatrix3;
var
I: Integer;
J: Integer;
D: Double;

function Next(I: Integer): Integer;
begin
Result := I + 1;
if Result > 3 then
Result := Result - 3 end;

function Prev(I: Integer): Integer;
begin
Result := I - 1;
if Result < 1 then
Result := Result + 3 end;

begin
D := 0;
for I := 1 to 3 do
D := D + M[1, I] * (M[2, Next(I)] * M[3, Prev(I)] -
M[2, Prev(I)] * M[3, Next(I)]);
FillChar(Result, SizeOf(Result), 0);
for I := 1 to 3
do for J := 1 to 3 do
Result[J, I] := (M[Next(I), Next(J)] * M[Prev(I), Prev(J)] -
M[Next(I), Prev(J)] * M[Prev(I), Next(J)]) / D end;

function LabToXyz(const Lab: TVector3): TVector3;
var
LL: Double;

function Cube(X: Double): Double;
begin
if X >= (6 / 29) then
Result := X * X * X
else
Result := (108 / 841) * (X - (4 / 29)) end;

begin
LL := (Lab[1] + 16) / 116;
Result[1] := WhitePoint[1] * Cube(LL + Lab[2] / 500);
Result[2] := WhitePoint[2] * Cube(LL);
Result[3] := WhitePoint[3] * Cube(LL - Lab[3] / 200) end;

function XyzToRgb(const Xyz: TVector3): TVector3;
var
I: Integer;
begin
Result := MultiplyMatrix3ByVector3(XyzRgb, Xyz);
for I := 1 to 3 do
if Result <= 0.0 then
Result := 0
else Result := Exp(Ln(Result) / Gamma) end;

function LabToRgb(Lab: TVector3): TVector3;
begin
Result := XyzToRgb(LabToXyz(Lab)) end;

function RgbToXyz(const Rgb: TVector3): TVector3;
var
I: Integer;
begin
Result := Rgb;
for I := 1 to 3 do
if Result <= 0.0 then
Result := 0
else Result := Exp(Ln(Result) * Gamma);
Result := MultiplyMatrix3ByVector3(RgbXyz, Result) end;

function XyzToLab(const Xyz: TVector3): TVector3;
var
YY: Double;

function CubeRoot(X: Double): Double;
begin
if X >= (216 / 24389) then
Result := Exp(Ln(X) / 3)
else
Result := (841 / 108) * X + (4 / 29) end;

begin
YY := CubeRoot(Xyz[2] / WhitePoint[2]);
Result[1] := 116 * YY - 16;
Result[2] := 500 * (CubeRoot(Xyz[1] / WhitePoint[1]) - YY);
Result[3] := 200 * (YY - CubeRoot(Xyz[3] / WhitePoint[3])) end;

function RgbToLab(Rgb: TVector3): TVector3;
begin
Result := XyzToLab(RgbToXyz(Rgb)) end;

procedure InitTransformationMatrices;
var
I: Integer;
J: Integer;
C: TVector3;
CToXyz: TMatrix3;
XyzToC: TMatrix3;
begin
for I := 1 to 3 do begin
CToXyz[1, I] := PhosphorX;
CToXyz[2, I] := PhosphorY;
CToXyz[3, I] := 1 - PhosphorX - PhosphorY end;
XyzToC := InvertMatrix3(CToXyz);
C := MultiplyMatrix3ByVector3(XyzToC, WhitePoint);

for I := 1 to 3 do
for J := 1 to 3 do
RgbXyz[I, J] := CToXyz[I, J] * C[J];

XyzRgb := InvertMatrix3(RgbXyz)
end;

initialization
InitTransformationMatrices

end.


这个与 Photoshop 非常近似.
 
>这个与 Photoshop 非常近似.

你试过吗?但我测试过比上面的函数更加离谱,与photoshop相差很远啊!!你是怎样使用的?
 
没说的,会的都说完了。
 
后退
顶部