diff --git a/Changes b/Changes index 831cc65..54e469b 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,7 @@ - no need to supply mstar for add_rgb_space - can supply add_rgb_space-format hash-ref to the relevant functions -- add rgb_to_lab and lab_to_rgb +- add rgb_to_lab, lab_to_rgb, rgb_{to,from}_linear +- add lsRGB colour space 0.201 2022-02-14 - more accurate dependencies diff --git a/ColorSpace/RGBSpace.pm b/ColorSpace/RGBSpace.pm index f78e4bb..e0acbfd 100644 --- a/ColorSpace/RGBSpace.pm +++ b/ColorSpace/RGBSpace.pm @@ -241,6 +241,27 @@ our $RGB_SPACE = { ]), 'white_point' => $WHITE_POINT->{'D65'}, }, + 'lsRGB' => { + 'gamma' => 1.0, + 'm' => pdl([ + [ + '0.412423757575757', + '0.212656', + '0.0193323636363636' + ], + [ + '0.357579', + '0.715158', + '0.119193' + ], + [ + '0.180465', + '0.072186', + '0.950449' + ] + ]), + 'white_point' => $WHITE_POINT->{'D65'}, + }, 'ColorMatch' => { 'gamma' => '1.8', 'm' => pdl([ diff --git a/color_space.pd b/color_space.pd index 8fa4e3a..6276503 100644 --- a/color_space.pd +++ b/color_space.pd @@ -125,6 +125,7 @@ Some conversions require specifying the RGB space which includes gamma curve and SMPTE-C [SMPTE] WideGamut sRGB [709] [CIE Rec 709] + lsRGB You can also add custom RGB space definitions via the function add_rgb_space. Alternatively, as of 0.202 you can directly supply the function with a @@ -667,6 +668,73 @@ BADDOC ); +pp_def('rgb_to_linear', + Pars => 'rgb(c=3); gamma(); [o]out(c=3)', + HandleBad => 1, + GenericTypes=>['D'], + Code => ' + PDL_IF_BAD(if ($ISBAD(rgb(c=>0)) || $ISBAD(rgb(c=>1)) || $ISBAD(rgb(c=>2))) { + loop (c) %{ $SETBAD(out()); %} + } + else,) { + rgb2linear( $P(rgb), $gamma(), $P(out) ); + } + ', + Doc => <<'DOCUMENTATION', +=for ref + +Converts an RGB color triple (presumably with gamma) to an RGB color triple +with linear values. + +=for usage + +Usage: + + my $rgb_linear = rgb_to_linear( $gammaed, 2.2 ); +DOCUMENTATION + BadDoc => < encounters a bad value in any of the R, G, or B +values the output ndarray will be marked as bad and the associated R, +G, and B values will all be marked as bad. +BADDOC +); + + +pp_def('rgb_from_linear', + Pars => 'rgb(c=3); gamma(); [o]out(c=3)', + HandleBad => 1, + GenericTypes=>['D'], + Code => ' + PDL_IF_BAD(if ($ISBAD(rgb(c=>0)) || $ISBAD(rgb(c=>1)) || $ISBAD(rgb(c=>2))) { + loop (c) %{ $SETBAD(out()); %} + } + else,) { + rgb2gamma( $P(rgb), $gamma(), $P(out) ); + } + ', + Doc => <<'DOCUMENTATION', +=for ref + +Converts an RGB color triple (presumably linear) to an RGB color triple +with the specified gamma. + +=for usage + +Usage: + + my $gammaed = rgb_from_linear( $rgb_linear, 2.2 ); +DOCUMENTATION + BadDoc => < encounters a bad value in any of the R, G, or B +values the output ndarray will be marked as bad and the associated R, +G, and B values will all be marked as bad. +BADDOC +); + pp_addpm(<<'EOD'); diff --git a/t/color_space.t b/t/color_space.t index 8e2f1d8..f21016a 100644 --- a/t/color_space.t +++ b/t/color_space.t @@ -81,17 +81,27 @@ sub tapprox { ok( tapprox( $a_rgb_bad, $rgb), 'hsv_to_rgb with bad value' ) or diag($a_rgb_bad, $rgb); } -# rgb_to_xyz +# rgb_to_xyz and rgb_{to,from}_linear { my $rgb = pdl( [255,255,255],[0,0,0],[255,10,50],[1,48,199] ) / 255; my $xyz = pdl( [0.950467757575757, 1, 1.08897436363636], - [0,0,0], - [0.419265223936783, 0.217129144548417, 0.0500096992920757], - [0.113762127389896, 0.0624295703768394, 0.546353858701224] ); + [0,0,0], + [0.419265223936783, 0.217129144548417, 0.0500096992920757], + [0.113762127389896, 0.0624295703768394, 0.546353858701224] ); + my $linear_ans = pdl( [1,1,1],[0,0,0], + [1, 0.0030352698, 0.031896033], + [0.00030352698, 0.029556834, 0.57112483] ); my $a_xyz = rgb_to_xyz( $rgb, 'sRGB' ); ok( tapprox( $a_xyz, $xyz), 'rgb_to_xyz sRGB' ) or diag($a_xyz, $xyz); + my $rgb_linear = rgb_to_linear($rgb, -1); + ok( tapprox( $rgb_linear, $linear_ans), 'rgb_to_linear sRGB' ) or diag($rgb_linear, $linear_ans); + my $rgb_regamma = rgb_from_linear($rgb_linear, -1); + ok( tapprox( $rgb_regamma, $rgb), 're-rgb_from_linear sRGB' ) or diag($rgb_regamma, $rgb); + my $a2_xyz = rgb_to_xyz( $rgb_linear, 'lsRGB' ); + ok( tapprox( $a2_xyz, $xyz), 'rgb_to_xyz lsRGB' ) or diag($a2_xyz, $xyz); + my $a_rgb = xyz_to_rgb( $xyz, 'sRGB' ); ok( tapprox( $a_rgb, $rgb), 'xyz_to_rgb sRGB' ) or diag($a_rgb, $rgb);