###########################################
package Camcap;
###########################################
use strict;
use warnings;
use Video::Capture::V4l;
use Imager;
use Imager::Misc;
use Log::Log4perl qw(:easy);

###########################################
sub new {
###########################################
    my($class, @options) = @_;

    my $self = {
        width   => 320,
        height  => 240,
        avg_opt => 128,
        avg_acc => 20,
        br_min  => 0,
        br_max  => 65535,
        @options,
    };

    $self->{video} = 
        Video::Capture::V4l->new() or
            LOGDIE "Open video failed: $!";

    bless $self, $class;
}

###########################################
sub cam_bright {
###########################################
    my($self, $brightness) = @_;

    my $pic = $self->{video}->picture();
    $pic->brightness($brightness);
    $pic->set();
}

###########################################
sub img_avg {
###########################################
  my($img) = @_;

  my $br = Imager::Misc::brightness($img);
  DEBUG "Brightness: $br";
  return $br;
}

###########################################
sub calibrate {
###########################################
  my($self) = @_;

  DEBUG "Calibrating";

  return if 
   img_avg($self->capture($self->{br_min}))
   > $self->{avg_opt};

  return if 
   img_avg($self->capture($self->{br_max}))
   < $self->{avg_opt};

      # Binary search
  my($low, $high) = ($self->{br_min}, 
                     $self->{br_max});

  for(my $max = 5; 
      $low <= $high && $max; 
      $max--) {
    my $try = int( ($low + $high) / 2);

    my $i  = $self->capture($try);
    my $br = img_avg($i);

    DEBUG "br=$try got avg=$br";
    return if abs($br-$self->{avg_opt}) <= 
              $self->{avg_acc};

    if($br < $self->{avg_opt}) {
        $low = $try + 1;
    } else {
        $high = $try - 1;
    }
  }
  # Nothing found, use last setting
}

###########################################
sub capture {
###########################################
    my($self, $br) = @_;

    $self->cam_bright($br) if defined $br;

    my $frame;
    for my $frameno (0, 1) {
       $frame = $self->{video}->capture(
              $frameno, $self->{width}, 
              $self->{height});

       $self->{video}->sync($frameno) or 
               LOGDIE "Unable to sync";
    }

    my $i = Imager->new();
    $frame = reverse $frame;
    $i->read(
      type => "pnm", 
      data => "P6\n$self->{width} " .
              "$self->{height}\n255\n" . 
              $frame
    );
    $i->flip(dir => "hv");
    return $i;
}

1;
