TCS3200 Match

download TCS3200 Match

of 9

Transcript of TCS3200 Match

  • 8/17/2019 TCS3200 Match

    1/9

    ############################################################################## ## TCS230/TCS3200/ColorPAL Color Match Software ## (C) Copyright 2006, 2009 Bueno Systems, Inc. ## Contact: [email protected] ## ## This program 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 2 of the License, or ## (at your option) any later version. ## ## This program 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 this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ##############################################################################

    use Win32::SerialPort qw(:STAT);use Win32::Registry;

    use Tk;use Tk::Canvas;use Tk::Photo;use Tk::Scale;use Tk::Table;use Tk::DialogBox;use Tk::ROText;use Tk::ToggleButton;use File::Basename;

    require Win32::API;require "utf8_heavy.pl";require "unicore/lib/SpacePer.pl";

    require "unicore/To/Lower.pl";require "unicore/To/Upper.pl";require "unicore/To/Fold.pl";require "unicore/lib/Digit.pl";require "unicore/lib/Word.pl";require "Encode/Unicode.pm";

    $CMD_OFF = chr(0x40);$CMD_RAW = chr(0x41);$CMD_BAL = chr(0x42);$CMD_PUT = chr(0x43);$CMD_GET = chr(0x44);

    $DLE = chr(0x10);

    my $Registry;$::HKEY_LOCAL_MACHINE->Open("HARDWARE\\DEVICEMAP\\SERIALCOMM", $Registry) or die "Can't open data: $^E";my @PortNames = ();

    @RGB = ('#ff0000', '#00ff00', '#0000ff');@CurrentBlack = (0, 0, 0);

  • 8/17/2019 TCS3200 Match

    2/9

    $mw = Tk::MainWindow->new(-title => 'TCS3200/TCS230/ColorPAL Color Match v2.02');

    $fraTop = $mw->Frame->pack(-side => 'top');

    $fraSwatchPanel = $fraTop->Frame(# -background => LIGHTGRAY,

    -height => 256,-width => 128,

    )->pack(-side => 'left');

    $txtMsg = $fraSwatchPanel->Label(-background => BLACK,-foreground => YELLOW,-textvariable => \$Message,-relief => 'sunken',-borderwidth => 2

    )->pack(-side => 'top', -expand => 1, -fill => 'x', -padx => 2, -pady => 2);

    $fraWB = $fraSwatchPanel->Frame()->pack(-side => 'top');

    foreach (0..1) {$btnWB[$_] = $fraWB->ToggleButton(

    -width => 10,

    -text => $_ ? 'Balanced' : 'Raw',-ontrigger => 'press',-latching => 1,-togglegroup => \@btnWB,-onbackground => CYAN,-onaltbackground => YELLOW,-onaltforeground => RED,-command => \&PressWB,-index => $_ 

    )->pack(-side => 'left');}

    $fraWB = $fraSwatchPanel->Frame()->pack(-side => 'top');

    $fraWB->ToggleButton(-offforeground => 'WHITE',-offbackground => '#999999',-width => 10,-text => 'Set White',-command => \&DoWhiteBalance

    )->pack(-side => 'left', -pady => 2);

    $fraWB->ToggleButton(-offforeground => 'BLACK',-offbackground => '#999999',-width => 10,

    -text => 'Set Black',-command => \&DoBlackBalance

    )->pack(-side => 'left', -pady => 2);

    $canBars = $fraSwatchPanel->Canvas(-background => BLACK,-width => 124,-height => 54,-relief => 'sunken',-borderwidth => 2

  • 8/17/2019 TCS3200 Match

    3/9

    )->pack(-side => 'top', -pady => 2);

    foreach (0..2) {$canBar[$_] = $canBars->createRectangle(

    0, $_ * 18 + 4, -128, $_ * 18 + 21,-fill => $RGB[$_]

    );$txtBar[$_] = $canBars->createText(

    65,$_ * 18 + 13,-text => '',-font => 'Arial 11 bold',-fill => WHITE,-justify => 'right'

    )}

    $fraSwatch = $fraSwatchPanel->Frame(-background => BLACK,-height => 40,-width => 128,-relief => 'sunken',-borderwidth => 2,

    )->pack(-side => 'top');

    $fraSwatchPanel->Scale(-orient => 'horizontal',-label => 'Gamma Correction',-length => 128,-width => 15,-sliderlength => 15,-from => 1,-to => 100,-troughcolor => BLACK,-variable => \$CurrentGamma,-command => \&SetGamma

    )->pack(-side => 'top');

    $CurrentGamma = 35;

    $fraSwatchPanel->Label(-text => "©Copyright 2002, 2009\nBueno Systems, Inc.",

    )->pack;

    $fraButtons = $fraTop->Frame(-width => 260,-height => 260

    )->pack(-side => 'left');

    foreach my $y (0..9) {foreach my $x (0..9) {

    my $i = $y * 10 + $x;$lblColor[$i] = $fraButtons->Label(

    -takefocus => 1,-relief => 'raised',-borderwidth => 1,-text => $i,

    )->place(-x => $x * 26, -y => $y * 26, -width => 26, -height =>26);

    $lblColor[$i]->bind('' => eval("sub {DefineColor($i, ".'@CurrentRGB)}'));

  • 8/17/2019 TCS3200 Match

    4/9

    $lblColor[$i]->bind('' => eval("sub {UndefineColor($i)}"));

    }}

    $fraBot = $mw->Frame->pack(-side => 'top');

    $canDist = $fraBot->Canvas(-background => BLACK,-height => 210,-width => 390

    )->pack;

    foreach (0..99) {$txtDist[$_] = $canDist->createText(

    500, 0,-text => $_,-fill => WHITE,-font => 'Arial 7 bold',-justify => 'right'

    )}

    $mw->update;

    OpenPort();

    $Message = '';$UpdateID = $mw->repeat(50, \&Update);$mw->repeat(250, \&FlashSelected);$btnWB[0]->TurnOn;MainLoop();

    sub OpenPort {my %coms;$Registry->GetValues(\%coms);@PortNames = grep {m/^COM\d+$/} (map {$coms{$_}->[2]} keys %coms);

    foreach my $dev ((@PortNames) x 2, undef) {unless (defined $dev) {$mw->messageBox(

    -title => 'Serial I/O Error',-message => 'Unable to locate color sensor outpu

    t on any serial port.',-type => 'OK'

    );exit

    }$Message = "Scanning $dev.";$txtMsg->update;

    unless ($Port = new Win32::SerialPort("\\\\.\\$dev")and $Port->baudrate(9600)and $Port->parity('none')and $Port->databits(8)and $Port->stopbits(2)and $Port->buffers(4096,4096)and $Port->binary(1)and $Port->write_settings)

    {next

  • 8/17/2019 TCS3200 Match

    5/9

    }Win32::Sleep 1000;my (undef, $n, undef, $err) = ($Port->status);if ($err) {

    $Port->reset_error;}if ($n) {

    my $stream = $Port->input;last if $stream =~ m/R\d+ G\d+ B\d+\r/

    }$Port->close

    }return

    }

    sub Update {my $nxt;$Port->error_msg(1);my (undef, $n, undef, $err) = ($Port->status);if ($err) {

    $Port->reset_error;}if ($n) {

    $QuiteTimes = 0;

    $stream .= $Port->input;while ($stream =~ m/(R\d+ G\d+ B\d+)\r/osg) {$lastRGB = $1;$nxt = pos($stream);

    }$stream = substr($stream, $nxt) if defined $nxt;if ($lastRGB && defined $WBMode) {

    @color = ($lastRGB =~ m/R(\d+) G(\d+) B(\d+)/);@CurrentRaw = @color;if ($WBMode eq $CMD_BAL && defined @CurrentWhite && defi

    ned @CurrentBlack) {@CurrentRGB = map {int(($CurrentRaw[$_] - $Curre

    ntBlack[$_]) * 255 / ($CurrentWhite[$_] - $CurrentBlack[$_]))} (0 .. 2)

    } else {@CurrentRGB = @CurrentRaw}my $status = grep {$_ > 255} @CurrentRGB;$Message = $status ? 'Saturated' : '';foreach my $i (0..2) {

    $canBars->itemconfigure($txtBar[$i], -text => $CurrentRGB[$i]);

    $canBars->coords($canBar[$i], 0, $i * 18 + 4, $CurrentRGB[$i] / 2, $i * 18 + 21)

    }@CurrentRGB = map {$_ > 255 ? 255 : $_} @CurrentRGB;$fraSwatch->configure(-background => ScreenColor(@Curren

    tRGB));&BestMatch

    }} else {

    PutMsg($WBMode) if $QuiteTimes++ > 30}

    }

    sub PutMsg {PutCmd(shift);

  • 8/17/2019 TCS3200 Match

    6/9

    map {PutDat(chr($_))} @_;}

    sub PutCmd {$Port->write($DLE.$_[0]);

    }

    sub PutDat {my $parm = $_[0];if ($parm eq $DLE) {

    $Port->write($DLE.$DLE);} else {

    $Port->write($parm);}

    }

    sub SetGamma {foreach (grep defined, @DefinedColor) {

    my ($n, @rgb) = @$_;$lblColor[$n]->configure(-background => ScreenColor(@rgb))

    }}

    sub ScreenColor {

    my @rgb = GammaCorrect(@_);do {$rgb[$_] = 0 if $rgb[$_] < 0} foreach (0 .. 2);return sprintf('#%2.2X%2.2X%2.2X', @rgb)

    }

    sub GammaCorrect {my $max = (sort {$b $a} @_)[0];my $gammaf = ($max / 255) ** ($CurrentGamma / 100) * 255 / ($max or 1);return map {$gammaf * $_} @_ 

    }

    sub RGBtoYCC {my @rgb = map {$_ / 255} @_;

    my ($r, $g, $b) = @rgb;my $y = 0.299 * $r + 0.587 * $g + 0.114 * $b;my $c1 = $b - $y;my $c2 = $r - $y;$y = int(255 * $y);$c1 = int(111.40 * $c1) + 156;$c2 = int(135.64 * $c2) + 137;return ($y, $c1, $c2)

    }

    sub RGBtoYUV {my @rgb = @_;my ($r, $g, $b) = @_;

    my $y = int(0.299 * $r + 0.587 * $g + 0.144 * $b);my $u = int(0.492 * ($b - $y) * 128 / 112 + 128);my $v = int(0.877 * ($r - $y) * 128 / 157 + 128);return ($y, $u, $v)

    }

    sub DefineColor {if ($WBMode eq $CMD_RAW) {

    $mw->messageBox(-message => "Can't assign a raw color. Use 'Balanced' mode.", -type => 'ok')

  • 8/17/2019 TCS3200 Match

    7/9

    } else {my $no = shift;my @rgb = @_;$lblColor[$no]->configure(

    -relief => 'sunken',-background => ScreenColor(@rgb),

    );$DefinedColor[$no] = [$no, @rgb];&BestMatch

    }}

    sub UndefineColor {my $no = shift;$lblColor[$no]->configure(-relief => 'raised', -background => GRAY);$canDist->coords($txtDist[$no], 500,0);undef $DefinedColor[$no];&BestMatch;

    }

    sub FlashSelected {if (defined $PrevSelected) {

    $lblColor[$PrevSelected]->configure(-foreground => BLACK);}

    if (defined $Selected) {$lblColor[$Selected]->configure(-foreground => $Flash ? BLACK :YELLOW);

    $Flash = not $Flash;}$PrevSelected = $Selected

    }

    sub BestMatch {my $nBest;my $distBest = 1e38;my @Defined = grep defined, @DefinedColor;foreach (@Defined) {

    my ($n, @rgb) = @$_;my $distMax = 0;foreach my $i (0..2) {

    $dist = abs($rgb[$i] - $CurrentRGB[$i]);$distMax = $dist if $dist > $distMax

    }$canDist->coords($txtDist[$n], $distMax * 2 + 10, $n * 2 + 10);if ($distMax < $distBest) {$nBest = $n; $distBest = $distMax}

    }return $Selected = $nBest

    }

    sub PressWB {

    my ($on, $i) = @_;if ($on) {

    if ($i && !defined @CurrentWhite) {$mw->messageBox(-message => '"White" is undefined. Set w

    hite first.', -type => 'ok');$btnWB[0]->TurnOn;return

    } elsif ($i && !defined @CurrentBlack) {$mw->messageBox(-message => '"Black" is undefined. Set b

    lack first.', -type => 'ok');

  • 8/17/2019 TCS3200 Match

    8/9

    $btnWB[0]->TurnOn;return

    }$WBMode = $i ? $CMD_BAL : $CMD_RAW

    }}

    sub DoWhiteBalance {@CurrentWhite = @CurrentRaw;$btnWB[1]->TurnOn if defined @CurrentBlack

    }

    sub DoBlackBalance {@CurrentBlack = @CurrentRaw;$btnWB[1]->TurnOn if defined @CurrentWhite

    }

    sub StoreColors {PutMsg($CMD_OFF);$mw->afterCancel($UpdateID);$Message = '';$txtMsg->update;foreach my $no (0..99) {

    if (defined $DefinedColor[$no]) {

    PutMsg($CMD_PUT, 0x80 + $no, @{$DefinedColor[$no]}[1..3]);} else {

    PutMsg($CMD_PUT, $no, 0, 0, 0)}my $c;do {

    $c = $Port->input} until $c =~ m/\x43/;if ($no & 1) {

    $Message .= '|';$txtMsg->update

    }

    }PutMsg($WBMode);$UpdateID = $mw->repeat(50, \&Update);

    # $Message = ''}

    sub RetrieveColors {PutMsg($CMD_OFF);$mw->afterCancel($UpdateID);$Message = '';$txtMsg->update;foreach my $no (0..99) {

    PutMsg($CMD_GET, $no);

    my $c = '';do {

    $c .= $Port->input} until $c =~ m/\x10\x44(((\x10\x10)|[^\x10]){4})/;$c = $1;$c =~ s/\x10\x10/\x10/;my ($def, @rgb) = map ord, split(//, $c);if ($def & 0x80) {

    DefineColor($no, @rgb);} else {

  • 8/17/2019 TCS3200 Match

    9/9

    UndefineColor($no)}if ($no & 1) {

    $Message .= '|';$txtMsg->update

    }}PutMsg($WBMode);$UpdateID = $mw->repeat(50, \&Update);

    }