[latex3-commits] [git/LaTeX3-latex3-latex3] color-models: Add support for CIE-Lab colors (280de807a)
Joseph Wright
joseph.wright at morningstar2.co.uk
Thu Jul 16 20:19:41 CEST 2020
Repository : https://github.com/latex3/latex3
On branch : color-models
Link : https://github.com/latex3/latex3/commit/280de807a05b2a6358f2796ace4e0d9b0965217c
>---------------------------------------------------------------
commit 280de807a05b2a6358f2796ace4e0d9b0965217c
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date: Thu Jul 16 18:50:30 2020 +0100
Add support for CIE-Lab colors
>---------------------------------------------------------------
280de807a05b2a6358f2796ace4e0d9b0965217c
l3experimental/l3color/l3color.dtx | 162 ++++++++++++++++++++++--
l3experimental/l3color/testfiles/m3color003.lvt | 12 ++
l3experimental/l3color/testfiles/m3color003.tlg | 28 ++++
3 files changed, 193 insertions(+), 9 deletions(-)
diff --git a/l3experimental/l3color/l3color.dtx b/l3experimental/l3color/l3color.dtx
index 58b46bd03..19bac84bb 100644
--- a/l3experimental/l3color/l3color.dtx
+++ b/l3experimental/l3color/l3color.dtx
@@ -334,12 +334,28 @@
% name of a spot color ink. Such a \meta{name} may contain spaces, etc.,
% which are not permitted in the \meta{model}.
% \item \texttt{alternative-model} An alternative device colorspace, one of
-% \texttt{cmyk}, \texttt{rgb} or \texttt{gray}
+% \texttt{cmyk}, \texttt{rgb}, \texttt{gray} or \texttt{CIELAB}. The three
+% parameter-based models work as described above; see below for
+% details of CIELAB colors.
% \item \texttt{alternative-values} A comma-separated list of values
% appropriate to the \texttt{alternative-model}. This information is used by
% the PDF application if the \texttt{Separation} is not available.
% \end{itemize}
%
+% CIELAB color separations are created using the
+% \texttt{alternative-model = CIELAB} setting. These colors must also have an
+% \texttt{illuminant} key, one of \texttt{a}, \texttt{c}, \texttt{e},
+% \texttt{d50}, \texttt{d55}, \texttt{d65} or \texttt{d75}. The
+% \texttt{alternative-values} in this case are the three parameters $L$, $a$
+% and $b$ of the CIELAB model. Full details of this device-independent color
+% approach are given in the documentation to the \pkg{colorspace} package.
+%
+% CIELAB colors \emph{cannot} be converted into other device-dependent color
+% spaces, and as such, mixing can only occur if colors set up using the CIELAB
+% model are also given with an alternative parameter-based model. If that is
+% not the case, \pkg{l3color} will fallback to using black as the colorant in
+% any mixing.
+%
% \end{documentation}
%
% \begin{implementation}
@@ -1331,6 +1347,35 @@
% \end{macrocode}
% \end{variable}
%
+% \begin{variable}
+% {
+% \c_@@_model_whitepoint_CIELAB_a_tl ,
+% \c_@@_model_whitepoint_CIELAB_b_tl ,
+% \c_@@_model_whitepoint_CIELAB_e_tl ,
+% \c_@@_model_whitepoint_CIELAB_d50_tl ,
+% \c_@@_model_whitepoint_CIELAB_d55_tl ,
+% \c_@@_model_whitepoint_CIELAB_d65_tl ,
+% \c_@@_model_whitepoint_CIELAB_d75_tl
+% }
+% Whitepoint data for the CIELAB profiles.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_model_whitepoint_CIELAB_a_tl { 1.0985 ~ 1 ~ 0.3558 }
+\tl_const:Nn \c_@@_model_whitepoint_CIELAB_b_tl { 0.9807~ 1 ~ 1.1822 }
+\tl_const:Nn \c_@@_model_whitepoint_CIELAB_e_tl { 1 ~ 1 ~ 1 }
+\tl_const:cn { c_@@_model_whitepoint_CIELAB_d50_tl } { 0.9642 ~, 1 ~ 0.8251 }
+\tl_const:cn { c_@@_model_whitepoint_CIELAB_d55_tl } { 0.9568 ~ 1 ~ 0.9214 }
+\tl_const:cn { c_@@_model_whitepoint_CIELAB_d65_tl } { 0.9504 ~ 1 ~ 1.0888 }
+\tl_const:cn { c_@@_model_whitepoint_CIELAB_d75_tl } { 0.9497 ~ 1 ~ 1.2261 }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_@@_model_range_CIELAB_tl}
+% The range for CIELAB color spaces.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_model_range_CIELAB_tl { -128 ~ 127 ~ -128 ~ 127 }
+% \end{macrocode}
+% \end{variable}
+%
% \begin{macro}{\color_model_new:nnn, \@@_model_new:nnn}
% \begin{macro}{\@@_model_separation:n}
% \begin{macro}{\@@_model_separation:nn}
@@ -1342,8 +1387,12 @@
% \@@_model_separation_gray:nnnnnn ,
% \@@_model_separation_rgb:nnnnnn
% }
-% \begin{macro}{\@@_model_conver:nnn}
-% \begin{macro}{\@@_model_separation_init:nnnn}
+% \begin{macro}{\@@_model_convert:nnn}
+% \begin{macro}{\@@_model_separation_CIELAB:nnnnnn}
+% \begin{macro}{\@@_model_separation_CIELAB:nnnnnnn}
+% \begin{macro}{\@@_model_separation_init:nnnnn}
+% \begin{macro}{\@@_model_separation_init_CIELAB:n}
+% \begin{macro}{\@@_model_separation_init_CIELAB:nnnnn}
% Set up a new model: in general this has to be handled by a family-dependent
% function. To avoid some \enquote{interesting} questions with casing, we
% fold the case of the family name. The key--value list should always be
@@ -1471,7 +1520,7 @@
}
\@@_model_convert:nnn {#1} { cmyk } { rgb }
\@@_model_convert:nnn {#1} { cmyk } { gray }
- \@@_model_separation_init:nnnn {#2} { /DeviceCMYK }
+ \@@_model_separation_init:nnnnn {#2} { /DeviceCMYK } { }
{ 0 ~ 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 ~ #6 }
}
\cs_new_protected:Npn \@@_model_separation_rgb:nnnnnn #1#2#3#4#5#6
@@ -1484,7 +1533,7 @@
}
\@@_model_convert:nnn {#1} { rgb } { cmyk }
\@@_model_convert:nnn {#1} { rgb } { gray }
- \@@_model_separation_init:nnnn {#2} { /DeviceRGB }
+ \@@_model_separation_init:nnnnn {#2} { /DeviceRGB } { }
{ 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 }
}
\cs_new_protected:Npn \@@_model_separation_gray:nnnnnn #1#2#3#4#5#6
@@ -1504,7 +1553,7 @@
\fp_eval:n {##1 * #3} ~
\fp_eval:n {##1 * #3}
}
- \@@_model_separation_init:nnnn {#2} { /DeviceGray } { 0 } {#3}
+ \@@_model_separation_init:nnnnn {#2} { /DeviceGray } { } { 0 } {#3}
}
% \end{macrocode}
% Generic model conversion \emph{via} an alternative intermediate.
@@ -1520,17 +1569,64 @@
}
}
% \end{macrocode}
+% Setting up for CIELAB needs a bit more work: there is the illuminant and
+% the need for an appropriate object.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_model_separation_CIELAB:nnnnnn #1#2#3#4#5#6
+ {
+ \prop_get:NnNF \l_@@_internal_prop { illuminant }
+ \l_@@_internal_tl
+ {
+ \__kernel_msg_error:nnn { color }
+ { CIELAB-requires-illuminant } {#1}
+ \tl_set:Nn \l_@@_internal_tl { d50 }
+ }
+ \exp_args:NV \@@_model_separation_CIELAB:nnnnnnn
+ \l_@@_internal_tl {#1} {#2} {#3} {#4} {#5} {#6}
+ }
+% \end{macrocode}
+% If a CIELAB space is being set up, we need the illuminant, then create
+% the appropriate set up. At present, this doesn't include \texttt{BlackPoint}
+% or \texttt{Range} data, but that may be added later. As CIELAB colors
+% cannot be converted to anything else, we fallback to producing black: the
+% user should set up a second model for colors set up this way.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_model_separation_CIELAB:nnnnnnn #1#2#3#4#5#6#7
+ {
+ \tl_if_exist:cTF { c_@@_model_whitepoint_CIELAB_ #1 _tl }
+ {
+ \@@_model_separation_init_CIELAB:n {#1}
+ \@@_model_separation_init_CIELAB:nnnnn {#2} {#3} {#4} {#5} {#6}
+ \cs_new:cpn { @@_convert_ #1 _cmyk:w } ##1 ~ ##2 \s_@@_stop
+ { 0 ~ 0 ~ 0 ~ 1 }
+ \cs_new:cpn { @@_convert_ #1 _rgb:w } ##1 ~ ##2 \s_@@_stop
+ { 1 ~ 1 ~ 1 }
+ \cs_new:cpn { @@_convert_ #1 _gray:w } ##1 ~ ##2 \s_@@_stop
+ { 1 }
+ }
+ {
+ \__kernel_msg_error:nnn { color }
+ { unknown-CIELAB-illuminant } {#1}
+ }
+ }
+% \end{macrocode}
% Initialising the PDF structures needs two parts: creating an object
% containing the \enquote{real} name of the Separation, then adding a reference
% to that to each page. The latter uses the internal name of the \texttt{cs}.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_model_separation_init:nnnn #1#2#3#4
+\cs_new_protected:Npn \@@_model_separation_init:nnnnn #1#2#3#4#5
{
\pdf_object_now:nx { array }
{
/Separation
/ \str_convert_pdfname:n {#1} ~ #2 ~
- << /FunctionType ~ 2 /Domain ~ [0 ~ 1] /C0 ~ [#3] ~ /C1 ~ [#4] /N ~ 1 >>
+ <<
+ /FunctionType ~ 2
+ /Domain ~ [0 ~ 1]
+ \tl_if_blank:nF {#3} { /Range ~ [#3] }
+ /C0 ~ [#4] ~
+ /C1 ~ [#5] /N ~ 1
+ >>
}
\use:x
{
@@ -1541,7 +1637,35 @@
}
}
\cs_if_exist:NF \pdf_object_now:nn
- { \cs_gset_protected:Npn \@@_model_separation_init:nnnn #1#2#3#4 { } }
+ { \cs_gset_protected:Npn \@@_model_separation_init:nnnnn #1#2#3#4#5 { } }
+% \end{macrocode}
+% For CIELAB colors, we need one object per document for the illuminant,
+% plus initialisation of the color space referencing that object.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_model_separation_init_CIELAB:n #1
+ {
+ \pdf_object_new:nn { @@_illuminant_CIELAB_ #1 } { array }
+ \pdf_object_write:nx { @@_illuminant_CIELAB_ #1 }
+ {
+ /Lab ~
+ <<
+ /WhitePoint ~
+ [ \tl_use:c { c_@@_model_whitepoint_CIELAB_ #1 _tl } ]
+ /Range ~ [ \c_@@_model_range_lab_tl ]
+ >>
+ }
+ }
+\cs_if_exist:NF \pdf_object_new:nn
+ { \cs_gset_protected:Npn \@@_model_separation_init_CIELAB:n #1 { } }
+\cs_new_protected:Npn \@@_model_separation_init_CIELAB:nnnnn #1#2#3#4#5
+ {
+ \@@_model_separation_init:nnnnn
+ {#2}
+ { \pdf_object_ref:n { @@_illuminant_CIELAB_ #1 } }
+ { \c_@@_model_range_lab_tl }
+ { 100 ~ 0 ~ 0 }
+ { #3 ~ #4 ~ #5 }
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1551,6 +1675,10 @@
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \subsection{Diagnostics}
%
@@ -1586,6 +1714,16 @@
% \subsection{Messages}
%
% \begin{macrocode}
+\__kernel_msg_new:nnnn { color } { CIELAB-requires-illuminant }
+ { CIELAB~color~space~'#1'~require~an~illuminant. }
+ {
+ LaTeX~has~been~asked~to~create~a~separation~color~space~using~
+ CIELAB~specifications,~but~no~\\ \\
+ \iow_indent:n { illuminant = <basis> }
+ \\ \\
+ key~was~given~with~the~correct~information.~LaTeX~will~use~illuminant~
+ 'd50'~for~recovery.
+ }
\__kernel_msg_new:nnnn { color } { conversion-not-available }
{ No~model~conversion~available~from~'#1'~to~'#2'. }
{
@@ -1646,6 +1784,12 @@
LaTeX~has~been~asked~to~export~a~color~in~format~'#1',~
but~this~has~never~been~defined.
}
+\__kernel_msg_new:nnnn { color } { unknown-CIELAB-illuminant }
+ { Unknown~illuminant~model~'#1'. }
+ {
+ LaTeX~has~been~asked~to~use~create~a~color~space~using~CIELAB~
+ illuminant~'#1',~but~this~does~not~exist.
+ }
\__kernel_msg_new:nnnn { color } { unknown-model }
{ Unknown~color~model~'#1'. }
{
diff --git a/l3experimental/l3color/testfiles/m3color003.lvt b/l3experimental/l3color/testfiles/m3color003.lvt
index 6977d9772..d5a6e3a54 100644
--- a/l3experimental/l3color/testfiles/m3color003.lvt
+++ b/l3experimental/l3color/testfiles/m3color003.lvt
@@ -161,6 +161,14 @@
\test:nn { CMYK } { 0.1 , 0.2 , 0.3 , 0.4 }
\test:nn { RGB } { 0.1 , 0.2 , 0.3 }
\test:nn { Gray } { 0.1 }
+ \color_model_new:nnn { BarToneLab } { Separation }
+ {
+ name = BarTone~555~GN ,
+ alternative-model = CIELAB ,
+ alternative-values = {50, -30, -40},
+ illuminant = d65
+ }
+ \color_show:n { BarToneLab }
}
\TEST { Creating~new~models:~errors }
@@ -174,6 +182,10 @@
{ name = BarTone~555~GN , alternative-model }
\color_model_new:nnn { foo4 } { separation }
{ name = BarTone~555~GN , alternative-model = foo }
+ \color_model_new:nnn { foo5 } { separation }
+ { name = BarTone~555~GN , alternative-model = CIELAB }
+ \color_model_new:nnn { foo5 } { separation }
+ { name = BarTone~555~GN , alternative-model = CIELAB , illuminant = dave }
}
\TEST { Converting~new~models }
diff --git a/l3experimental/l3color/testfiles/m3color003.tlg b/l3experimental/l3color/testfiles/m3color003.tlg
index 99b060f8f..364c20658 100644
--- a/l3experimental/l3color/testfiles/m3color003.tlg
+++ b/l3experimental/l3color/testfiles/m3color003.tlg
@@ -229,6 +229,18 @@ The color fooGray has the properties:
> BarToneGray => 0.5.
<recently read> }
l. ... }
+Defining \c__color_fallback_BarToneLab_tl on line ...
+Defining \__color_parse_mix_BarToneLab:nw on line ...
+Defining \__color_parse_model_BarToneLab:w on line ...
+Defining \__color_backend_BarToneLab:n on line ...
+Defining \__color_convert_d65_cmyk:w on line ...
+Defining \__color_convert_d65_rgb:w on line ...
+Defining \__color_convert_d65_gray:w on line ...
+Defining \__color_model_BarToneLab_white: on line ...
+The color BarToneLab is undefined.
+> .
+<recently read> }
+l. ... }
============================================================
============================================================
TEST 8: Creating new models: errors
@@ -282,6 +294,22 @@ LaTeX has been asked to create a separation color space, but the model given
as
alternative-model=<model>
is unknown.
+! LaTeX3 Error: Separation color space 'foo5' require values for the
+(LaTeX3) alternative space.
+For immediate help type H <return>.
+ ...
+l. ... }
+LaTeX has been asked to create a separation color space, but no
+ alternative-values=<model>
+key was given with the correct information.
+! LaTeX3 Error: Separation color space 'foo5' require values for the
+(LaTeX3) alternative space.
+For immediate help type H <return>.
+ ...
+l. ... }
+LaTeX has been asked to create a separation color space, but no
+ alternative-values=<model>
+key was given with the correct information.
============================================================
============================================================
TEST 9: Converting new models
More information about the latex3-commits
mailing list.