/pliant/graphic/color/editor.page
 
 1  module "/pliant/language/compiler.pli" 
 2  module "/pliant/graphic/misc/float.pli" 
 3  module "/pliant/admin/file.pli" 
 4  module "/pliant/protocol/http/uvar.pli" 
 5  module "/pliant/language/data/cache.pli" 
 6  module "database.pli" 
 7  module "spectrum.pli" 
 8  module "color.pli" 
 9  module "adjust.pli" 
 10  module "gradation.pli" 
 11  module "ink.pli" 
 12  module "gamut.pli" 
 13  module "spectro.pli" 
 14   
 15  module "/pliant/math/curve.pli" 
 16  module "/pliant/graphic/image/prototype.pli" 
 17  module "/pliant/graphic/image/pixmap.pli" 
 18  module "/pliant/graphic/filter/io.pli" 
 19  module "/pliant/util/encoding/http.pli" 
 20   
 21  module "/pliant/protocol/http/style/draw.pli" 
 22   
 23  requires "color_administrator" 
 24   
 25   
 26  method page display_spectrum filter1 filter2 filter3 scale_x scale_y 
 27    arg_rw HtmlPage page ; arg ColorSpectrum32 filter1 filter2 filter3 ; arg Int scale_x scale_y 
 28    var Link:ImagePixmap pixmap :> new ImagePixmap 
 29    pixmap setup (image_prototype 700 100 400 0 300*scale_x+1 100*scale_y+color_gamut:"rgb""" 
 30    for (var Int w) 400 700 
 31      (var ColorSpectrum sp) set_step 10 
 32      for (var Int i) 400 700 step 10 
 33        sp set_measure 0.1 
 34      sp set_measure w-w%10 0.1+0.9*(1-w%10/10) 
 35      sp set_measure w-w%10+10 0.1+0.9*(w%10/10) 
 36      var ColorRGB888 rgb := cast filter_XYZ:(cast sp ColorSpectrum32) ColorRGB888 
 37      for (var Int iy) 0 100*scale_y 
 38        for (var Int i) scale_x-1 
 39          if (700-w)*scale_x+i<pixmap:size_x 
 40            memory_copy addressof:rgb (pixmap pixel (700-w)*scale_x+iy) ColorRGB888:size 
 41    for (var Int d) 0 2 
 42      var ColorSpectrum32 filter := shunt d=filter1 d=filter2 filter3 
 43      if filter<>undefined 
 44        var ColorSpectrum := cast filter ColorSpectrum 
 45        for (var Int w) 400 700 
 46          var Float := w 
 47          if z>=and z<=1 
 48            (pixmap pixel (700-w)*scale_x (cast 100*scale_y*(1-z) Int)) map uInt8 := 255 
 49    var Str f1 := string (cast filter1 ColorSpectrum) 
 50    var Str f2 := string (cast filter2 ColorSpectrum) 
 51    var Str f3 := string (cast filter3 ColorSpectrum) 
 52    draw pixmap position 
 53      f1 parse (var ColorSpectrum s1a) 
 54      f2 parse (var ColorSpectrum s2a) 
 55      f3 parse (var ColorSpectrum s3a) 
 56      display_spectrum (cast s1a ColorSpectrum32) (cast s2a ColorSpectrum32) (cast s3a ColorSpectrum32) 2 5 
 57   
 58  method page display_spectrum filter1 filter2 filter3 
 59    arg_rw HtmlPage page ; arg ColorSpectrum32 filter1 filter2 filter3 
 60    display_spectrum filter1 filter2 filter3 1 1 
 61   
 62  if (options option "device"and (options option "channel") 
 63    var Link:ImagePixmap img :> new ImagePixmap 
 64    img setup (image_prototype 0 0 501 501 501 501 color_gamut:"rgb""" 
 65    var ColorRGB888 black ; black := 0 ; black := 0 ; black := 0 
 66    var ColorRGB888 dark ; dark := 40h ; dark := 40h ; dark := 40h 
 67    var ColorRGB888 middle ; middle := 80h ; middle := 80h ; middle := 80h 
 68    var ColorRGB888 light ; light := 0C0h ; light := 0C0h ; light := 0C0h 
 69    for (var Int i) 0 500 
 70      img fill 501 addressof:light 
 71    for (var Int i) 0 500 step 5 
 72      for (var Int j) 0 500 step 5 
 73        (img pixel j) map ColorRGB888 := shunt i%50=or j%50=black i%25=or j%25=dark middle 
 74    for (var Int i) 0 2 
 75      for (var Int j) 0 2 
 76        for (var Int k) -2 2 
 77          var Int xx := i*250+k 
 78          var Int yy := j*250 
 79          if xx>=and xx<=500 and yy>=and yy<=500 
 80            (img pixel xx yy) map ColorRGB888 := black 
 81          var Int xx := i*250 
 82          var Int yy := j*250+k 
 83          if xx>=and xx<=500 and yy>=and yy<=500 
 84            (img pixel xx yy) map ColorRGB888 := black 
 85    var Data:ColorDevice z_d :> color_database:data:device:(options option "device" Str) 
 86    var Data:ColorChannel z_ch :> z_d:channel:(options option "channel" Str) 
 87    var ColorSpectrum32 z_s0 := z_ch s0 
 88    var ColorSpectrum32 z_s100 := z_ch s100 
 89    if z_s0=undefined and z_s100=undefined 
 90      return 
 91    var Float zero := z_ch:options+" "+z_d:options option "zero" Float 0 
 92    var Str adjust := z_ch:options+" "+z_d:options option "adjust" Str 
 93    var Curve ac := var Curve empty_curve 
 94    for (var Int i) 0 100 
 95      ac through i/100 (dot_unadjust i/100 adjust) 
 96    ac compute both 
 97    var ColorSpectrum32 zz := cast zero ColorSpectrum32 
 98    var Curve curve1 := var Curve empty_curve 
 99    var Curve curve2 := var Curve empty_curve 
 100    var Curve curve3 := var Curve empty_curve 
 101    var Float range_x := 1 
 102    var Float range_y := 1 
 103    each sample z_ch:sample filter (keyof:sample parse (var Int i)) sort (right keyof:sample " ") 
 104      keyof:sample parse (var Float x) 
 105      var Float := ink_density color_spectrum32:sample-zz z_s0-zz z_s100-zz 
 106      curve1 through x (ac 1e-6) 
 107      var Float := ink_surface color_spectrum32:sample-zz z_s0-zz z_s100-zz 
 108      curve2 through x (ac 1e-6) 
 109      var Float := ink_thickness color_spectrum32:sample-zz z_s0-zz z_s100-zz 
 110      curve3 through x (ac 1e-6) 
 111      range_x := max range_x x 
 112      range_y := max range_y y 
 113    curve1 compute y_from_x 
 114    curve2 compute y_from_x 
 115    curve3 compute y_from_x 
 116    if curve3=success 
 117      var ColorRGB888 blue ; blue := 0 ; blue := 0 ; blue := 255 
 118      for (var Int i) 0 500 
 119        var Float := (curve3 i/500*range_x 1e-6)/range_y 
 120        if y=defined 
 121          var Int := cast y*500 Int 
 122          if j>=and j<=500 
 123            (img pixel 500-j) map ColorRGB888 := blue 
 124    if curve2=success 
 125      var ColorRGB888 green ; green := 0 ; green := 255 ; green := 0 
 126      for (var Int i) 0 500 
 127        var Float := (curve2 i/500*range_x 1e-6)/range_y 
 128        if y=defined 
 129          var Int := cast y*500 Int 
 130          if j>=and j<=500 
 131            (img pixel 500-j) map ColorRGB888 := green 
 132    if curve1=success 
 133      var ColorRGB888 red ; red := 255 ; red := 0 ; red := 0 
 134      for (var Int i) 0 500 
 135        var Float := (curve1 i/500*range_x 1e-6)/range_y 
 136        if y=defined 
 137          var Int := cast y*500 Int 
 138          if j>=and j<=500 
 139            (img pixel 500-j) map ColorRGB888 := red 
 140    reset_http_answer 
 141    http_request send_header "mime [dq]image/png[dq]" 
 142    img save http_request:answer_stream "filter [dq].png[dq]" 
 143    http_request send_footer 
 144    return 
 145     
 146  title "Color database editor" 
 147   
 148  para 
 149    [Please notice that in Pliant terminology, a 'color gamut', a 'color device' and a 'color profile' are basically all the same thing.] 
 150   
 151  page button "load new parameters" 
 152    file_tree_delete "data:/pliant/graphic/cache/" 
 153    cache_shrink 0 cache_class_costy 
 154    reload_page 
 155   
 156  uvar Str src_gamut_name densities dest_gamut_name 
 157   
 158  para 
 159    page note "sample color conversion tool" 
 160      title "Sample color conversion" 
 161      input "Source gamut: " src_gamut_name length 80 
 162      input "Source densities (in %): " densities length 40 
 163      input "Destination gamut: " dest_gamut_name length 80 
 164      button "Compute" 
 165        reload_page 
 166      para 
 167        var Link:ColorGamut src_gamut :> color_gamut src_gamut_name 
 168        var Link:ColorGamut dest_gamut :> color_gamut dest_gamut_name 
 169        if src_gamut=success and dest_gamut=success 
 170          var ColorBuffer pixel 
 171          var Str all := densities ; var Int := 0 
 172          while i<gamut_maximum_dimension and i<src_gamut:dimension and (all parse (var Float d) any:(var Str remain)) 
 173            pixel:bytes := cast d/100*255 Int 
 174            all := remain ; += 1 
 175          var ColorXYZ pixel_color := src_gamut simulate addressof:pixel 
 176          var ColorSpectrum32 pixel_spectrum := src_gamut simulate2 addressof:pixel 
 177          var ColorXYZ pixel_color2 := shunt pixel_spectrum=defined filter_XYZ:pixel_spectrum pixel_color 
 178          dest_gamut formulate pixel_color addressof:(var ColorBuffer result) 
 179          var ColorXYZ result_color := dest_gamut simulate addressof:result 
 180          var ColorSpectrum32 result_spectrum := dest_gamut simulate2 addressof:result 
 181          var ColorXYZ result_color2 := shunt result_spectrum=defined filter_XYZ:result_spectrum result_color 
 182          table columns 4 border 0 
 183            cell 
 184              table columns 3 
 185                cell header [Ink] 
 186                cell header [Encoded[lf]density] 
 187                cell header 
 188                  font color (color hsl 0 0 50) 
 189                    [Thickness] 
 190                src_gamut decode addressof:pixel (var (Array Float32 gamut_maximum_dimension) l) 
 191                for (var Int i) src_gamut:dimension-1 
 192                  cell 
 193                    text (src_gamut query "component_name "+string:i) 
 194                  cell 
 195                    text (string pixel:bytes:i/255*100 "fixed 1")+" %" 
 196                  cell 
 197                    font color (color hsl 0 0 50) 
 198                      text (string l:i*100 "fixed 1")+" %" 
 199            cell 
 200              void 
 201            cell 
 202              void 
 203            cell 
 204              table columns 3 
 205                cell header [Ink] 
 206                cell header [Encoded[lf]density] 
 207                cell header 
 208                  font color (color hsl 0 0 50) 
 209                    [Thickness] 
 210                dest_gamut decode addressof:result (var (Array Float32 gamut_maximum_dimension) l) 
 211                for (var Int i) dest_gamut:dimension-1 
 212                  cell 
 213                    text (dest_gamut query "component_name "+string:i) 
 214                  cell 
 215                    text (string result:bytes:i/255*100 "fixed 1")+" %" 
 216                  cell 
 217                    font color (color hsl 0 0 50) 
 218                      text (string l:i*100 "fixed 1")+" %" 
 219            cell 
 220              var ColorXYZn colorn := cast pixel_color ColorXYZn 
 221              text "XYZn "+(string colorn:"fixed 3")+" "+(string colorn:"fixed 3")+" "+(string colorn:"fixed 3") ; eol 
 222              var ColorLCh lch := cast pixel_color ColorLCh 
 223              text "LCh "+(string lch:"fixed 1")+" "+(string lch:"fixed 1")+" "+(string lch:"fixed 0") 
 224            cell 
 225              var ColorXYZn colorn := cast pixel_color2 ColorXYZn 
 226              text "XYZn "+(string colorn:"fixed 3")+" "+(string colorn:"fixed 3")+" "+(string colorn:"fixed 3") ; eol 
 227              var ColorLCh lch := cast pixel_color ColorLCh 
 228              text "LCh "+(string lch:"fixed 1")+" "+(string lch:"fixed 1")+" "+(string lch:"fixed 0") 
 229            cell 
 230              var ColorXYZn colorn := cast result_color2 ColorXYZn 
 231              text "XYZn "+(string colorn:"fixed 3")+" "+(string colorn:"fixed 3")+" "+(string colorn:"fixed 3") ; eol 
 232              var ColorLCh lch := cast result_color ColorLCh 
 233              text "LCh "+(string lch:"fixed 1")+" "+(string lch:"fixed 1")+" "+(string lch:"fixed 0") 
 234            cell 
 235              var ColorXYZn colorn := cast result_color ColorXYZn 
 236              text "XYZn "+(string colorn:"fixed 3")+" "+(string colorn:"fixed 3")+" "+(string colorn:"fixed 3") ; eol 
 237              var ColorLCh lch := cast result_color ColorLCh 
 238              text "LCh "+(string lch:"fixed 1")+" "+(string lch:"fixed 1")+" "+(string lch:"fixed 0") 
 239            cell color (cast pixel_color ColorRGB888) 
 240              fixed [ ] 
 241            cell color (cast pixel_color2 ColorRGB888) 
 242              fixed [ ] 
 243            cell color (cast result_color2 ColorRGB888) 
 244              fixed [ ] 
 245            cell color (cast result_color ColorRGB888) 
 246              fixed [ ] 
 247      para 
 248        display_spectrum (src_gamut simulate2 addressof:pixel) (dest_gamut simulate2 addressof:result) (var ColorSpectrum32 no_spectrum) 
 249      para 
 250        text "CMC("+string:cmc_distance_l_parameter+","+string:cmc_distance_c_parameter+") distance is " ; bold text:(string (cmc_distance (cast pixel_color ColorXYZ) (cast result_color ColorXYZ)) "fixed 1") ; eol 
 251    eol 
 252    page note "compute LCh CMC distance" 
 253      title "CMC distance" 
 254      input "Reference LCh: " (var Str color1) length 20 
 255      input "Effective LCh: " (var Str color2) length 20 
 256      page button "Compute CMC distance" 
 257        if (color1 parse (var Float l1) (var Float c1) (var Float h1)) 
 258          if (color2 parse (var Float l2) (var Float c2) (var Float h2)) 
 259            var ColorLCh lch1 ; lch1 := l1 ; lch1 := c1 ; lch1 := h1 
 260            var ColorLCh lch2 ; lch2 := l2 ; lch2 := c2 ; lch2 := h2 
 261            table columns 2 
 262              cell 
 263                text "Reference LCh: "+(string l1 "fixed 1")+" "+(string c1 "fixed 1")+" "+(string h1 "fixed 0") ; eol 
 264              cell color (cast (cast lch1 ColorXYZ) ColorRGB888) 
 265                fixed [   ] 
 266              cell 
 267                text "Effective LCh: "+(string l2 "fixed 1")+" "+(string c2 "fixed 1")+" "+(string h2 "fixed 0") ; eol 
 268              cell color (cast (cast lch2 ColorXYZ) ColorRGB888) 
 269                fixed [   ] 
 270              cell 
 271                text "CMC distance is "+(string (cmc_distance (cast lch1 ColorLab) (cast lch2 ColorLab)) "fixed 1") ; eol 
 272              cell 
 273                void 
 274    eol 
 275    page note "compute spectrum CMC distance" 
 276      title "CMC distance" 
 277      input "Reference white: " (var Str white1) length 80 
 278      input "Reference spectrum: " (var Str spectrum1) length 80 
 279      input "Effective white: " (var Str white2) length 80 
 280      input "Effective spectrum: " (var Str spectrum2) length 80 
 281      page button "Compute CMC distance" 
 282        if (white1 parse any ":" (var ColorSpectrum w1)) or (white1 parse (var ColorSpectrum w1)) 
 283          if (spectrum1 parse any ":" (var ColorSpectrum s1)) or (spectrum1 parse (var ColorSpectrum s1)) 
 284            if (white2 parse any ":" (var ColorSpectrum w2)) or (white2 parse (var ColorSpectrum w2)) 
 285              if (spectrum2 parse any ":" (var ColorSpectrum s2)) or (spectrum2 parse (var ColorSpectrum s2)) 
 286                var ColorLCh lch1 := cast (filter_XYZ s1/w1) ColorLCh 
 287                var ColorLCh lch2 := cast (filter_XYZ s2/w2) ColorLCh 
 288                table columns 2 
 289                  cell 
 290                    text "Reference LCh: "+(string lch1:"fixed 1")+" "+(string lch1:"fixed 1")+" "+(string lch1:"fixed 0") ; eol 
 291                  cell color (cast (cast lch1 ColorXYZ) ColorRGB888) 
 292                    fixed [   ] 
 293                  cell 
 294                    text "Effective LCh: "+(string lch2:"fixed 1")+" "+(string lch2:"fixed 1")+" "+(string lch2:"fixed 0") ; eol 
 295                  cell color (cast (cast lch2 ColorXYZ) ColorRGB888) 
 296                    fixed [   ] 
 297                  cell 
 298                    text "CMC distance is "+(string (cmc_distance (cast lch1 ColorLab) (cast lch2 ColorLab)) "fixed 1") ; eol 
 299                  cell 
 300                    void 
 301   
 302  table columns 3 
 303    cell header [Device] 
 304    cell void 
 305    cell header [Description] 
 306    each color_database:data:device 
 307      cell 
 308        text keyof:d 
 309      cell 
 310        text d:label 
 311      cell 
 312        page button "edit" 
 313          title "Color device '"+keyof:d+"'" 
 314          page note "printer settings used to build this profile" 
 315            title "Printer settings for '"+keyof:d+"' color profile" 
 316            var Data:ColorPrinter :> printer 
 317            table columns 3 border 0 
 318              cell [Driver:] 
 319              cell 
 320                input "" p:driver length 10 
 321              cell 
 322                [The filter is the Pliant driver.] ; eol 
 323                [Most common filter are] ; fixed [ escp2 ] ; [for Epson stylus line,] 
 324                fixed [ pcl ] ; [for HP Designjet (does not work on HP Desktop inkjet printers), ] 
 325                [and ] ; fixed [ gimprint ] ; [if the printer will be driven using Gimp-print free software.] 
 326              cell [Model:] 
 327              cell 
 328                input "" p:model length 20 
 329              cell 
 330                [Must be one of the models the driver is awared of.] 
 331              cell [Extra options:] 
 332              cell 
 333                input "" p:options length 40 
 334              cell 
 335                [As an example, the] ; fixed [ escp2 ] ; [driver recognizes] ; fixed [ unidirectional ] ; [option.] 
 336              cell [Paper name:] 
 337              cell 
 338                input "" p:paper length 40 noeol 
 339              cell 
 340                [This is informative only.] 
 341              cell [Paper size:] 
 342              cell 
 343                input "" p:size_x length 4 noeol 
 344                input " x " p:size_y length 4 noeol 
 345                [ mm] 
 346              cell 
 347                void 
 348              cell [Margins:] 
 349              cell 
 350                input "L" p:margin_left length 3 noeol 
 351                input "T" p:margin_top length 3 noeol 
 352                input "R" p:margin_right length 3 noeol 
 353                input "B" p:margin_bottom length 3 noeol 
 354                [ mm] 
 355              cell 
 356                void 
 357              cell [R鳯lution:] 
 358              cell 
 359                input "" p:resolution_x length 4 noeol 
 360                input " x " p:resolution_y length 4 noeol 
 361                [ dpi] 
 362              cell 
 363                void 
 364              cell [Antialiasing:] 
 365              cell 
 366                input "" p:antialiasing_x length 1 noeol 
 367                input " x " p:antialiasing_y length 1 
 368              cell 
 369                [Use no antialiasing if your computer is slow, 2 if your computer is faster than the printer.]  
 370              cell [Sharpening:] 
 371              cell 
 372                input "" p:sharpening length 5 
 373              cell 
 374                [Leave it blank unless you want to experiment.] 
 375              cell [Maximum density:] 
 376              cell 
 377                input "" p:limit length 5 
 378              cell 
 379                [Leave it blank unless you know what you do: this is not the right way to correct a poor calibration.] 
 380              cell [Middle adjustment:] 
 381              cell 
 382                input "" p:middle length 5 
 383              cell 
 384                [Leave it blank unless you know what you do: this is not the right way to correct a poor calibration.] 
 385              cell [Gamut:] 
 386              cell 
 387                input "" p:gamut length 40 
 388              cell 
 389                void 
 390              cell [Calibration steps:] 
 391              cell 
 392                input "" p:grid_steps length 2 
 393              cell 
 394                [How many steps do we compute on the calibration grid in each dimension. ] 
 395                [33 is perfect but will require several hours of calibration on a fast computer, 17 is high quality, and 9 is correct.] 
 396            button "Update" 
 397              goto_backward 
 398          table columns 2 border 0 
 399            cell [Label:] 
 400            cell 
 401              input "" d:label length 60 
 402            cell [Description:] 
 403            cell 
 404              text_input "" d:comment columns 60 rows 10 
 405            cell [Gamut extra options:] 
 406            cell 
 407              input "" d:options length 60 noeol 
 408              button "Update" 
 409                cache_shrink 0 cache_class_costy 
 410                goto_backward 
 411              link "what do these options mean" "/pliant/graphic/color/adjust" 
 412             
 413          table columns 5 
 414            cell header [Ink] 
 415            cell header [Sample] 
 416            cell header [Opacity] 
 417            cell void 
 418            cell header [Options] 
 419            each ch d:channel 
 420              cell 
 421                text keyof:ch 
 422              var ColorSpectrum32 a_s0 := ch s0 
 423              var ColorSpectrum32 a_s100 := ch s100 
 424              if a_s0=defined and a_s100=defined 
 425                cell color (cast (filter_XYZ a_s100/a_s0) ColorRGB888) 
 426                  fixed [ ] 
 427              else 
 428                cell void 
 429              cell 
 430                if (ch:options option "opacity" Float)=defined 
 431                  text string:(ch:options option "opacity" Float) 
 432              cell 
 433                page button "edit" 
 434                  title "Ink '"+keyof:ch+"' for device '"+keyof:d+"'" 
 435                  var ColorSpectrum32 s0 := ch s0 
 436                  var ColorSpectrum32 s100 := ch s100 
 437                  var Float zero := ch:options+" "+d:options option "zero" Float 0 
 438                  var ColorSpectrum32 := cast zero ColorSpectrum32 
 439                  var Float deaden := ch:options+" "+d:options option "deaden" Float 0 
 440                  var CBool composed := (keyof:ch search "+" -1)<>(-1) 
 441                  var Int maxi := shunt (exists ch:sample:"255") 255 100 
 442                  var Float display := ch:options option "density_exposure_display" Float 0 
 443                  if s0=defined and s100=defined 
 444                    check ColorSpectrum32:size=31*Float32:size 
 445                    table columns 4 border 0 
 446                      cell 
 447                        var Float mi := 1 
 448                        var Float ma := 0 
 449                        for (var Int w) 0 30 
 450                          mi := min mi (addressof:s100 map Float32 w) 
 451                          ma := max ma (addressof:s100 map Float32 w) 
 452                        text "Absolute reflexion range: " 
 453                        fixed 
 454                          text (string (cast mi*1000 Int)/1000)+" "+(string (cast ma*1000 Int)/1000) 
 455                        eol 
 456                        var Float mi := 1 
 457                        var Float ma := 0 
 458                        for (var Int w) 0 30 
 459                          mi := min mi (addressof:s100 map Float32 w)/(addressof:s0 map Float32 w) 
 460                          ma := max ma (addressof:s100 map Float32 w)/(addressof:s0 map Float32 w) 
 461                        text "Relative reflexion range: " 
 462                        fixed 
 463                          text (string (cast mi*1000 Int)/1000)+" "+(string (cast ma*1000 Int)/1000) 
 464                        eol 
 465                        var ColorXYZ xyz := filter_XYZ s100/s0 
 466                        text "XYZ: " 
 467                        fixed 
 468                          text (string xyz:"fixed 3")+" "+(string xyz:"fixed 3")+" "+(string xyz:"fixed 3") 
 469                        eol 
 470                        var ColorYxy yxy := cast xyz ColorYxy 
 471                        text "Yxy: " 
 472                        fixed 
 473                          text (string yxy:"fixed 3")+" "+(string yxy:"fixed 3")+" "+(string yxy:"fixed 3") 
 474                        eol 
 475                        var ColorLab lab := cast xyz ColorLab 
 476                        text "L*a*b*: " 
 477                        fixed 
 478                          text (string lab:"fixed 1")+" "+(string lab:"fixed 1")+" "+(string lab:"fixed 1") 
 479                        eol 
 480                        text "Zero: "+(string zero "fixed 3") 
 481                        eol 
 482                        text "Deaden: "+(string deaden "fixed 3") 
 483                      var ColorXYZ paper := filter_XYZ s0 
 484                      cell 
 485                        [Paper:] ; eol 
 486                        var ColorLCh lch := cast paper ColorLCh 
 487                        [L*C*h] ; small [ ab] ; eol 
 488                        fixed 
 489                          text (string lch:"fixed 1") ; fixed [ ] ; text (string lch:"fixed 1") ; fixed [ ] ; text (string lch:"fixed 0") ; eol 
 490                        [Sample and spectrum ->] 
 491                      cell 
 492                        var ColorRGB888 rgb := cast paper ColorRGB888 
 493                        image "sample/r"+string:(cast rgb:Int)+"g"+string:(cast rgb:Int)+"b"+string:(cast rgb:Int) 
 494                      cell 
 495                        display_spectrum s0 (var ColorSpectrum32 no_spectrum) (cast no_spectrum ColorSpectrum32) 
 496                  table columns (shunt composed 9 7) 
 497                    cell header [Color] 
 498                    cell header 
 499                      [Linear[lf]Thickness[lf]Surface] 
 500                    cell header [Density] 
 501                    cell header [Opacity] 
 502                    cell header [Sample] 
 503                    cell header 
 504                      [L*C*h] ; small [ ab] 
 505                    if composed 
 506                      cell header [computation[lf]color] 
 507                      cell header [computation[lf]sample] 
 508                    cell header 
 509                      [Spectrum] ; eol 
 510                      small [red is measured, green is computed] 
 511                    each sample ch:sample sort (right keyof:sample " ") 
 512                      cell 
 513                        text keyof:sample 
 514                      cell 
 515                        if s0=defined 
 516                          var ColorXYZ wished := filter_XYZ (color_spectrum32:sample-z)/(s0-z) 
 517                        if s0=defined and s100=defined 
 518                          var Float density := ink_linear color_spectrum32:sample-s0-s100-z 
 519                          text (string density*100 "fixed 1")+"%" 
 520                          var ColorXYZ got := filter_XYZ (ink_linear_simulation density s0-s100-z)/(s0-z) 
 521                          var Float err := lab_distance wished got 
 522                          fixed [ ] ; small { html "&Delta;E " ; text (string err "fixed 1") }  
 523                          var Float err := cmc_distance wished got 
 524                          fixed [ ] ; small (text "CMC "+(string err "fixed 1")) 
 525                          eol 
 526                          var Float density := ink_thickness color_spectrum32:sample-s0-s100-z 
 527                          text (string density*100 "fixed 1")+"%" 
 528                          var ColorXYZ got := filter_XYZ (ink_thickness_simulation density s0-s100-z)/(s0-z) 
 529                          var Float err := lab_distance wished got 
 530                          fixed [ ] ; small { html "&Delta;E " ; text (string err "fixed 1") }  
 531                          var Float err := cmc_distance wished got 
 532                          fixed [ ] ; small (text "CMC "+(string err "fixed 1")) 
 533                          eol 
 534                          var Float density := ink_surface color_spectrum32:sample-s0-s100-z 
 535                          text (string (cast density*1000 Int)/10)+"%" 
 536                          var ColorXYZ got := filter_XYZ (ink_surface_simulation density s0-s100-z)/(s0-z) 
 537                          var Float err := lab_distance wished got 
 538                          fixed [ ] ; small { html "&Delta;E " ; text (string err "fixed 1") }  
 539                          var Float err := cmc_distance wished got 
 540                          fixed [ ] ; small (text "CMC "+(string err "fixed 1")) 
 541                      cell 
 542                        if s0=defined and s100=defined 
 543                          var Float density := ink_density color_spectrum32:sample-s0-s100-z 
 544                          bold (text (string (exposure density display)*100 "fixed 1")+"%") 
 545                          if false 
 546                            eol 
 547                            var Float density0 := ink_density color_spectrum32:sample-z s0-z s100-z (the_function ink_density_simulation Float ColorSpectrum32 ColorSpectrum32 -> ColorSpectrum32) 0 1 (var Float err) 
 548                            small (text (string (exposure density0 display)*100 "fixed 1")+"%") 
 549                            eol 
 550                            var Float density2 := ink_density color_spectrum32:sample-z s0-z s100-z (the_function ink_density_simulation Float ColorSpectrum32 ColorSpectrum32 -> ColorSpectrum32) 2 1 (var Float err) 
 551                            small (text (string (exposure density2 display)*100 "fixed 1")+"%") 
 552                      cell 
 553                        text string:(sample option "opacity" Float) 
 554                      cell 
 555                        if s0=defined 
 556                          var ColorRGB888 rgb := cast (filter_XYZ (color_spectrum32:sample-z)/(s0-z)) ColorRGB888 
 557                          image "sample/r"+string:(cast rgb:Int)+"g"+string:(cast rgb:Int)+"b"+string:(cast rgb:Int) 
 558                      cell 
 559                        if s0=defined 
 560                          var ColorLCh lch := cast wished ColorLCh 
 561                          text (string lch:"fixed 1") ; fixed [ ] ; text (string lch:"fixed 1") ; fixed [ ] ; text (string lch:"fixed 0") 
 562                      if composed 
 563                        var ColorSpectrum32 s1 := var ColorSpectrum32 undefined_spectrum 
 564                        var Link:ColorGamut :> color_gamut keyof:d+":"+keyof:ch "" 
 565                        if g=success and (keyof:sample parse (var Int level)) 
 566                          var ColorBuffer pixel1 
 567                          for (var Int i) 0 gamut_maximum_dimension-1 
 568                            pixel1:bytes := level*255\maxi 
 569                          s1 := simulate2 addressof:pixel1 
 570                        cell 
 571                          var ColorXYZ wished1 := filter_XYZ s1 
 572                          var ColorLCh lch1 := cast wished1 ColorLCh 
 573                          text (string lch1:"fixed 1") ; fixed [ ] ; text (string lch1:"fixed 1") ; fixed [ ] ; text (string lch1:"fixed 0") 
 574                        cell 
 575                          if s1=defined 
 576                            var ColorRGB888 rgb := cast filter_XYZ:s1 ColorRGB888 
 577                            image "sample/r"+string:(cast rgb:Int)+"g"+string:(cast rgb:Int)+"b"+string:(cast rgb:Int) 
 578                        cell 
 579                          if s0=defined and s1=defined 
 580                            display_spectrum (color_spectrum32:sample-z)/(s0-z) s1-z (var ColorSpectrum32 no_spectrum)  
 581                      else 
 582                        cell 
 583                          if s0=defined 
 584                            display_spectrum (color_spectrum32:sample-z)/(s0-z) (var ColorSpectrum32 no_spectrum) (var ColorSpectrum32 no_spectrum) 
 585                  input "Color level: " (var Str l) noeol 
 586                  page button "Measure" noeol 
 587                    var Str s 
 588                    if (parse any:(var Str l1) "=" any:(var Str l2) "/" any:(var Str l3) "/" any:(var Str l4)) 
 589                      := l1 
 590                      := color_database:data:device:l2:channel:l3:sample:l4 
 591                    else 
 592                      := string spectro_spectrum 
 593                    ch:sample create l 
 594                    ch:sample := s 
 595                    reload_page 
 596                  button "Delete" noeol 
 597                    ch:sample delete l 
 598                    reload_page 
 599                  para 
 600                    input "Options: " ch:options length 60 noeol 
 601                    page button "Update" noeol 
 602                      cache_shrink 0 cache_class_costy 
 603                      goto_backward 
 604                    page button "Redraw" noeol 
 605                      cache_shrink 0 cache_class_costy 
 606                      reload_page 
 607                  if s0=defined and s100=defined 
 608                    para 
 609                      image "editor.html?"+(http_encode "device "+(string keyof:d)+" channel "+(string keyof:ch)) 
 610                      eol ; small [red is density, green is surface,  blue is thickness.] 
 611              cell 
 612                text ch:options 
 613          input "Channel ID: " (var Str cid) noeol 
 614          button "Create new ink" noeol 
 615            d:channel create cid 
 616            reload_page 
 617          button "Delete the ink" 
 618            d:channel delete cid 
 619            reload_page 
 620          table columns 4 
 621            cell header [Color] 
 622            cell header [... is an alias of] 
 623            cell header [Sample] 
 624            cell header [Opacity] 
 625            each d:alias 
 626              cell 
 627                text keyof:a 
 628              cell 
 629                input "" a 
 630              var Data:ColorChannel ch :> d:channel a 
 631              var ColorSpectrum32 a_s0 := ch s0 
 632              var ColorSpectrum32 a_s100 := ch s100 
 633              if a_s0=defined and a_s100=defined 
 634                cell color (cast (filter_XYZ a_s100/a_s0) ColorRGB888) 
 635                  fixed [ ] 
 636              else 
 637                cell void 
 638              cell 
 639                if (ch:options option "opacity" Float)=defined 
 640                  text string:(ch:options option "opacity" Float) 
 641          input "Alias ID: " (var Str aid) noeol 
 642          button "Create new alias" noeol 
 643            d:alias create aid 
 644            reload_page 
 645          button "Delete the alias" 
 646            d:alias delete aid 
 647            reload_page 
 648          table columns 2 
 649            cell header [Grid] 
 650            cell header [Steps] 
 651            each d:grid 
 652              cell 
 653                text keyof:g 
 654              cell 
 655                input "" length 2 
 656          input "Grid: " (var Str gid) length 40 noeol 
 657          button "Create new grid" noeol 
 658            d:grid create gid 
 659            d:grid gid := undefined 
 660            reload_page 
 661          button "Delete the grid" 
 662            d:grid delete gid 
 663            reload_page 
 664          [A grid value could be 'process_cyan+process_magenta+process_yellow+process_black' specifying that when converting from a gamut using several of these colors, the conversion will use a multidimension grid instead of per channel conversion.] 
 665        
 666   
 667  input "Color device ID: " (var Str did) noeol 
 668  button "Create new color device" noeol 
 669    color_database:data:device create did 
 670    reload_page 
 671  button "Delete the color device" 
 672    color_database:data:device delete did 
 673    reload_page 
 674