Porta-Retratos Digital Caseiro
Autor: forinti | Publicado: 2016-10-27T08:07:00-07:00

Os preços dos porta-retratos digitais estão começando a ficar interessantes, mas construir o próprio é mais divertido.

Usei um Raspberry Pi A+ (256MB de RAM e um ARM11 de 700MHz) com a última versão do Raspbian Jessie. Eu queria mesmo era usar um Raspberry Pi Zero (que custa apenas US$5), mas são muito procurados e ainda não apareceram na minha loja preferida.

Comecei muito otimista (como sempre) e tentei montar uma solução com HTML, Javascript, jQuery, transições, etc. Ela resultou ser muito pesada. Então, tentei em Tcl/Tk, mas manipular os tamanhos das imagens resultou ser muito trabalhoso (possível, mas trabalhoso).

Então, só me restou usar Perl. Foi preciso instalar dois pacotes: Tk e Imager.


sudo apt-get install perl-tk
sudo cpanm Imager



A interface é muito simples. Há um quadro grande com uma foto qualquer e uma foto pequena com a foto seguinte. A foto grande é escolhida aleatoriamente, mas a pequena é sempre a que segue (para haver uma relação entre elas). Além disso, exibo as horas e a data.


O script recebe um único parâmetro que indica o diretório onde as fotos são armazenadas. Ctrl+C suavemente encerra o programa.




Futuramente, espero exibir algo mais interessante no quadro das horas (a previsão do tempo ou as notícias).

#!/usr/bin/perl
use Tk;
use Tk::JPEG;
use Tk::Photo;
use Imager;
use File::Find;
use MIME::Base64;
use POSIX 'strftime';
use strict;

my @file_list;

find(\&amp;wanted, $ARGV[0]);

sub wanted {
    return unless -f;
    return unless /\.jpe?g$/i;
    push @file_list, $File::Find::name;
}

my $main = MainWindow-&gt;new (
  -title =&gt; 'PiFrame',
  -background =&gt; 'black'
);

my $w=$main-&gt;screenwidth();
my $h=$main-&gt;screenheight();
$main-&gt;overrideredirect(1);
$main-&gt;MoveToplevelWindow(0,0);
$main-&gt;geometry(join('x',$w,$h));

my $photo_width=int($w*3/4);
my $photo_height=$h;
my $thumb_width=$w-$photo_width;
my $thumb_height=int($h/3);

my $canvas=$main-&gt;Canvas(
  -width=&gt;$photo_width,
  -height=&gt;$h,
  -background=&gt;'black',
  -highlightthickness =&gt; 0);
$canvas-&gt;pack(-side=&gt;'left');

my $small_canvas=$main-&gt;Canvas(
  -width=&gt;$thumb_width,
  -height=&gt;$thumb_height,
  -background=&gt;'black',
  -highlightthickness =&gt; 0);
$small_canvas-&gt;pack(-side=&gt;'bottom');

my $time;

my $clock=$main-&gt;Label(
  -textvariable=&gt;\$time,
  -width=&gt;100,
  -height=&gt;100,
  -background=&gt;'black',
  -foreground=&gt;'white',
  -highlightthickness =&gt; 0,
  -font=&gt;'courier 40 bold');
$clock-&gt;pack(-side=&gt;'top');

my $photo=$canvas-&gt;Photo();
$canvas-&gt;createImage(0,0,-image=&gt;$photo,-anchor=&gt;'nw');
my $thumb=$small_canvas-&gt;Photo();
$small_canvas-&gt;createImage(0,0,-image=&gt;$thumb,-anchor=&gt;'nw');

sub scale {
  my ($width, $height, $image)=@_;
  my $scaled=$image-&gt;scale(xpixels=&gt;$width,ypixels=&gt;$height,type=&gt;'min');
  my $data;
  $scaled-&gt;write(data=&gt;\$data, type=&gt;'jpeg');
  return encode_base64($data)
}

my $image=Imager-&gt;new();

sub next_photo {
  my $index=int(rand($#file_list));
  my $filename=$file_list[$index];
  
  $image-&gt;open(file=&gt;$filename);
  $photo-&gt;configure(-data=&gt;scale($photo_width, $photo_height, $image));
  
  $filename=$file_list[($index+1)%($#file_list+1)];
  $image-&gt;open(file=&gt;$filename);
  $thumb-&gt;configure(-data=&gt;scale($thumb_width, $thumb_height, $image));
  
  $main-&gt;update();
}

$canvas-&gt;repeat(60000, sub {eval {next_photo()}});
$canvas-&gt;repeat(1000, sub {$time=strftime("%H:%M\n%A\n%d/%m", localtime)});

next_photo();

MainLoop;


O sistema operacional que usei para este projeto é o Raspbian com Pixel. As fotos estão armazenadas na pasta /data01/fotos. Então, adicionei a seguinte linha ao arquivo &nbsp;/home/pi/.config/lxsession/LXDE-pi/autostart para que o sistema inicie automaticamente:

@perl /home/pi/piframe.pl /data01/fotos/


O gasto de memória oscila entre 25MB e 50MB, o que cabe confortavelmente no espaço que o A+ oferece. Um Pi 3 talvez possa executar isso ao mesmo tempo que ofereça o serviço do Amazon Echo.