App-PLab
view release on metacpan or search on metacpan
bin/MorphometryI view on Meta::CPAN
push @hx, $x[$j];
push @hy, $y[$j];
$j++;
$j = 0 if $j >= $#x;
}
push @hx, $x[$j];
push @hy, $y[$j];
my ($hx,$hy) = make_contour_continuous([@hx], [@hy]);
push @$hx, $hx->[0];
push @$hy, $hy->[0];
# flatten
my @ret = ();
while (@$hx) {
push @ret, shift(@$hx), shift(@$hy);
}
push @holes, [@ret];
}
return @holes;
}
# WIN
sub win_objectsetsmenuaction
{
my ( $self, $id) = @_;
my $menu = $self-> menu;
return if $self-> {currentSet} == $id;
$menu-> checked( 'lw'.($self-> {ini}-> {'LW'.$self-> {currentSet}}), 0);
$menu-> checked( 'lw'.($self-> {ini}-> {'LW'.$id}), 1);
$menu-> checked( $self-> {currentSet}, 0);
$menu-> checked( $id, 1);
my $iv = $self-> IV;
$self-> iv_cancelmode( $iv);
$self-> {currentSet} = $id;
$self-> pt_newset();
$iv-> {bone}-> backColor( $self-> {ini}-> {$self-> {setColors}->[ $self-> {currentSet}]});
my $c = $menu-> text( $id);
$c =~ s/\~//;
$self-> sb_text("Object set:$c");
}
sub win_objectlwmenuaction
{
my ( $self, $id) = @_;
my $width = $id;
$width =~ s/lw//;
$width = 9 if $width > 9;
$width = 1 if $width < 1;
return if $width == $self-> {ini}-> {'LW'.$self-> {currentSet}};
$self-> {ini}-> {'LW'.$self-> {currentSet}} = $width;
$self-> sb_text("Line width set:$width");
}
sub win_inidefaults
{
my $w = $_[0];
my $calcopt = '';
vec( $calcopt, 0, 32) = ocq::Files | ocq::Basics;
return (
$w-> SUPER::win_inidefaults,
RecWindowPos => '100 100',
RecWindowVisible => 0,
UFThreshold => 40,
BinThreshold => 128,
EdgeSize => 3,
MinArea => 0,
MaxArea => 0,
LW0 => 1,
LW1 => 1,
LW2 => 3,
EqualBrightness => 0,
CalcBrightness => 0,
CalcConvex => 0,
CalcHoles => 0,
HolesPercent => 5,
NumberOfRotations=> 128,
StatPath => '.',
CalcOptions => $calcopt,
FrameWidth => 0,
FrameColor => 0,
InvertImage => 0,
);
}
sub on_create
{
my $self = $_[0];
$self-> SUPER::on_create;
my $w = $self;
$w-> {dataExt} = 'xml';
my $i = $w-> {ini};
my $xref = [
['*0' => "~Features" => \&win_objectsetsmenuaction],
['1' => "~Background" => \&win_objectsetsmenuaction],
['2' => "~Remove" => \&win_objectsetsmenuaction],
[],
[ LineWidthIncrement => '~Increase line width' => sub {
$_[0]-> win_objectlwmenuaction( 'lw'.($_[0]-> {ini}-> {'LW'.$_[0]-> {currentSet}} + 1));
}],
[ LineWidthDecrement => '~Decrease line width' => sub {
$_[0]-> win_objectlwmenuaction( 'lw'.($_[0]-> {ini}-> {'LW'.$_[0]-> {currentSet}} - 1));
}],
];
$w-> {setColors} = [ qw( Color_Features Color_Background Color_Remove)];
$w-> menu-> insert( [[ "~Object sets" => $xref]], 'edit' , 6);
$w-> {currentSet} = 0;
$w-> pt_init();
my $iv = $w-> IV;
my $bone = $iv-> {bone};
$bone-> backColor( $w-> {ini}-> {$w-> {setColors}->[$w-> {currentSet}]});
$bone-> set( onMouseClick => sub {
my ( $cs, $mx) = ( $w-> {currentSet} + 1, scalar @{$w-> {setColors}});
$cs = 0 if $cs >= $mx;
$w-> win_objectsetsmenuaction($cs);
$_[0]-> clear_event;
});
my $scale = $::application-> uiScaling;
$scale = 1 if $scale < 1;
my $cck = $self-> ToolBar-> insert(
SpeedButton =>
name => "Contours",
origin => [120 * $scale, 1],
size => [ 36 * $scale, 36 * $scale],
image => App::PLab::ImageAppGlyphs::icon( bga::drawprocesses),
enabled => 0,
checkable => 1,
checked => 1,
hint => 'Toggle contours tickmarks drawing',
onClick => sub { $self-> iv_togglemode( $iv)},
glyphs => 2,
text => "",
selectable => 0,
transparent => 1,
flat => 1,
borderWidth => 1,
glyphs => 1,
);
$self-> ToolBar-> insert(
SpeedButton =>
name => "CalcStatistics",
origin => [ 162 * $scale, 1],
size => [ 36 * $scale, 36 * $scale],
image => App::PLab::ImageAppGlyphs::icon( bga::calcstatistics),
enabled => 1,
hint => 'Calculate statistics',
onClick => sub { $self-> opt_statistics(); },
text => "",
selectable => 0,
transparent => 1,
flat => 1,
borderWidth => 1,
);
$iv-> {drawmode} = $cck-> checked ? 1 : undef;
init_convex( $w->{ini}->{NumberOfRotations});
}
sub on_destroy
{
my ($w,$i) = ($_[0],$_[0]->{ini});
$i-> {RecWindowVisible} = defined $w-> {recWindow} ? 1 : 0;
$w-> SUPER::on_destroy;
}
sub win_closeframe
{
my $w = $_[0];
$w-> SUPER::win_closeframe;
$w-> pt_clear_all();
$w-> rpt_clear();
}
sub win_framechanged
{
my $w = $_[0];
$w-> SUPER::win_framechanged;
$w-> {mirrorImage} = undef;
my $i = $w-> IV-> image;
my $canApply = defined $i && $i-> type == im::Byte;
$w-> menu-> EditToggleMode-> enabled( defined $i);
$w-> menu-> EditApplyContours-> enabled( $canApply);
$w-> menu-> EditValidate-> enabled( defined $i);
$w-> menu-> EditImport-> enabled( defined $i);
$w-> ToolBar-> Contours-> enabled( defined $i);
if ( $w-> {recWindow}) {
my $r = $w-> {recWindow};
if ( defined $i) {
my @sz = $i-> size;
$r-> Min-> max( $sz[0] * $sz[1]);
$r-> Max-> max( $sz[0] * $sz[1]);
$r-> Edge-> max(int(($sz[0] < $sz[1] ? $sz[0] : $sz[1]) / 2));
}
$r-> ApplyBtn-> enabled( $canApply);
$r-> RestoreBtn-> enabled( $canApply && defined $w-> {mirrorImage});
$r-> Preview1-> enabled( $canApply);
$r-> Preview2-> enabled( $canApply);
$r-> Preview3-> enabled( $canApply);
}
$w-> pt_newset;
}
sub win_showrec
{
my $w = $_[0];
if ( $w-> {recWindow}) {
$w-> {recWindow}-> bring_to_front;
$w-> {recWindow}-> select;
return;
}
$w-> {recWindow} = PropRollup-> create( owner => $w);
}
sub win_entersubplace
{
my $w = $_[0];
$w-> {savePointer} = $::application-> pointer;
$::application-> pointer( cr::Wait);
return defined $w-> {mirrorImage} ? $w-> {mirrorImage} : $w-> IV-> image;
}
sub win_leavesubplace
{
my $w = $_[0];
$::application-> pointer( $w-> {savePointer});
$w-> {mirrorImage} = $w-> IV-> image unless defined $w-> {mirrorImage};
$w-> IV-> image( $_[1]);
$w-> {recWindow}-> RestoreBtn-> enabled( 1) if $w-> {recWindow};
$w-> {savePointer} = undef;
}
sub win_restore
{
my ( $w, $i) = @_;
$w-> IV-> repaint, return unless defined $w-> {mirrorImage};
$w-> IV-> image($w-> {mirrorImage});
$w-> {mirrorImage} = undef;
bin/MorphometryI view on Meta::CPAN
Handlers => {
Start => sub {
my ($obj, $el, %attrs) = @_;
return if $state{finished_header};
if ($el eq 'morphology_data') {
return if $state{seen_header};
$state{morphology_data} = {%attrs};
$state{seen_header} = 1;
} elsif ( $el eq 'object') {
return unless $state{seen_header};
return if $state{reading_object};
$state{reading_object} = 1;
for ( qw( type x y)) {
die "No tag:$_" unless defined $attrs{$_};
}
if ( $objsub) {
$_ = $objsub-> ( \%attrs, $n0, $n1);
return if $_ && $_ eq 'nocalc';
}
if ( $attrs{type} eq $n0 || $attrs{type} eq $n1) {
my @xs = split( ' ', $attrs{x});
my @ys = split( ' ', $attrs{y});
return if scalar @xs != scalar @ys;
my @poly = ();
my $i;
for ( $i = 0; $i < scalar @xs; $i++) {
next if $xs[$i] < 0 || $ys[$i] < 0;
next if scalar( @is) && ( $xs[$i] >= $is[0] || $ys[$i] >= $is[1]);
next if scalar @poly and $xs[$i] == $poly[-2] and $ys[$i] == $poly[-1];
push( @poly, $xs[$i], $ys[$i]);
}
$i = $attrs{type} eq $n0 ? $state{feats} : $state{backs};
push ( @$i, \@poly) if scalar @poly > 3;
} elsif ( $attrs{type} eq $n2) {
return if $attrs{x} < 0 || $attrs{y} < 0;
return if scalar( @is) && ( $attrs{x} >= $is[0] || $attrs{y} >= $is[1]);
push( @{$state{points}}, $attrs{x}, $attrs{y});
}
} else {
$state{has_extras} = 1;
}
},
End => sub {
my ($obj, $el) = @_;
$state{finished_header} = 1 if $el eq 'morphology_data';
$state{reading_object} = 0 if $el eq 'object';
},
});
eval { parsefile $xml $xmlname; };
if ($@) {
$w-> win_xmlerror( $xmlname);
return 0;
}
return \%state;
}
sub win_newframe
{
my $w = $_[0];
$w-> SUPER::win_newframe;
return unless defined $w-> {file};
$w-> win_extwarn if defined $w-> {ini}-> {path} &&
defined $w-> {oldPath} && $w-> {oldPath} ne $w-> {ini}-> {path};
$w-> {oldPath} = $w-> {ini}-> {path};
my $img = $w-> IV-> image;
if ( $w-> {ini}-> {InvertImage}) {
my ( $gray, $bpp) = ( $img-> type & im::GrayScale, $img-> type & im::BPP);
if ( $gray && $bpp > 1) {
$img-> resample( 0, 255, 255, 0);
} elsif ( $bpp < 24) {
$img-> palette([ map { 255 - $_} @{$img-> palette}]);
} else {
my $c = $img-> data;
$c =~ s/(.)/chr(255-ord($1))/ge;
$img-> data( $c);
}
}
my @is = $img-> size;
my $i;
my $lw = $w-> {ini}-> {FrameWidth};
my $c = $w-> {ini}-> {FrameColor} ? 0xffffff : 0;
while ( $lw--) {
for ( $i = $lw; $i < $is[0] - $lw; $i++) {
$img-> pixel( $i, $lw, $c);
$img-> pixel( $i, $is[1]-$lw-1, $c);
}
for ( $i = $lw; $i < $is[1] - $lw; $i++) {
$img-> pixel( $lw, $i, $c);
$img-> pixel( $is[0]-$lw-1, $i, $c);
}
}
my $xmlname = $w-> win_extname( $w-> {file});
return unless -f $xmlname;
$w-> {file} =~ m{[/\\]([^/\\]*)$};
my $iname = $1;
my $state = $w-> win_xmlload( $xmlname);
return unless $state;
for ( qw( imagename imagewidth imageheight xcalib ycalib)) {
next if defined $state->{morphology_data}->{$_};
$@ = "Tag $_ not present into morphology_data section.\n";
$w-> win_xmlerror( $xmlname);
}
if ( !$w->{silence} && (
($state->{morphology_data}->{imagename} ne $iname) ||
($state->{morphology_data}->{imagewidth} != $is[0]) ||
($state->{morphology_data}->{imageheight} != $is[1])
)) {
bin/MorphometryI view on Meta::CPAN
breadth = "$brd"
convex_area = "$carea"
convex_width = "$cwidth"
convex_perimeter = "$perimeter"
convex_formfactor= "$ff"
convex_xcentroid = "$xcen"
convex_ycentroid = "$ycen"
convex_fxcentroid= "$fxcen"
convex_fycentroid= "$fycen"
convex_length_width= "$clw"
spreading_index = "$si"
PARAMS
if ( $w->{ini}->{CalcHoles}) {
my @holz = get_holes( $pp, $fnc);
my $h = '"';
for ( @holz) {
my ($harea) = ($w-> win_calcbasicparameters( @$_));
$h .= "$harea ";
}
$h =~ s/\s*$//; $h .= '"';
print F " harea = $h\n";
}
}
}
# End calc
print F "/>\n\n";
}
}
my $ww = $w-> {points};
if ( defined $ww) {
for ( $i = 0; $i < scalar @$ww; $i+=2) {
print F <<POINTS;
<object type = "point"
x = "$$ww[$i]"
y = "$$ww[$i+1]"
\/>
POINTS
}
}
print F "</morphology_data>\n";
close F;
$w-> sb_text( 'saved ok.');
$w-> modified( 0);
$::application-> pointer( $waitPtr);
} else {
if ( $w->{silence}) {
$w-> win_abortpacket;
return 0;
}
return 0 if Prima::MsgBox::message(
"Error saving file $xmlname. Ignore changes?", mb::YesNo|mb::Warning) == mb::No;
}
return 1;
}
sub win_newextras
{
my $w = $_[0];
$w-> SUPER::win_newextras;
return unless defined $w-> {prevFile};
my $num = $w->{cypherMask};
my $xmlname;
my ( $min, $max) = $w-> win_getseriesrange;
$xmlname = $w-> win_formfilename( $min);
$xmlname = $w-> win_extname( $xmlname);
return unless -f $xmlname;
my $state = $w-> win_xmlload( $xmlname);
return unless $state;
$w-> {extraPoints} = $state-> {points} if scalar @{$state-> {points}};
}
sub win_importextras
{
my $w = $_[0];
$w-> iv_cancelmode( $w-> IV);
my $d = $w-> dlg_file(
cwd => 1,
directory => $w->{ini}->{path},
filterIndex => 0,
multiSelect => 0,
filter => [
['Data files' => '*.xml'],
['All files' => '*']
],
);
return 0 unless $d-> execute;
my $state = $w-> win_xmlload( $d-> fileName);
return unless $state;
my $x = 0;
if ( scalar @{$state->{feats}}) {
$w-> {lineStorage}->[0] = [] unless defined $w->{lineStorage}->[0];
$w-> {lwStorage}->[0] = [] unless defined $w->{lwStorage}->[0];
push( @{$w-> {lineStorage}->[0]}, @{$state->{feats}});
push( @{$w-> {lwStorage}->[0]}, (1) x scalar @{$state->{feats}});
$x |= 1;
}
if ( scalar @{$state->{backs}}) {
$w-> {lineStorage}->[1] = [] unless defined $w->{lineStorage}->[0];
$w-> {lwStorage}->[1] = [] unless defined $w->{lwStorage}->[0];
push( @{$w-> {lineStorage}->[1]}, @{$state->{backs}});
push( @{$w-> {lwStorage}->[1]}, (1) x scalar @{$state->{backs}});
$x |= 2;
}
return unless $x; # no contours to import
$w-> pt_updatemenu;
$w-> IV-> repaint;
$w-> modified(1);
}
sub win_closeextras
{
my $w = $_[0];
$w-> SUPER::win_closeextras;
$w-> rptex_clear();
}
sub win_extraschanged
{
my $w = $_[0];
$w-> SUPER::win_extraschanged;
$w-> menu-> EditOptCalib-> enabled( defined $w-> {nextFile} || defined $w-> {prevFile});
}
# WIN_END
# OPT
sub opt_colors
{
return {
Features => [ cl::LightGreen, 'Features'],
Background => [ cl::Yellow, 'Background'],
Remove => [ cl::White, 'Remove'],
Points => [ cl::LightRed, 'Points'],
},
}
sub opt_colormount
{
my $w = $_[0];
$w-> IV-> {bone}-> backColor( $w-> {ini}-> {$w-> {setColors}->[$w-> {currentSet}]});
}
sub opt_keys
{
return {
%{$_[0]-> SUPER::opt_keys()},
EditImport => [ kb::NoKey , "Import another contours into document"],
EditOptCalib => [ kb::NoKey , "Recalculate series"],
EditCalcStats => [ '@C' , "Calculate and display statistics"],
Undo1 => [ kb::Backspace , "Undo drawing"],
Undo2 => [ km::Alt|kb::Backspace , "Undo group of lines"],
Undo3 => [ '@U' , "Show undo dialog"],
EditInvertImage => [ kb::NoKey , "Invert image"],
EditClearAll => [ kb::NoKey , "Clear all drawings"],
EditRemovePoints => [ kb::NoKey , "Remove all points"],
EditToggleMode => [ 'F11' , "Toggle drawings/points mode"],
EditValidate => [ km::Ctrl|kb::Enter , "Validate contours"],
EditRecSetup => [ kb::NoKey , "Display recognition setup dialog"],
EditApplyContours => [ km::Alt|kb::Enter , "Apply contours to document"],
EditHack => [ kb::NoKey , "Outline convex hull of current drawing"],
HelpAbout => [ kb::NoKey, 'Standard about box'],
HelpPlabApps => [ kb::NoKey, 'Online PlabApps overview'],
HelpContents => [ kb::NoKey, 'Online Morphometry I overview'],
LineWidthIncrement => [ '@+', 'Increment line width for current object'],
LineWidthDecrement => [ '@-', 'Decrement line width for current object'],
};
};
sub opt_changecalib
{
my $w = $_[0];
Prima::MsgBox::message( "No series to convert"), return if ( !defined $w-> {nextFile} && !defined $w-> {prevFile});
my $num = $w-> {cypherMask};
my ( $fn, $tn) = $w-> win_getseriesrange;
return if Prima::MsgBox::message( "This will recalculate series ".
$w-> {fileBeg}.('X' x $num).$w-> {fileEnd}." [$fn-$tn] . Proceed?",
mb::OKCancel|mb::Information) != mb::OK;
my $fnsave = $w->{fileNum};
my $f;
my $ok = 1;
$w->{silence} = 1;
$w->{packetAborted} = 0;
my $userAborted = 0;
my $statwin = $w-> insert( Dialog =>
centered => 1,
text => 'Processing',
size => [ 300, 60],
onKeyDown => sub {
my ( $self, $code, $key, $mod) = @_;
if ( $key == kb::Esc &&
( Prima::MsgBox::message("Abort process?", mb::OKCancel|mb::Warning) == mb::OK)) {
$userAborted = 1;
$_[0]-> text('Cancelling');
}
},
onClose => sub {
$_[0]-> clear_event;
return if Prima::MsgBox::message("Abort process?", mb::OKCancel|mb::Warning) != mb::OK;
$userAborted = 1;
bin/MorphometryI view on Meta::CPAN
$dir = '' unless -d $dir;
my $d = Prima::SaveDialog-> create(
owner => $dlg,
filter => [
['Text files' => '*.txt'],
['All files' => '*']
],
directory => $dir,
);
my $res = $d-> execute;
if ( $res) {
open F, '>'.$d-> fileName;
print F $$textRef;
close F;
};
$w-> {ini}-> {StatPath} = $d-> directory;
$d-> destroy;
}
my $dlg = Prima::Window-> create(
size => [ 520, 430],
text => 'Statistic results',
widgetClass => wc::Dialog,
centered => 1,
menuItems => [
[ '~Export' => [
["~Summary..." => "F2" => kb::F2 => sub { esummary( $_[0], \$meta2, $w)} ],
["~Experiment data..." => "Ctrl+F2" => km::Ctrl|kb::F2 => sub { esummary( $_[0], \$meta1, $w)} ],
]],
[ 'Copy' => "" => kb::NoKey => sub { $::application-> Clipboard-> store( 'Text', $texts);}],
],
);
$dlg-> insert( Edit =>
origin => [ 1, 1],
size => [ $dlg-> width - 2, $dlg-> height - 2],
text => $texts,
growMode => gm::Client,
hScroll => 1,
vScroll => 1,
readOnly => 1,
font => { pitch => fp::Fixed},
wordWrap => 0,
syntaxHilite => 1,
hiliteNumbers => undef,
hiliteQStrings => undef,
hiliteQQStrings => undef,
hiliteIDs => undef,
hiliteChars => undef,
hiliteREs => [ '(N\/A)', cl::Red,
'(([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?\*)', cl::Red],
);
$dlg-> select;
}
sub opt_propcreate
{
my ( $w, $dlg, $nb, $nbpages) = @_;
$w-> SUPER::opt_propcreate( $dlg, $nb, $nbpages);
$nb-> tabs( @{$nb-> tabs}, 'Calculations', 'Frame');
$nb-> insert_to_page( $nb-> pageCount - 2,
[ Label =>
text => 'By default, only the area, the perimeter, the formfactor and centroid locations are calculated,though the program is perfectly capable of calculating all other parameters. The reason for disabling the rest is that it normally ta...
wordWrap => 1,
designScale => [ $nbpages-> font-> width, $nbpages-> font-> height],
valignment => ta::Top,
name => 'TopText',
],[ CheckBox =>
origin => [ 5, 185],
name => 'CalcBrightness',
size => [ 300, 27],
text => 'Calculate ~brightness',
onCheck => sub {
$nbpages-> EqualBrightness-> set(
checked => ($_[0]-> checked ? $nbpages-> EqualBrightness-> checked : 0),
enabled => $_[0]-> checked,
);
},
],[ CheckBox =>
origin => [ 5, 155],
name => 'EqualBrightness',
size => [ 300, 27],
text => 'E~qualize brightness',
],[ CheckBox =>
origin => [ 5, 125],
name => 'CalcConvex',
size => [ 248, 27],
text => 'Convex ~hull derived parameters',
],[ Label =>
origin => [ 5, 100],
height => 20,
name => 'SigRot',
text => '~Number of rotations',
],[ SpinEdit =>
origin => [ 5, 80],
name => 'NumberOfRotations',
size => [ 100, 20],
min => 1,
max => 256,
],[ CheckBox =>
origin => [ 5, 50],
name => 'CalcHoles',
size => [ 248, 27],
text => '~Process index / domain',
onCheck => sub {
$nbpages-> CalcConvex-> set(
checked => ($_[0]-> checked ? 1 : $nbpages-> CalcConvex-> checked),
enabled => !$_[0]-> checked,
);
},
],[ Label =>
origin => [ 5, 25],
name => 'SigPce',
height => 20,
text => 'Significance level for holes, %',
],[ SpinEdit =>
origin => [ 5, 5],
name => 'HolesPercent',
size => [ 100, 20],
bin/MorphometryI view on Meta::CPAN
);
$fcnt[2]-> focusLink( $fcnt[1]);
$fcnt[0]-> insert( [ Radio =>
origin => [ 9, 5],
size => [ 89, 28],
name => 'FT_Black',
text => 'B~lack',
], [ Radio =>
origin => [ 102, 5],
size => [ 89, 28],
name => 'FT_White',
text => 'W~hite',
]);
my $s1 = $nb-> insert_to_page( 1, Slider =>
origin => [ 100, 10],
size => [ 270, 56],
min => 1,
max => 10,
name => 'LineWidth',
scheme => ss::Gauge,
snap => 1,
increment => 1,
step => 1,
onChange => sub {
unless ( $nbpages-> {deprecate}) {
my $widths = $dlg-> {page2}-> {widths};
$$widths[ $nbpages-> NameSel-> focusedItem] = $_[0]-> value;
}
},
);
my $s2 = $nb-> insert_to_page( 1, Label =>
origin => [ 10, 10],
size => [ 90, 56],
text => "Line ~width\n[Alt + - and 1-9]",
focusLink => $s1,
autoWidth => 0,
valignment => ta::Center,
wordWrap => 1,
);
my $delta = $nbpages-> LineWidth-> top;
for ( $nbpages-> widgets_from_page(1)) {
next if $_ == $s1 || $_ == $s2;
$_-> bottom( $_-> bottom + $delta);
}
my $namesel = $nbpages-> NameSel;
$namesel-> set( onChange => sub {
$nbpages-> {deprecate} = 1;
$nbpages-> LineWidth-> value( $dlg-> {page2}-> {widths}-> [ $_[0]-> focusedItem]);
$nbpages-> {deprecate} = undef;
});
}
my %widcolors = ( Features => 1, Background => 1, Remove => 1);
sub opt_proppush
{
my ( $w, $dlg, $nb, $nbpages) = @_;
$w-> SUPER::opt_proppush( $dlg, $nb, $nbpages);
my $nbc = $nbpages-> pageIndex;
$nbpages-> pageIndex(3);
for ( qw( CalcBrightness EqualBrightness CalcConvex CalcHoles)) {
$nbpages->bring($_)->checked( $w->{ini}->{$_});
}
$nbpages-> CalcBrightness-> notify(q(Check)); # force dependent disablements
$nbpages-> CalcHoles-> notify(q(Check));
for ( qw( HolesPercent NumberOfRotations)) {
$nbpages->bring($_)->value( $w->{ini}->{$_});
}
$nbpages-> pageIndex( $nbc);
$dlg->{page3}->{NumberOfRotations} = $w->{ini}->{NumberOfRotations};
my $i = 0;
my %colors = %{$w-> opt_colors};
my %ids = map { ( $_ , $i++ ) } keys %colors;
my @widths = (1) x scalar keys %colors;
$widths[$ids{Features}] = $w-> {ini}-> {LW0};
$widths[$ids{Background}] = $w-> {ini}-> {LW1};
$widths[$ids{Remove}] = $w-> {ini}-> {LW2};
$dlg-> {page2}-> {widths} = \@widths;
$nbpages-> LineWidth-> value( $widths[ $nbpages-> NameSel-> focusedItem]);
$nbpages-> FrameWidth-> value( $w-> {ini}-> {FrameWidth});
$nbpages-> FrameColor-> index( $w-> {ini}-> {FrameColor} ? 1 : 0);
}
sub opt_proppop
{
my ( $w, $dlg, $nb, $nbpages, $mr) = @_;
$w-> SUPER::opt_proppop( $dlg, $nb, $nbpages, $mr);
if ( $mr) {
for ( qw( EqualBrightness CalcBrightness CalcConvex CalcHoles)) {
$w->{ini}->{$_} = $nbpages-> bring($_)-> checked;
}
for ( qw( HolesPercent NumberOfRotations)) {
$w->{ini}->{$_} = $nbpages-> bring($_)-> value;
}
my $i = 0;
my %colors = %{$w-> opt_colors};
my %ids = map { ( $_ , $i++ ) } keys %colors;
$w-> {ini}-> {LW0} = $dlg-> {page2}-> {widths}-> [$ids{Features}];
$w-> {ini}-> {LW1} = $dlg-> {page2}-> {widths}-> [$ids{Background}];
$w-> {ini}-> {LW2} = $dlg-> {page2}-> {widths}-> [$ids{Remove}];
init_convex( $w->{ini}->{NumberOfRotations}) if
$w->{ini}->{NumberOfRotations} != $dlg->{page3}->{NumberOfRotations};
my @v = ( $nbpages-> FrameWidth-> value, $nbpages-> FrameColor-> index ? 1 : 0);
if ( $v[0] != $w-> {ini}-> {FrameWidth} || $v[1] != $w-> {ini}-> {FrameColor}) {
$w-> {ini}-> {FrameWidth} = $v[0];
$w-> {ini}-> {FrameColor} = $v[1];
$w-> win_loadfile( $w-> {file});
}
}
}
# OPT_END
# PT
sub pt_lines
{
return $_[0]-> {lineStorage}->[$_[0]->{currentSet}];
}
sub pt_lines_ptr
{
return \$_[0]-> {lineStorage}->[$_[0]->{currentSet}];
}
sub pt_lw
{
return $_[0]-> {lwStorage}->[$_[0]->{currentSet}];
}
sub pt_lw_ptr
{
return \$_[0]-> {lwStorage}->[$_[0]->{currentSet}];
}
sub pt_init
{
$_[0]-> pt_clear_all();
}
sub pt_undo1
{
my $w = $_[0];
$w-> iv_cancelmode( $w-> IV);
return unless defined $w-> pt_lines;
bin/MorphometryI view on Meta::CPAN
sub pt_clear
{
my $w = $_[0];
${$w-> pt_lines_ptr()} = undef;
${$w-> pt_lw_ptr()} = undef;
for ( qw( Undo1 Undo2 Undo3)) {
$w-> menu-> action( $_, sub{});
$w-> menu-> disable( $_);
}
}
sub pt_clear_all
{
my $w = $_[0];
$w-> pt_clear;
my $sc = scalar @{$w->{setColors}};
$w-> {lineStorage} = [];
$w-> {lwStorage} = [];
while ( $sc--) {
push( @{$w-> {lineStorage}}, undef);
push( @{$w-> {lwStorage}}, undef);
}
}
# PT_END
# RPT
sub rpt_toggle
{
my ( $w, $x, $y) = @_;
$w-> {points} = [] unless defined $w-> {points};
$w = $w->{points};
my $i = 0;
my $found = undef;
for ( $i = 0; $i < scalar @$w; $i+=2) {
my ( $ax, $ay) = @$w[$i,$i+1];
$found = $i, last if abs( $ax - $x) < $App::PLab::ImageAppWindow::pointClickTolerance &&
abs( $ay - $y) < $App::PLab::ImageAppWindow::pointClickTolerance;
}
defined $found ? splice( @$w, $i, 2) : push( @$w, $x, $y);
return !defined $found;
}
sub rpt_clear
{
$_[0]-> {points} = undef;
}
sub rptex_clear
{
$_[0]-> {extraPoints} = undef;
}
# RPT_END
# IV
sub IV_MouseDown
{
my ( $w, $self, $btn, $mod, $x, $y) = @_;
$w-> SUPER::IV_MouseDown( $self, $btn, $mod, $x, $y);
return unless $self-> eventFlag;
$self-> clear_event, return if $btn != mb::Left;
if ($self->{transaction}) {
if ( $self->{transaction} == 2) {
my ( $ax, $ay) = $self-> screen2point( $x, $y);
$self-> {transaction} = 1;
$w-> pt_add( $ax, $ay);
$w-> sb_text( "Freehand: $ax $ay");
$w-> modified( 1);
$self-> repaint;
}
$self-> clear_event;
return;
}
unless ( $self->{drawmode}) {
my ( $ax, $ay) = $self-> screen2point( $x, $y);
if ( $w-> rpt_toggle( $ax, $ay)) {
$self-> begin_paint;
$self-> color( $w->{pointColor});
my $p = ( 6 * $self-> zoom < 1) ? 1 : ( 6 * $self-> zoom);
$self-> fill_ellipse( $x, $y, $p, $p);
$self-> end_paint;
$w-> sb_text( "New reference point: $ax $ay");
} else {
my $p = ( 32 * $self-> zoom < 1) ? 1 : ( 32 * $self-> zoom);
$self-> invalidate_rect( $x - $p, $y - $p, $x + $p, $y + $p);
$w-> sb_text( "Reference point deleted: $ax $ay");
}
$w-> modified( 1);
$self-> clear_event;
return;
}
{
#starting freehand session
$w-> iv_entermode( $self, 1);
$w-> pt_start;
my ( $ax, $ay) = $self-> screen2point( $x, $y);
$w-> pt_add( $ax, $ay);
$w-> modified( 1);
$w-> sb_text( "Freehand: $ax $ay");
}
$self-> clear_event;
}
sub IV_MouseClick
{
my ( $w, $self, $btn, $mod, $x, $y, $dbl) = @_;
if ( $btn == mb::Right and ( $self-> {transaction})) {
$w-> iv_cancelmode( $self) if $self-> {transaction} == 2;
$self-> clear_event;
return;
}
}
sub IV_MouseUp
{
my ( $w, $self, $btn, $mod, $x, $y) = @_;
return unless $self->{transaction};
$w-> SUPER::IV_MouseUp( $self, $btn, $mod, $x, $y);
return unless $self-> eventFlag;
if ( $btn == mb::Left and $self-> {transaction} == 1) {
$self-> {transaction} = 2;
$self-> {xors} = undef;
$w-> sb_text("Lineplot:");
$self-> clear_event;
}
}
sub IV_MouseMove
{
my ( $w, $self, $mod, $x, $y) = @_;
unless ( $self->{transaction}) {
if (( $mod & km::Shift) && defined $self-> image) {
my $i = $self-> image;
my $pix = $i-> pixel( $self-> screen2point( $x, $y));
$w-> sb_text((( $i-> type & im::BPP) > 8) ?
sprintf("%02x %02x %02x", ($pix>>16)&0xFF, ($pix>>8)&0xFF, $pix&0xFF) :
$pix
) if $pix != cl::Invalid;
}
}
$w-> SUPER::IV_MouseMove( $self, $mod, $x, $y);
return unless $self-> eventFlag && $self-> {transaction};
if ( $self-> {transaction} == 1) {
my ( $x1, $y1) = $self-> point2screen( @{$w-> pt_lines->[-1]}[-2,-1]);
$w-> pt_add( $self-> screen2point( $x, $y));
$self-> begin_paint;
$self-> color( $w-> {ini}-> {$w->{setColors}->[$w->{currentSet}]});
$self-> lineWidth( $self-> zoom * $w-> {ini}-> {'LW'.$w->{currentSet}});
$self-> line( $x, $y, $x1, $y1);
$self-> end_paint;
$w-> sb_text("Freehand: $x1 $y1");
} elsif ( $self-> {transaction} == 2) {
my ( $ax, $ay) = $self-> point2screen( @{$w-> pt_lines->[-1]}[-2,-1]);
$self-> begin_paint;
$self-> color( cl::White);
$self-> rop( rop::XorPut);
$self-> linePattern( lp::Dot);
$self-> line( $ax, $ay, @{$self->{xors}}) if defined $self->{xors};
$self-> line( $ax, $ay, $x, $y);
$self-> {xors} = [$x, $y];
$self-> end_paint;
my ( $x1, $y1) = $self-> screen2point( $x, $y);
$w-> sb_text("Lineplot: $x1 $y1");
}
}
sub IV_Paint
{
my ( $w, $self, $canvas) = @_;
$self-> on_paint( $canvas);
my $wl = $w-> {lineStorage};
$canvas-> translate( $self-> point2screen( 0, 0));
my $z = $self-> zoom;
my $p = ( 6 * $z < 1) ? 1 : ( 6 * $z);
if ( defined $wl) {
my $i;
for ( $i = 0; $i < scalar @{$w->{setColors}}; $i++) {
my $wwl = $w->{lineStorage}->[$i];
my $wwlw = $w->{lwStorage}->[$i];
next unless defined $wwl;
$canvas-> color( $w-> {ini}-> {$w->{setColors}->[$i]});
my $j;
my $lastLW = 0;
for ( $j = 0; $j < @$wwl; $j++) {
my @x = map { $_ * $z } @{$$wwl[$j]};
$canvas-> lineWidth( $$wwlw[$j] * $z), $lastLW = $$wwlw[$j] if $lastLW != $$wwlw[$j];
$canvas-> polyline( \@x);
}
}
}
$wl = $w-> {points};
if ( defined $wl) {
my $i;
$canvas-> color( $w->{pointColor});
for ( $i = 0; $i < scalar @$wl; $i+=2) {
my ( $x, $y) = @$wl[ $i, $i+1];
$canvas-> fill_ellipse( $x * $z, $y * $z, $p, $p);
}
}
$wl = $w-> {extraPoints};
if ( defined $wl) {
my $i;
$canvas-> color( $w->{pointColor});
$canvas-> lineWidth( $z);
for ( $i = 0; $i < scalar @$wl; $i+=2) {
my ( $x, $y) = @$wl[ $i, $i+1];
$canvas-> line( $x * $z - $p, $y * $z - $p, $x * $z + $p, $y * $z + $p);
$canvas-> line( $x * $z + $p, $y * $z - $p, $x * $z - $p, $y * $z + $p);
}
}
}
sub iv_cancelmode
{
my ( $w, $self) = @_;
my $t = $self->{transaction};
$w-> SUPER::iv_cancelmode( $self);
$w-> pt_close() if $t;
}
sub iv_togglemode
{
my ( $w, $self) = @_;
return if !$ImageApp::testing and !defined $self-> image;
$w-> iv_cancelmode( $self);
$self-> {drawmode} = defined $self-> {drawmode} ? undef : 1;
$w-> ToolBar-> Contours-> checked( defined $self-> {drawmode});
$w-> sb_text( defined $self-> {drawmode} ? "Drawing mode on - Esc or right button to cancel" : "Reference point mode on");
}
# IV_END
package PropRollup;
use vars qw(@ISA);
@ISA = qw(Prima::Dialog);
sub profile_default
{
my $def = $_[ 0]-> SUPER::profile_default;
my %prf = (
borderIcons => bi::SystemMenu | bi::TitleBar,
width => 207,
height => 306,
sizeDontCare => 0,
text => 'Parameters',
visible => 0,
);
@$def{keys %prf} = values %prf;
return $def;
}
sub init
{
my $self = shift;
my %profile = $self-> SUPER::init(@_);
my $image = Prima::Icon->create( width=>16, height=>16, type => im::bpp1,
palette => [ 0,0,0,0,0,0],
data =>
"\x01\x00\x00\x00A\x08\x00\x00\!\x10\x00\x00\x10 \x00\x00\x07\xc0\x00\x00".
"\x080\x00\x001\x88\x00\x00C\xc0\x00\x00\x03\xc4\x00\x00\!\x88\x00\x00".
"\x18p\x00\x00\x07\x80\x00\x00\x10\x10\x00\x00\!\x08\x00\x00A\x04\x00\x00".
"\x01\x00\x00\x00".
'');
my $w = $self-> owner;
my $i = $w-> IV-> image;
my @sz = defined $i ? $i-> size : (0,0);
my $canApply = defined $i && $i-> type == im::Byte;
$self-> insert(
[ Label =>
origin => [ 5, 280],
name => 'UF',
size => [ 148, 20],
text => 'Union ~find threshold',
],[ SpinEdit =>
origin => [ 5, 255],
name => 'Union',
size => [ 148, 20],
min => 1,
value => $w-> {ini}-> {UFThreshold},
max => 255,
],[ Label =>
origin => [ 5, 230],
name => 'BT',
size => [ 148, 20],
text => '~Binary threshold',
],[ SpinEdit =>
origin => [ 5, 205],
name => 'Binary',
size => [ 148, 20],
min => 0,
value => $w-> {ini}-> {BinThreshold},
max => 255,
],[ Label =>
origin => [ 5, 180],
name => 'ES',
size => [ 148, 20],
text => '~Edge size',
],[ SpinEdit =>
origin => [ 5, 155],
name => 'Edge',
size => [ 148, 20],
value => $w-> {ini}-> {EdgeSize},
min => 1,
max => defined $i ? ( int(($sz[0] < $sz[1] ? $sz[0] : $sz[1]) / 2)) : 16383,
],[ Label =>
origin => [ 5, 130],
name => 'MIN',
size => [ 148, 20],
text => 'Mi~n area',
],[ SpinEdit =>
origin => [ 5, 105],
bin/MorphometryI view on Meta::CPAN
$w-> win_leavesubplace(
Prima::IPA::Point::threshold(
$im,
minvalue => 0,
maxvalue => $self-> Binary-> value,
));
},
],[ SpeedButton =>
origin => [ 164, 54],
name => 'Preview3',
size => [ 36, 120],
image => $image,
enabled => $canApply,
hint => 'Previews all methods',
onClick => sub {
my $im = Prima::IPA::Local::unionFind(
$w-> win_entersubplace,
method => 'ave',
threshold => $self-> Union-> value);
$im = Prima::IPA::Point::threshold(
$im,
minvalue => 0,
maxvalue => $self-> Binary-> value);
$im = Prima::IPA::Global::fill_holes( $im,
edgeSize => $self-> Edge-> value,
);
$im = Prima::IPA::Global::area_filter( $im,
edgeSize => $self-> Edge-> value,
minArea => $self-> Min-> value,
maxArea => $self-> Max-> value,
);
$w-> win_leavesubplace( $im);
},
],);
my @p = split( ' ', $w->{ini}->{RecWindowPos});
my @as = $::application-> size;
my @ss = $self-> size;
for ( 0..1) {
$p[$_] = 100 unless defined $p[$_];
$p[$_] = 0 if $p[$_] < -$ss[$_] + 100;
$p[$_] = $as[$_] - $ss[$_] - 30 if $p[$_] > $as[$_] - $ss[$_] - 30;
}
$self-> origin( @p);
$self-> visible(1);
return %profile;
}
sub cleanup
{
my $self = $_[0];
my $w = $self-> owner;
$w-> {recWindow} = undef;
my $i = $w-> {ini};
$i-> {RecWindowPos} = join( ' ', $self-> origin);
$i-> {UFThreshold} = $self-> Union-> value;
$i-> {BinThreshold} = $self-> Binary-> value;
$i-> {EdgeSize} = $self-> Edge-> value;
$i-> {MinArea} = $self-> Min-> value;
$i-> {MaxArea} = $self-> Max-> value;
$self-> SUPER::cleanup();
}
package Run;
my $wfil = App::PLab::ImageAppWindow::winmenu_file();
splice( @{$$wfil[1]}, -2, 0,
[],
[ EditImport => "~Import contours" => q(win_importextras)],
[ '-EditOptCalib' => "~Recalculate series" => q(opt_changecalib)],
[ EditCalcStats => "~Calculate statistics" => q(opt_statistics)],
);
my $wedt = App::PLab::ImageAppWindow::winmenu_edit();
splice( @{$$wedt[2]}, 0, 0,
[ '-Undo1' => "~Undo drawing" => "BkSp" => kb::Backspace , sub {},],
[ '-Undo2' => "~Group undo" => "Alt+BkSp" => km::Alt|kb::Backspace , sub {},],
[ '-Undo3' => "Undo ~dialog" => "Alt+U" => '@U' => sub {},],
[ EditClearAll => "Clear all ~drawings" => sub {
$_[0]-> iv_cancelmode( $_[0]-> IV);
$_[0]-> pt_clear;
$_[0]-> IV-> repaint;
$_[0]-> modified( 1);
}, ],
[ EditRemovePoints => "Clear all ~points" => sub {
$_[0]-> rpt_clear;
$_[0]-> IV-> repaint;
$_[0]-> modified( 1);
}, ],
[],
[ '-EditToggleMode' => "~Toggle points <-> drawings" => 'F11'=>'F11' => sub { $_[0]-> iv_cancelmode( $_[0]-> IV); $_[0]-> iv_togglemode( $_[0]-> IV)}],
[],
[ 'EditInvertImage' => '~Invert image' => sub { $_[0]-> win_set_negative( $_[0]-> {ini}-> {InvertImage} ? 0 : 1); } ],
[ '-EditValidate' => "~Validate contours" => 'Ctrl+Enter'=> km::Ctrl|kb::Enter ,
sub { $_[0]-> win_validate(0) }],
[ EditRecSetup => "Recognition ~setup" => sub { $_[0]-> win_showrec; }, ],
[ '-EditApplyContours' => "~Apply contours" => 'Alt+Enter'=> km::Alt|kb::Enter , q(win_applycontours)],
[],
[ 'EditHack' => "~Outline convex ~hull" => q(win_outline_convex_hull)],
);
my $w = MorphoWindow-> create(
visible => 0,
menuItems => [
$wfil,
$wedt,
App::PLab::ImageAppWindow::winmenu_view(),
[],["~Help" => [
[ HelpAbout => "~About" => sub {Prima::MsgBox::message("PLab application series, Morphometry I, version $App::PLab::VERSION", mb::OK|mb::Information)}],
[ HelpPlabApps => "~PLab Apps" => sub { $_[0]-> open_help(); }],
[ HelpContents => "~Contents" => sub { $_[0]-> open_help("MorphometryI"); }],
]],
],
accelItems => [
( map {[ "lw$_" => $_ => "Alt+$_" => "\@$_" => q(win_objectlwmenuaction)]} 1..9),
],
);
$w-> IV-> delegations(['MouseClick', 'Paint']);
$w-> sb_text("Started OK");
$w-> visible(1);
( run in 0.903 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )