Monday, March 25, 2013

Practical Color Matching

A friend posted this link on facebook recently. Its a really cool test. It got me thinking. its no wonder people have a hard time doing color matching. Its hard just to see that a color is in fact different, then to have decide why its different and compensate for it. Not to mention you then have to compensate for lighting, and finish (matte/gloss, etc.). So i dug up an old illustrator script that i wrote for a colleague. It helps do some of the heavy lifting for you when color matching for print. It makes new color chips based on your current selection in illustrator. Heres a brief video of it in action, with a special bonus at the end.




The color nazzis will say its evil because it uses the HSB color model to create the variations. But, the range of colors that are outside the hsb gamut is small.
It doesn't make sense to do something the hard way every time because its not going to work 10% of the time. Do it the easy way then if the color is out of gamut do it the hard way. You will save time in the long run by always doing it the easy way first. You just have to keep in mind that some colors are suspect to being out of the HSB gamut, and keep an eye out for them.

Okay, the script. The best way to operate it is by..
1) Opening a new document
2) Creating an object to hold the color you want to test.
3) Set the fill color of that object to the color you wish to test.
4) Set the document color mode to RGB if its not already.
5) Select the object and run the script.
You can skip steps 2 and 3 by copying an object from another file to make it easier, and if you forget step 4, the script will remind you.
Once you have run the script you will be given the option to adjust the amount of variation between swatches. The default of 10 might be too coarse for regular use but it works great for a demo :P
You can adjust it to get more or less variation between colors as needed.
Run it as many times as you need to fine tune your prints.


Here's the Script....
-------------------------

var docRef = activeDocument;
var sel = docRef.selection;
var ColorMode = docRef.documentColorSpace;
//alert(ColorMode);
var increment = prompt("Enter adjustment value/n0 = fine, 10=Coarse","10");

try{
 if(ColorMode != "DocumentColorSpace.RGB"){
  throw new Error("Document color mode must be set to RGB\nMenu: File > Document Color Mode > RGB Color");
 }
 if(sel[0].fillColor){
  var existingcolor = sel[0].fillColor;
 }else{
  throw new Error("You must select something");
 }
 if(isNaN(increment *1)){
  throw new Errow("Adjustment entered is not a number")
 }

var exR = existingcolor.red;
var exG = existingcolor.green;
var exB = existingcolor.blue;
var exHSV =  RGBtoHSV(exR,exG,exB);
var y=0;
var posy;

for(z=0; z<3; z++){
if(z==0){
   posy = 483;
   var zfill = ModHSV(exHSV, increment*-1, 0,0);
}else if(z==1){
   posy = 0;
   var zfill = ModHSV(exHSV, 0, 0, 0);
}else if(z==2){
   posy = -483;
   var zfill = ModHSV(exHSV, increment*1, 0,0);
}
for(x=0; x<=3; x++){
 //alert("new row "+x+", V="+exHSV[2])
 var xfill = ModHSV(zfill, 0, x*increment/100, 0);
 for(y=0; y<=3; y++){
  var yfill = ModHSV(xfill, 0, 0, y*increment*2.55);
  var swatchY = docRef.pathItems.rectangle(posy+0+(x*66), 0+(y*66), 48,48);
  swatchY.fillColor = HSVtoRGB(yfill); 
 }
}
for(x=0; x<=3; x++){
 //alert("new row "+x+", V="+exHSV[2])
 var xfill = ModHSV(zfill, 0, (x*increment/100)*-1, 0);
 for(y=0; y<=3; y++){
  var yfill = ModHSV(xfill, 0, 0, y*increment*2.55);
  var swatchY = docRef.pathItems.rectangle(posy+0+(x*66)*-1, 0+(y*66), 48,48);
  swatchY.fillColor = HSVtoRGB(yfill); 
 }
}
for(x=0; x<=3; x++){
 //alert("new row "+x+", V="+exHSV[2])
 var xfill = ModHSV(zfill, 0, (x*increment/100)*-1, 0);
 for(y=0; y<=3; y++){
  var yfill = ModHSV(xfill, 0, 0, (y*increment*2.55)*-1);
  var swatchY = docRef.pathItems.rectangle(posy+0+(x*66)*-1, 0+(y*66)*-1, 48,48);
  swatchY.fillColor = HSVtoRGB(yfill); 
 }
}
for(x=0; x<=3; x++){
 //alert("new row "+x+", V="+exHSV[2])
 var xfill = ModHSV(zfill, 0, x*increment/100, 0);
 for(y=0; y<=3; y++){
  var yfill = ModHSV(xfill, 0, 0, (y*increment*2.55)*-1);
  var swatchY = docRef.pathItems.rectangle(posy+0+(x*66), 0+(y*66)*-1, 48,48);
  swatchY.fillColor = HSVtoRGB(yfill); 
 }
}
}//end z loop
}catch(e){
 alert(e);
}


// - START RGBtoHSV - //
function RGBtoHSV(exR,exG,exB){
var HSVColor = new Array();
var cMin= myMin(exR,exG,exB);   
var V = myMax(exR,exG,exB);
var Delta = V - cMin;
var S, H; 
 // Calculate saturation: saturation is 0 if r, g and b are all 0
if( V== 0){
 S= 0;
 //alert("S=0")
}else{
 S = Delta / V;
 //alert("S="+S)
}
if(S== 0){
  H = 0
}else if(exR==V){
 H = 60 * (exG - exB) / Delta
 }else if(exG==V){
     H = 120 + 60 * (exB - exR) / Delta
 }else if(exB==V){
     H = 240 + 60 * (exR - exG) / Delta;
}else{
  alert("i don't know!")
}
 
 if(H < 0){
 H = H + 360
}
HSVColor[0] = H;
HSVColor[1] = S;
HSVColor[2] = V;
return HSVColor;
}
// -  end - //

// - START HSVtoRGB - //
function HSVtoRGB(HSVColor){
 var nRGBColor = new RGBColor();
 var V = HSVColor[2];
  //alert(V);
 var S = HSVColor[1];
  //alert(S); 
 var Hex = HSVColor[0]/60;
  //alert(HSVColor[0]+"/60="+Hex);
 var primclr = Math.floor(Hex);
  //alert(primclr);
 var secclr = Hex - primclr;
  //alert(secclr+"="+Hex+"-"+primclr);
 var a = (1-S)*V;
 var b = (1-(S*secclr))*V;
 var c = (1-(S*(1-secclr)))*V;
 //alert("ABC="+secclr+","+a+", "+b+", "+c) 
 //alert(primclr);
 switch(primclr){
  case 0:
   nRGBColor.red = V;
   nRGBColor.green = c;
   nRGBColor.blue = a;
   break;
  case 1:
   nRGBColor.red = b;
   nRGBColor.green = V;
   nRGBColor.blue = a;
   break;
  case 2:
   nRGBColor.red = a;
   nRGBColor.green = V;
   nRGBColor.blue = c;
   break;
  case 3:
   nRGBColor.red = a;
   nRGBColor.green = b;
   nRGBColor.blue = V;
   break;
  case 4:
   nRGBColor.red = c;
   nRGBColor.green = a;
   nRGBColor.blue = V;
   break;
  case 5:
   nRGBColor.red = V;
   nRGBColor.green = a;
   nRGBColor.blue = b;
   break;
  case 6:
   nRGBColor.red = V;
   nRGBColor.green = c;
   nRGBColor.blue = a;
   break;
 }
 return nRGBColor;
}
// - end - //

// START ModHSV - //
//ModHSV(exHSV, increment, (increment/100), (increment*2.549))
function ModHSV(xHSVColor, H, S, V){
 var nHSV = new Array();
 nHSV[0] = xHSVColor[0] + H;
 nHSV[1] = xHSVColor[1] + S;
 nHSV[2] = xHSVColor[2] + V;
 
 if(nHSV[0]>360 || nHSV[0]<0){
  if(nHSV[0]>360){
   nHSV[0] = nHSV[0]-360;
  }else if(nHSV[0]<0){
   nHSV[0] = nHSV[0]+360;
  }else{
  nHSV[0] = 0;
  }
 }
 if(nHSV[1] > 1 || nHSV[1] < 0){
  // set to gray
  nHSV[1] = 0;
  nHSV[2] = 204;
 }
 if(nHSV[2]>255 || nHSV[2]<0){
  nHSV[1] = 0;
  nHSV[2] = 204;
 }
 return nHSV;
}
// - end - //

function myMax(r,g,b){
  if (r >= g && r >= b){
   return r;
  }else if(g >= r && g >= b){
   return g;
  }else{
   return b;
  } 
}
// end

function myMin(a,b,c){
  if (a <= b && a <= c){
   return a;
  }else if(b <= a && b <= c){
   return b;
  }else{
   return c;
  } 
}
//end

No comments:

Post a Comment