.
Coding practice - Grin with cat attached — LiveJournal
Previous Entry Next Entry
Coding practice May. 8th, 2002 09:58 pm
Just so I can still claim to write perl, and since you wondered

 
This is the RGB-average colour of the proposed EU flag


 
This is the CIEXYZ-average colour of the proposed EU flag



[wechsler@home ~] ~/xpmavg.pl < euroflag410x283.xpm
Total: R:0x11dd32e/18731822 G:0xcc85be/13403582 B:0xc474f3/12874995 Pels:112580
Avg: R:0xa6/166.386764967134 G:0x77/119.058287440043 B:0x72/114.363075146562 Pels:112580


#!/usr/bin/perl

#XPM averager: Read in a 2-char XPM file and produce pixel totals and avg
#Usage: xpmavg.pl < file.xpm

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);
		$hadpal=1;
	} elsif ($hadpal && $line =~ /".*"/) {
		$line =~ s/"(.*)"/$1/;
		while ($line =~ s/^(..)//) {
			if($r{$1}) {
				$red+=$r{$1};	
				$green+=$g{$1};	
				$blue+=$b{$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;
printf("Avg: R:0x%02x/$red G:0x%02x/$green B:0x%02x/$blue Pels:$pels\n",$red,$green,$blue); 

I was right!

From: olithered
Date: May 8th, 2002 - 03:46 pm (Link)
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...
From: wechsler
Date: May 8th, 2002 - 11:48 pm (Link)
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.
From: wechsler
Date: May 8th, 2002 - 11:49 pm (Link)
#!/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: olithered
Date: May 9th, 2002 - 04:03 am (Link)
Still looks pretty brown to me.
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 :-)

Ah well...

From: wechsler
Date: May 9th, 2002 - 03:10 am (Link)
I think I'll leave any more work on this as an exercise to the reader. I just don't enjoy maths enough to chase it any further.
From: wehmuth
Date: May 11th, 2002 - 12:12 pm (Link)
To be honest it's probably easier on the eye than the bar-code...