From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Mark Oteiza Newsgroups: gmane.emacs.bugs Subject: bug#28400: 26.0.50; lcms2 bindings Date: Mon, 11 Sep 2017 19:10:06 -0400 Message-ID: <20170911231006.GA5455@holos.localdomain> References: <877ex7yiph.fsf@holos> <83shfvvkme.fsf@gnu.org> <20170910220422.GA14577@holos.localdomain> <831sndth2e.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: blaine.gmane.org 1505171485 32529 195.159.176.226 (11 Sep 2017 23:11:25 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 11 Sep 2017 23:11:25 +0000 (UTC) User-Agent: Mutt/1.9.0 (2017-09-02) Cc: 28400@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Tue Sep 12 01:11:15 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1drXr7-0007Vy-BU for geb-bug-gnu-emacs@m.gmane.org; Tue, 12 Sep 2017 01:11:05 +0200 Original-Received: from localhost ([::1]:60980 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1drXrE-0001io-9F for geb-bug-gnu-emacs@m.gmane.org; Mon, 11 Sep 2017 19:11:12 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:43124) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1drXr8-0001ib-1t for bug-gnu-emacs@gnu.org; Mon, 11 Sep 2017 19:11:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1drXr4-0000d1-OW for bug-gnu-emacs@gnu.org; Mon, 11 Sep 2017 19:11:06 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:53836) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1drXr4-0000cs-Kf for bug-gnu-emacs@gnu.org; Mon, 11 Sep 2017 19:11:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1drXr4-0002Y3-90 for bug-gnu-emacs@gnu.org; Mon, 11 Sep 2017 19:11:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Mark Oteiza Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 11 Sep 2017 23:11:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 28400 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 28400-submit@debbugs.gnu.org id=B28400.15051714209739 (code B ref 28400); Mon, 11 Sep 2017 23:11:02 +0000 Original-Received: (at 28400) by debbugs.gnu.org; 11 Sep 2017 23:10:20 +0000 Original-Received: from localhost ([127.0.0.1]:34284 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1drXqJ-0002Wv-Ny for submit@debbugs.gnu.org; Mon, 11 Sep 2017 19:10:20 -0400 Original-Received: from mail-qk0-f179.google.com ([209.85.220.179]:33137) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1drXqH-0002Wg-Tm for 28400@debbugs.gnu.org; Mon, 11 Sep 2017 19:10:14 -0400 Original-Received: by mail-qk0-f179.google.com with SMTP id o129so21885333qkd.0 for <28400@debbugs.gnu.org>; Mon, 11 Sep 2017 16:10:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=udel-edu.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=aArURim+PhE6IO/01jjVh8Ohb3KBmK3b+sXlCKvxe4o=; b=WifvVdYxcoDTXNJkDqJFt6IN8GNIUX7b1YwQny6mUQ1a2t8J1d0r4NTrP27Bwp0Jis Frk93sh1ml4wR9y6JGtPMWS9IStlSFZqS6enP0quzcKsbfRcju9ukLnAfqMsodQeDkL8 fJHtdQd40z5yvnjymge79Z8PGJphwi86HJNTl7CD9PL1FrPXF/gWc0E42Twp7Onlt5dI I70yffx4eEQg0hRDteENjZiUAzdP11xk1XpOYA5Da215iEuyOyM8CoxHXCakYQEqXqiH V3EOk89UDzcqQ8MAhuI37/CG8agDXKmkf9hYBi9UdGArdJ1YhRfeLVMZVtYlIoWLoDWi Ft1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=aArURim+PhE6IO/01jjVh8Ohb3KBmK3b+sXlCKvxe4o=; b=EOlvW94If6UXpYyxzc49IUemIvoV4Hku/h77EsAff2YSALmmbUL9Mv7ELKseIfCCsi xrYUmAEx40qSrk8cOOU/75loZCctwcGKigSvmFl/2LUmMoQz/8o0HdFYvB8ql2RiGDyS jlruFu9IN4fSKpL8IkFimZZVwptVTy5WdY2XxxfEpQFTTyPts/smGTqfpTLc513pNDcc z7EiL69yqreCj027bggcY+UlLkE381gaTaag7slwrn+ABXfop3vOpVjNACq0MIUOUMBG WxOuBw/VRUQ1uJ/BuT8RiyNpgvdaeAZGQmyH30uhY0h/kfRHGkdaGVDbttlY6Oh0t0Ky Sr0g== X-Gm-Message-State: AHPjjUiJ+FLZSlxnu12f4HZrGlUoCA6HayVodHNYI1q5blKGSRhnxcJb hBx9VUBklcGmkgChMpPqTw== X-Google-Smtp-Source: AOwi7QBAB+7f/lhAvtxT+u7XXCQy9IMJRxkyO2oxybuZb54ddH+afKm6SQxfQdC43dIWGyA3o8GWPg== X-Received: by 10.55.148.3 with SMTP id w3mr18371744qkd.26.1505171407964; Mon, 11 Sep 2017 16:10:07 -0700 (PDT) Original-Received: from holos.localdomain (pool-173-67-36-61.bltmmd.fios.verizon.net. [173.67.36.61]) by smtp.gmail.com with ESMTPSA id b27sm7090085qtc.78.2017.09.11.16.10.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 11 Sep 2017 16:10:07 -0700 (PDT) Original-Received: by holos.localdomain (Postfix, from userid 1000) id 2E39968E70; Mon, 11 Sep 2017 19:10:06 -0400 (EDT) Content-Disposition: inline In-Reply-To: <831sndth2e.fsf@gnu.org> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:136818 Archived-At: On 11/09/17 at 06:01pm, Eli Zaretskii wrote: > > Date: Sun, 10 Sep 2017 18:04:22 -0400 > > From: Mark Oteiza > > Cc: 28400@debbugs.gnu.org > > > > >Is it really so much better than what we have now to justify requiring > > >yet another library to build Emacs? If it is, could you tell what are > > >the main advantages, or point to where those advantages are described? > > > > It was just much easier for me to hack existing code than figure out adding > > a new file and the configure.ac business. It would be much more > > sensible to offer it as an optional feature and expose color metrics as > > optional arguments, e.g. > > > > (color-distance COLOR1 COLOR2 &optional FRAME METRIC) > > > > where METRIC accepts two colors and returns a number. > > Oh, I see. But in that case, I think adding a new file and the > configure.ac business is actually quite easy. Humble beginnings attached. configure.ac | 19 +++++++ src/Makefile.in | 6 ++- src/emacs.c | 4 ++ src/lcms.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lisp.h | 5 ++ 5 files changed, 189 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index d294412dc4..df3931f938 100644 --- a/configure.ac +++ b/configure.ac @@ -3451,6 +3451,25 @@ AC_DEFUN fi AC_SUBST(LIBJPEG) +HAVE_LCMS2=no +LIBLCMS2= +if test "${with_lcms2}" != "no"; then + OLIBS=$LIBS + AC_SEARCH_LIBS([cmsCreateTransform], [lcms2], [HAVE_LCMS2=yes]) + LIBS=$OLIBS + case $ac_cv_search_cmsCreateTransform in + -*) LIBLCMS2=$ac_cv_search_cmsCreateTransform ;; + esac +fi +if test "${HAVE_LCMS2}" = "yes"; then + AC_DEFINE([HAVE_LCMS2], 1, [Define to 1 if you have the lcms2 library (-llcms2).]) + ### ??? + if test "${opsys}" = "mingw32"; then + LIBLCMS2= + fi +fi +AC_SUBST(LIBLCMS2) + HAVE_ZLIB=no LIBZ= if test "${with_zlib}" != "no"; then diff --git a/src/Makefile.in b/src/Makefile.in index dde3f1d3fb..a98ad9c5eb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -234,6 +234,8 @@ LIBXML2_CFLAGS = GETADDRINFO_A_LIBS = @GETADDRINFO_A_LIBS@ +LIBLCMS2 = @LIBLCMS2@ + LIBZ = @LIBZ@ ## system-specific libs for dynamic modules, else empty @@ -389,7 +391,7 @@ base_obj = syntax.o $(UNEXEC_OBJ) bytecode.o \ process.o gnutls.o callproc.o \ region-cache.o sound.o atimer.o \ - doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \ + doprnt.o intervals.o textprop.o composite.o xml.o lcms.o $(NOTIFY_OBJ) \ $(XWIDGETS_OBJ) \ profiler.o decompress.o \ thread.o systhread.o \ @@ -490,7 +492,7 @@ LIBES = $(LIBXML2_LIBS) $(LIBGPM) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ - $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) \ + $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) $(LIBLCMS2) \ $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) ## FORCE it so that admin/unidata can decide whether these files diff --git a/src/emacs.c b/src/emacs.c index 44f6285795..668711a5ab 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1546,6 +1546,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_xml (); #endif +#ifdef HAVE_LCMS2 + syms_of_lcms2 (); +#endif + #ifdef HAVE_ZLIB syms_of_decompress (); #endif diff --git a/src/lcms.c b/src/lcms.c new file mode 100644 index 0000000000..560b262818 --- /dev/null +++ b/src/lcms.c @@ -0,0 +1,157 @@ +/* Interface to Little CMS + Copyright (C) 2017 Mark Oteiza + +This file is NOT part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#include + +#ifdef HAVE_LCMS2 + +#include +#include + +#include "lisp.h" + +static bool +parse_lab_list (Lisp_Object lab_list, cmsCIELab *color) +{ +#define PARSE_LAB_LIST_FIELD(field) \ + if (CONSP (lab_list) && NUMBERP (XCAR (lab_list))) \ + { \ + color->field = XFLOATINT (XCAR (lab_list)); \ + lab_list = XCDR (lab_list); \ + } \ + else \ + return false; + + PARSE_LAB_LIST_FIELD (L); + PARSE_LAB_LIST_FIELD (a); + PARSE_LAB_LIST_FIELD (b); + + return true; +} + +/* http://www.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf> */ + +DEFUN ("lcms-cie-de2000", Flcms_cie_de2000, Slcms_cie_de2000, 2, 2, 0, + doc: /* Compute CIEDE2000 metric distance between COLOR1 and COLOR2. +Each color is a list of L*a*b* coordinates, where the L* channel ranges from +0 to 100, and the a* and b* channels range from -128 to 128. +Optional arguments KL, KC, KH are weighting parameters for lightness, +chroma, and hue, respectively. */) + (Lisp_Object color1, Lisp_Object color2) +{ + cmsCIELab Lab1, Lab2; + + if (!(CONSP (color1) && parse_lab_list (color1, &Lab1))) + signal_error ("Invalid color", color1); + if (!(CONSP (color2) && parse_lab_list (color2, &Lab2))) + signal_error ("Invalid color", color1); + return make_float (cmsCIE2000DeltaE (&Lab1, &Lab2, 1.0f, 1.0f, 1.0f)); +} + +/* FIXME: code duplication */ + +static bool +parse_xyz_list (Lisp_Object xyz_list, cmsCIEXYZ *color) +{ +#define PARSE_XYZ_LIST_FIELD(field) \ + if (CONSP (xyz_list) && NUMBERP (XCAR (xyz_list))) \ + { \ + color->field = XFLOATINT (XCAR (xyz_list)); \ + xyz_list = XCDR (xyz_list); \ + } \ + else \ + return false; + + PARSE_XYZ_LIST_FIELD (X); + PARSE_XYZ_LIST_FIELD (Y); + PARSE_XYZ_LIST_FIELD (Z); + + return true; +} + +DEFUN ("lcms-cam02-ucs", Flcms-cam02-ucs, Slcms_cam02_ucs, 2, 2, 0, + doc: /* Compute CAM02-UCS metric distance between COLOR1 and COLOR2. +Each color is a list of XYZ coordinates. +Optional argument is the XYZ white point, which defaults to D65. */) + (Lisp_Object color1, Lisp_Object color2) +{ + cmsViewingConditions vc; + cmsJCh jch1, jch2; + cmsHANDLE h1, h2; + cmsCIEXYZ xyz1, xyz2; + double Jp1, ap1, bp1, Jp2, ap2, bp2; + double Mp1, Mp2, FL, k; + + if (!(CONSP (color1) && parse_xyz_list (color1, &xyz1))) + signal_error ("Invalid color", color1); + if (!(CONSP (color2) && parse_xyz_list (color2, &xyz2))) + signal_error ("Invalid color", color1); + + vc.whitePoint.X = 95.047; + vc.whitePoint.Y = 100.00; + vc.whitePoint.Z = 108.883; + vc.Yb = 20; + vc.La = 100; + vc.surround = AVG_SURROUND; + vc.D_value = 1.0; + + h1 = cmsCIECAM02Init(0, &vc); + h2 = cmsCIECAM02Init(0, &vc); + cmsCIECAM02Forward(h1, &xyz1, &jch1); + cmsCIECAM02Forward(h2, &xyz2, &jch2); + cmsCIECAM02Done(h1); + cmsCIECAM02Done(h2); + /* Now have JCh, need to calculate Jab + + M = C * F_L^0.25 + J' = 1.7 J / (1 + 0.007 J) + M' = 43.86 ln(1 + 0.0228 M) + a' = M' cos(h) + b' = M' sin(h) + + where + + F_L = 0.2 k^4 (5 L_A) + 0.1 (1 - k^4)^2 (5 L_A)^(1/3), + k = 1/(5 L_A + 1) + */ + k = 1.0f / (1.0f + (5.0f * vc.La)); + FL = pow(k, 4) * vc.La + + 0.1f * pow(1 - pow(k, 4), 2) * pow(5.0f * vc.La, 1.0f / 3.0f); + Mp1 = 43.86f * log(1.0f + 0.0228f * (jch1.C * pow(FL, 0.25))); + Mp2 = 43.86f * log(1.0f + 0.0228f * (jch2.C * pow(FL, 0.25))); + Jp1 = 1.7f * jch1.J / (1.0f + (0.007f * jch1.J)); + Jp2 = 1.7f * jch2.J / (1.0f + (0.007f * jch2.J)); + ap1 = Mp1 * cos(jch1.h); + ap2 = Mp2 * cos(jch2.h); + bp1 = Mp1 * sin(jch1.h); + bp2 = Mp2 * sin(jch2.h); + return make_float(sqrt(pow(Jp2 - Jp1, 2) + + pow(ap2 - ap1, 2) + + pow(bp2 - bp1, 2))); +} + + +/* Initialization */ +void +syms_of_lcms2 (void) +{ + defsubr (&Slcms_cie_de2000); + defsubr (&Slcms_cam02_ucs); +} + +#endif /* HAVE_LCMS2 */ diff --git a/src/lisp.h b/src/lisp.h index 81f8d6a24b..19594e7830 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4396,6 +4396,11 @@ extern void syms_of_xml (void); extern void xml_cleanup_parser (void); #endif +#ifdef HAVE_LCMS2 +/* Defined in lcms.c. */ +extern void syms_of_lcms2 (void); +#endif + #ifdef HAVE_ZLIB /* Defined in decompress.c. */ extern void syms_of_decompress (void);