Coding practice - Grin with cat attached — LiveJournal
Yuck indeed!
From: ciphergoth Date: May 8th, 2002 - 07:03 pm (Link) |
Averaging practically anything in the Gamma-RGB colour space will get you shitty brown - it isn't very meaningful. You should try a linear colour space like CIEXYZ...
Does RGB summation not give you the result of adding paints/dyes? I'd have guessed that CIE XYZ would be more the equivalent of addition of light?
(What I know of this I studied in german, and can't remember a great deal right now).
But, assuming that this page:
http://www.engr.uconn.edu/~zhangl/convert.htm
holds the correct matrices for an 8-bit colourspace, CIE XYZ summation gives an RGB-equivalent of #A97672, instead of the #A67772 I get from raw summation of RGB.
Which may mean I've got it wrong. Go easy on me, it's early.
(What I know of this I studied in german, and can't remember a great deal right now).
But, assuming that this page:
http://www.engr.uconn.edu/~zhangl/convert.htm
holds the correct matrices for an 8-bit colourspace, CIE XYZ summation gives an RGB-equivalent of #A97672, instead of the #A67772 I get from raw summation of RGB.
Which may mean I've got it wrong. Go easy on me, it's early.
#!/usr/bin/perl #XPM averager: Read in a 2-char XPM file and produce pixel totals and avg while ($line = <>) { if($line =~ /"(..)\s+c\s#(\w\w)(\w\w)(\w\w)"/) { $r{$1}=hex($2); $g{$1}=hex($3); $b{$1}=hex($4); $X{$1}= 0.412453*$r{$1} + 0.357580*$g{$1} + 0.189423*$b{$1}; $Y{$1}= 0.212671*$r{$1} + 0.715160*$g{$1} + 0.072169*$b{$1}; $Z{$1}= 0.019334*$r{$1} + 0.119193*$g{$1} + 0.950227*$b{$1}; $hadpal=1; } elsif ($hadpal && $line =~ /".*"/) { $line =~ s/"(.*)"/$1/; while ($line =~ s/^(..)//) { if($r{$1}) { $red+=$r{$1}; $green+=$g{$1}; $blue+=$b{$1}; $CIE_X+=$X{$1}; $CIE_Y+=$Y{$1}; $CIE_Z+=$Z{$1}; $pels++; } } } } print("\n"); printf("Total: R:0x%02x/$red G:0x%02x/$green B:0x%02x/$blue Pels:$pels\n",$red,$green,$blue); $red/=$pels; $green/=$pels; $blue/=$pels; print("Total: X:$CIE_X Y:$CIE_Y Z:$CIE_Z\n"); $CIE_X/=$pels; $CIE_Y/=$pels; $CIE_Z/=$pels; printf("Avg: R:0x%02x/$red G:0x%02x/$green B:0x%02x/$blue Pels:$pels\n",$red,$green,$blue); $CIE_R=3.240479*$CIE_X -1.537150*$CIE_Y -0.498535*$CIE_Z; $CIE_G=0-0.969256*$CIE_X + 1.875992*$CIE_Y + 0.041556*$CIE_Z; $CIE_B=0.055648*$CIE_X -0.204043*$CIE_Y + 1.057311*$CIE_Z; print("Avg: X:$CIE_X Y:$CIE_Y Z:$CIE_Z -> "); printf("R:0x%02x/$CIE_R G:0x%02x/$CIE_G B:0x%02x/$CIE_B Pels:$pels\n",$CIE_R,$CIE_G,$CIE_B);
From: ciphergoth Date: May 9th, 2002 - 03:01 am (Link) |
I don't know if the results of adding paints and dyes are well defined enough to talk about in the abstract, but light is quite well behaved.
You need to gamma-correct your RGB colours in the conversion to and from XYZ. The relative intensity of a pixel is modelled as x^gamma where x is the pixel value and gamma varies between monitors but is typically around 2.2... Strictly speaking, you shouldn't then need to convert to and from XYZ since addition is the same in any linear space.
Since we don't really know the intended colour space for the image we're working from, there's a limit to how precise we can be anyway, but there you go :-)
You need to gamma-correct your RGB colours in the conversion to and from XYZ. The relative intensity of a pixel is modelled as x^gamma where x is the pixel value and gamma varies between monitors but is typically around 2.2... Strictly speaking, you shouldn't then need to convert to and from XYZ since addition is the same in any linear space.
Since we don't really know the intended colour space for the image we're working from, there's a limit to how precise we can be anyway, but there you go :-)
I was right!
From: olitheredDate: May 8th, 2002 - 03:46 pm (Link)