Closed ozett closed 8 years ago
Well, the limitation there is not something you'd be care of. Any GIF file that can be opened with PILlow is supported. This project is FOR the animated gif, obviously it supports them.
http://pillow.readthedocs.io/en/3.2.x/handbook/image-file-formats.html Here says it supports both 87a and 89a.
cool. i tried, but... have a raspberry pi2, fresh raspian from today (2016-05-27-raspbian-jessie.img), cloned github, tried to run fb.py...but errors
root@raspberrypi:/usr/src/FBpyGIF# ./fb.py from: can't read /var/mail/mmap from: can't read /var/mail/ioctl ./fb.py: Zeile 139: import: Kommando nicht gefunden. ./fb.py: Zeile 141: mm: Kommando nicht gefunden. ./fb.py: Zeile 142: bpp,: Kommando nicht gefunden. ./fb.py: Zeile 143: vi,: Kommando nicht gefunden. ./fb.py: Zeile 144: _fb_cmap: Kommando nicht gefunden. ./fb.py: Zeile 146: Syntaxfehler beim unerwarteten Wort
(' ./fb.py: Zeile 146:
def ready_fb(_bpp = 24, i = 0):'
installed python-pil on default python 2.7, but still this errors.... what to do? thaaaanks..
tried as user "pi", but...
pi@raspberrypi:/usr/src/FBpyGIF $ python fb.py Traceback (most recent call last): File "fb.py", line 138, in
from ioctl import * ImportError: No module named ioctl pi@raspberrypi:/usr/src/FBpyGIF $
It's made for py3. Try with sudo python3 fb.py test.gif
. Writing to fb driver needs super user privileges.
cool. fastest reply ever. thhaaaanks. i will try. (may you add this at prominent place to the readme.md here?)
Okay, I will. Thanks for feedbacks.
ohhh. whats wrong...
tried with gif on cmd-line, still ioctl error ..
Pil missing for python3 ...just a guess...?
It has to be from fcntl import *
instead of from ioctl import *
i changed it. no error in terminal. looks better. you update github-code? i go check on my screen on the raspberry in another room. thanks so far :smile:
Yup, did it right now. Thanks for noticing.
my plan did not work... i wanted to build a picture frame with 1980x1020, so i rotated my raspberry screen with 90 degrees. i quickly tried two of my gifs, but i did not worked... i assumed i would be succesfull, even if i rotated the screen ... or am i wrong ..?
You mean, FHD screen in vertical with 1080*1920 pixels resolution?
I never tried it by my self but in ready_fb
function, there's two ioctl
commands with FBIOGET_VSCREENINFO
and FBIOPUT_VSCREENINFO
flags which tries to get screen info and set back after some modifications.
You could try to force set its resolution settings to what you want by vi[:4] = 1080, 1920, 1080, 1920
.
yes. rotated FHD 90 degree in /boot/config.txt
where do i set this options? cmd-line? or inside fb.py?
It's inside the fb.py
, line around 158.
Wait a minute.. I guess your image is not having the same resolution as screen. There'e a way to force resizing it.. I'll push it soon.
cool...maybe autoresize to width/height... if youre on this... :smiley:
I've pushed the auto resizing version but it seems to be working in horizontal mode only.
Rotating with pillow function .rotate(90)
would do the work by now..
I'll add auto rotating by reading angle info from ioctl. Please wait more..
It looks like the frame buffer driver doesn't know if the screen is rotated or not. I'll try other ways..
Oh.. I found how to do it. Will push the code soon.
Updated the code. Done a test in rotated mode. 640d3adc135977b26f57b7c05b2d55616d26b7e3
Fantastic! i will post a picture in a minute... meanwhile you coded i tried different ways to achieve a picture frame...
tried "mirage" (with autosize) on raspberry with x, tried fbi (no animated gif) on FB, googled, rotated my 800x480 panel..
but now i looks awesome on the 1920x1080 display in 90 degree rotation and autosize...!
:santa: does it load all images from a directory... ??? :santa:
FANTASTIC! thanks!
found the image here (animated gif, the eyes blink from time to time): http://headlikeanorange.tumblr.com/archive
Happy for you!
After doing the same things, made this script.
That's why I think it's the only program suitable for an animated raspberry pi kiosk.
You can use os.path
python default library for that.
I'll update that too.
4abb93c5abb3c9eeeacd6773e1b153a8dd13d82f
This update will scan a directory and play all images under it.
sudo python3 fb.py [directory or file] [delay seconds for static images=30]
sudo python3 fb.py
will just clear screen.
i had to look at the picture quality, the resizing is fantastic good. i had a comparison to other viewers, but the 500x700 animated gifs looks amazing good on 1080x1920. Realy Great!
i will give your update another try (ofter my first coffee).. 1) i thought, if i can mix the animated gifs with some .jpegs from my family-album? do you want support (or is it already in?) some other file fomats for a expanded picture frame? 2) it suits my needs for autoresize and auto-center, but what if another one wants original-size and displaying at left-corner/right-corner... :smile_cat:
(by the way, i tried "info-beamer" as a kiosk-displayer on raspberry with my rtsp-cams. it is promising..)
It does already support other file formats including jpg, png, bmp. Full list is again, the same as the PILlow library has. You'll be surprised how many this library supports. Some other mature features are not in the scope of this project.. This project is providing a library, not an program. Which means it's only showing an way how it can be done. Much complex features like playlist, network synchronization, user configuration, head-up displays are what I've done in a bigger close source project. You can take this sources and try to build it by yourself at no cost, at anytime.
ok, i will see how far i can come with this, as i am no developer..
a the moment i tried to give the directory option with a 20 second delay. i have a mix of animated and static gifs in the directory. the static gifs stay 20 seconds, the animated gifs show only 2-3 sek. animation, than the gif changed to the next. is this the default, or something what comes from the mixtures of static/animation and is intended?
Everyone becomes coding hobbyist in such way... :)
It simply reads delay information of each frame from the gif file itself by cut.info['duration']
.
Which means that 2-3 seconds are just as the gif artist expected to be as the entire playtime.
ok, i understand.... may "you" want at last make the x-second delay for static images a global delay (also looping the gifs)? if you intend not to change the code again, i will see if i understand anything of you python to do i as a bloody hobbiist :sweat_smile: anyway, the library is super! :thumbsup:
I deeply understand that this program is yet the only way to do things like this. I'm simply too busy to make other "crazier" things.. When I have some free time, I'll consider to add such features. What you've asked needs several steps of works and quite personal need it is.. Thus I'll give you a snippet, instead of an updating.
...
from threading import Event, Timer
e=Event()
try:
for fpath in cycle(fpaths):
if fpath[-4:].lower() == '.gif':
Timer(DELAY, lambda e:e.set(), [e]).start()
gif_loop(ready_img(fpath), e, True)
e.clear()
else:
...
Yeah, gif_loop
function was already in ready for this work.
ok, nevertheless thanks for all help. great! :satisfied: i'll have a look after a strong coffee..and try to fiddle around... :boom:
i am forced to look at it later at night, the kids love the animals looping ...
there is room to experiment.... :thought_balloon: i tried to overlay the animated gif with an rtsp-stream from my webcams. it worked
omxplayer --layer -2 --adev local -n 1 --win '370 50 722 248'--stats --vol 0 --video_queue 10 --timeout 30 rtsp://192.168.14.103:554/ch0_1.h264
now i can push an videostream over the pictureframe in case on motion-detection sensors or on the alarm-events from motion-detection on my grandstream videocams.
cooooooolllll :+1:
What an amazing father you are!
Thanks for sharing your experiences.
Yes you can mix up videos and web pages, sensors, etc. Welcome to the world of IoT.
When I have time, I'll first try to reduce loading terms between gif animations.
RGB_to_BGR
is just taking up too many time to.
Please feel free to do any experiment you want.
i was motivated with this wonderfull results to test it a bit more...
here you can (not really in motion) see, that there is an semitransparent letter-animation of info-beamer running over the animated gif with your python library, and also semitransparent on another layer in there the realtime movie-stream from my webcams (which is currently an experimentyl feature in info-beamer) all running on my 480x800 panel, means rotatet 90 degree .... FANTASTIC! (but lots of work to come to realize all ideas...) :laughing:
looping with bash not working...i am not experienced enough in python..need help?
i tried to overcome changing the fb.py by scripting a bash-loop:
#!/bin/bash
while true
do
animation=$(/bin/ls /home/pi/Pictures/ | /usr/bin/shuf -n 1)
echo "File: $animation"
export animation=$animation
/usr/bin/python3 /usr/src/FBpyGIF/fb.py "/home/pi/Picures/${animation}"
sleep 200s
done
but the file-name not gets passed to the python script. i changed fb.py to debug, but the right count of args is passed from bash. and iserted this:
#debug args
# Get the arguments list
cmdargs = str(argv)
# Print it
#print ("The total numbers of args passed to the script: %d " % total)
print ("Args list: %s " % cmdargs)
i must be something with the dir/filename recognition.. i am lost ..
it is all ok, if i do it in bash-cmd line.
root@raspberrypi:/home/pi# python3 /usr/src/FBpyGIF/fb.py /home/pi/Pictures/tumblr_nz385enEIC1rc3rlfo1_1280.jpg
Args list: ['/usr/src/FBpyGIF/fb.py', '/home/pi/Pictures/tumblr_nz385enEIC1rc3rlfo1_1280.jpg']
you can manually set delay for non-animated files by 2nd argument (seconds)
files to play: ['/home/pi/Pictures/tumblr_nz385enEIC1rc3rlfo1_1280.jpg']
and from the script:
root@raspberrypi:/home/pi# ./display.sh
File: tumblr_mmj673VFUL1r4zr2vo2_r2_500.gif
Args list: ['/usr/src/FBpyGIF/fb.py', '/home/pi/Picures/tumblr_mmj673VFUL1r4zr2vo2_r2_500.gif']
you can manually set delay for non-animated files by 2nd argument (seconds)
files to play: []
Oh my..
My code also has infinite loop code and it would be much easier to learn some python and modify that loop than using shell script.. Because the Python is a good replacement for shell scripts.
for fpath in cycle(fpaths):
makes infinite loop iterator with fpaths
list.
So.. why are you making it with bash again?
So.. you wanna shuffle around?
How about changing for fpath in cycle(fpaths):
to
from random import shuffle
while True:
shuffle(fpaths)
for fpath in fpaths:
You'll need to take care of other indents of lines below.
i now "must" dive into python...because i cannot make it work. my (horrible noob) debuging
root@raspberrypi:/home/pi# ./display.sh
File: tumblr_n0wh4dIl3i1r4zr2vo1_500.gif
Args list: ['/usr/src/FBpyGIF/fb.py', '/home/pi/Picures/tumblr_n0wh4dIl3i1r4zr2vo1_500.gif', '44']
args length: 3
file/dir: /home/pi/Picures/tumblr_n0wh4dIl3i1r4zr2vo1_500.gif
debug: reclist started
debug.reclist: no dir/no file /home/pi/Picures/tumblr_n0wh4dIl3i1r4zr2vo1_500.gif
files to play: []
the check for "isdir(path/file)" in rec_list_dir function seems to work different from cmd-line than from bash-script. (i googled something about absoulte-path...??)
i will look up your hints for python on this rainy sunday... thanks a lot (up to now) :smile:
never give up on the looping animals... :smile_cat:
heavy to jump up from nothing to python threading... as far as i understand your code, the "gif_loop" loops endless for showing the animated gif. if i want this to stop after DELAY, i thing at the moment, i have to wrap this in an own event with timer. i have no experience in python coding, so i dont see another way... and ...i ....jump ...
oho, heavy stuff: "tuple unpacking" for looping an animal: http://stackoverflow.com/questions/10867882/tuple-unpacking-in-for-loops :smiling_imp:
That e
in loop is actually not doing anything. It's left over of other threading experiment.
The code snippet I wrote for you is the only part needs to be changed for letting DELAY applied to every images. Already done a test that it works fine. Here's entire end of the working code.
def gif_loop(gif, event=None, force_loop=False):
from threading import Thread, Event, Timer
from itertools import cycle
ready_fb()
imgs = ready_gif(gif)
for img, dur in cycle(imgs) if force_loop else imgs:
e=Event()
Timer(dur, lambda e:e.set(), [e]).start()
show_img(img)
e.wait() # wait for animation frame duration
if event and event.is_set():
break
if event: event.clear()
def rec_list_dir(path):
from os.path import isdir, isfile
from imghdr import what
if isdir(path):
from os import listdir
from os.path import join
rst = []
for f in listdir(path):
rst += rec_list_dir(join(path, f))
return rst
elif isfile(path) and what(path):
return [path]
return []
if __name__ == '__main__':
from sys import argv
if len(argv) == 1:
ready_fb()
black_scr()
exit()
if len(argv)<3:
DELAY=30
print('you can manually set delay for non-animated files by 2nd argument (seconds)')
else:
DELAY=int(argv[2])
fpaths = rec_list_dir(argv[1])
print('files to play:', fpaths)
from itertools import cycle
from time import sleep
from threading import Event, Timer
e=Event()
try:
for fpath in cycle(fpaths):
if fpath[-4:].lower() == '.gif':
Timer(DELAY, lambda e:e.set(), [e]).start()
gif_loop(ready_img(fpath), e, True)
e.clear()
else:
ready_fb()
show_img(RGB_to_BGR(ready_img(fpath).convert('RGB').resize((w,h))))
sleep(DELAY)
except KeyboardInterrupt:
e.clear() # stop gif loop
finally:
#e.wait() # wait for thread end
black_scr()
And ran sudo python3 fb.py gif
to read all image files in gif directory.
again, i am thankful again. really. not only for the code, but for pushing me investigating the inner workings of python language. i start with tuples, threading and callbacks. i suprised myself, what i can google in one day :innocent: i thought of giving up during the day, but... it was interesting enough to stay on..
i had some ideas for later years, but do you considered (i did not really look it up in the code) to use layers? i can set info-beamer Frambuffer output on different layers, also omxplayer too. is it possible with your python-library? :see_no_evil:
thanks for the code, i will put in in my ugly testing-fragments tomorrow, to get it clean and fantastic again. :thumbsup:
sometimes i start with random images that way, but that is my past. no i am a developer :punch:
python3 fb.py $(ls /home/pi/Pictures/*.gif | shuf -n 1)
But your code won't shuffle again after a loop..?! While what I suggested will do. Layers aren't something considered but you made me consider now.. It probably would be able to be done with another ioctl.. As soon as I finish my work, I'll keep track on them too..
yes, your right. my shell workaround only picked one gif by random. it was just for the record. the task had been to heavy, to become a great python-dev like you from out of nothing...:wink:
if you are interested, i can show my trigger for overlaying the picture frame. i use a simple cgi-bin listener for the build-in motion-detection of my grandstream videoconverter. the grandstream calls the cgi on motion, and i show with omxplayer an rtsp-stream as overlay. could all be build in one python, i guess. would be perfect elegant, but i have to learn python more..in holidays, maybe.
i stumbled again on my own mistake, may it could be helpful to check for python-version on start?
root@raspberrypi:/usr/src/FBpyGIF# ./fb.py
from: can't read /var/mail/mmap
from: can't read /var/mail/fcntl
./fb.py: Zeile 139: import: Kommando nicht gefunden.
./fb.py: Zeile 141: mm: Kommando nicht gefunden.
./fb.py: Zeile 142: bpp,: Kommando nicht gefunden.
./fb.py: Zeile 143: vi,: Kommando nicht gefunden.
./fb.py: Zeile 144: _fb_cmap: Kommando nicht gefunden.
./fb.py: Zeile 146: Syntaxfehler beim unerwarteten Wort `('
./fb.py: Zeile 146: `def ready_fb(_bpp = 24, i = 0):'
root@raspberrypi:/usr/src/FBpyGIF# python3 fb.py
Args list: ['fb.py']
args length: 1
root@raspberrypi:/usr/src/FBpyGIF#
img-type selection was also my fault... :smirk:
root@raspberrypi:/usr/src/FBpyGIF# python3 fb2.py /home/pi/Pictures/*.gif
Traceback (most recent call last):
File "fb2.py", line 297, in <module>
DELAY=int(argv[2])
ValueError: invalid literal for int() with base 10: '/home/pi/Pictures/tumblr_mh1h2nLnn01r4zr2vo1_500.gif'
root@raspberrypi:/usr/src/FBpyGIF# python3 fb2.py /home/pi/Pictures/*.gif 60
Traceback (most recent call last):
File "fb2.py", line 297, in <module>
DELAY=int(argv[2])
ValueError: invalid literal for int() with base 10: '/home/pi/Pictures/tumblr_mh1h2nLnn01r4zr2vo1_500.gif'
root@raspberrypi:/usr/src/FBpyGIF# python3 fb2.py /home/pi/Pictures/ 60
(by the way: i keep on listening here...all very promising...:blush:)
i used the same unchanged dir as before, with a mix of .jpg and animated.gifs, used your code, but got this error after the first .jpg showed correct:
Traceback (most recent call last):
File "fb2.py", line 308, in <module>
gif_loop(ready_img(fpath), e, True)
File "fb2.py", line 262, in gif_loop
imgs = ready_gif(gif)
NameError: name 'ready_gif' is not defined
means i cannot select *.gifs in the directory arg, and the shuffle needs diretories with only one filetype. i go again diving into python (day2)...:disappointed: (edit: i looked a little bit around, my guess is, the ready_gif routine was an addition and is missing?)
Oh right.. ready_gif
was missing. Here it goes.
I've been testing to parallelize converting process.. so this code is a little dirty.. Sorry about that.
def _ready_gif(cut):
return RGB_to_BGR(cut.convert('RGB').resize((w,h))).tobytes(), cut.info['duration']/1000
def ready_gif(gif):
from PIL import ImageSequence
#from multiprocessing import Pool
ready_fb()
imgs = []
for img in ImageSequence.Iterator(gif):
imgs.append(_ready_gif(img))#.copy())
#with Pool(4) as p:
#imgs=list(p.map(_ready_gif, imgs))
return imgs
Python version checking seems useful. I'll add it soon.
is there a limitation to the gif format? does it support animated gifs?
thanks