User avatar
sapnho
Posts: 244
Joined: Sun Sep 14, 2014 3:49 pm
Location: Frankfurt am Main
Contact: Website

Re: Image viewer with transition between images

Wed Apr 15, 2020 5:14 am

Hi Chris, glad you found the culprit!

I never use Textedit because there is always a risk that programs like this will add some special characters. I do all my editing in https://www.sublimetext.com/.
www.TheDigitalPictureFrame.com - Build a really great digital picture frame with the Raspberry Pi.
With lots of great tips from this forum.
Please submit your digital picture frame project to the user gallery here: bit.ly/2WkyjW1

satnerd
Posts: 9
Joined: Sun Oct 29, 2017 9:23 am

Re: Image viewer with transition between images

Tue May 12, 2020 11:15 am

Hi

I am writing a python class allowing me to retrieve weather information from openweathermap.org.
I also came across the erikflowers.github.io/weather-icons weather icons and I managed to
merge them with another font so I can display text and weather icons. In the end, I want to display weather information
on PictureFrame.py.

While using below block from PictureFrame.py, I noticed that sending a carriage return would not break lines as expected.

Code: Select all

textblock = pi3d.TextBlock(x=-DISPLAY.width * 0.5 + 50, y=-DISPLAY.height * 0.4,
                          z=0.1, rot=0.0, char_count=199,
                          text_format="{}".format(" "), size=0.99, 
                          spacing="F", space=0.02, colour=(1.0, 1.0, 1.0, 1.0))
text.add_text_block(textblock)
I then tried using pi3d.FixedString but this broke the beautiful blending implemented in /home/pi/pi3d_demos/PictureFrame.py

Proportional fonts (and particularly Thai fonts) are rendered with plenty of white space in between when using pi3d.TextBlock.

So I thought to myself, why not using
  • a: a Libreoffice template to do text formatting
  • b: substitute weather information in the template
  • c: generate a png using 'soffice --convert-to png'
  • d: and blend the png into the picture on display
Quick test shows no problem for task a...c., but I have no clue on how to best implement d.

I'd highly appreciate some code snippet for building this.

KR Beat

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Image viewer with transition between images

Tue May 12, 2020 12:43 pm

Hi, yes, carriage returns in the TextBlock/PointText system is still on the TODO list. The advantage of the TextBlock is that the characters can be moved around and changed very easily with little CPU load. Basically each character is an OpenGL point textured from a location on grid of characters- the font that you fed into PointText was basically 'just' an image filled with characters. FixedString basically is the same kind of image as the font but filled with the characters you supply it - so it ought to be capable of blending in just the same way. However there are some tricky aspects to do with blending and the sequence of drawing text and images that need to be sorted out. I will have a look at it now and get back to you.

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Image viewer with transition between images

Tue May 12, 2020 1:52 pm

Hi, this seems to work OK with text fading identical to PointText system

Code: Select all

...
sbg = None # slide for foreground
if nFi == 0:
  print('No files selected!')
  exit()
######################################################
# FixedString. If SHOW_NAMES is False then this is just used for no images message
text = pi3d.FixedString(config.FONT_FILE, "place-holder", justify="L")
flatsh = pi3d.Shader("uv_flat")
text.set_shader(flatsh)
text.sprite.position(x=-DISPLAY.width * 0.5 + 50, y=-DISPLAY.height * 0.4, z=0.1)
######################################################

num_run_through = 0
while DISPLAY.loop_running():
  tm = time.time()
....
          slide.unif[49] = 0.0
          kb_up = not kb_up
      # set the file name as the description
      if config.SHOW_NAMES:
######################################################
        raw_str = "THIS IS A STRING WITH {} EMBEDDED IN IT THAT WILL BE CHOPPED UP".format(
            tidy_name(iFiles[pic_num][0])).split(" ")
        new_str = [""]
        for w in raw_str:
          if len(new_str[-1]) > 20:
            new_str.append("")
          new_str[-1] = new_str[-1] + w + " "
        text = pi3d.FixedString(config.FONT_FILE, "\n".join(new_str), justify="L")
        text.set_shader(flatsh)
        text.sprite.position(x=-DISPLAY.width * 0.2, y=-DISPLAY.height * 0.3, z=0.1)
######################################################
    if config.KENBURNS:
      t_factor = nexttm - tm
...
    if a < 1.0: # transition is happening
      a += delta_alpha
      slide.unif[44] = a
      if config.SHOW_NAMES:
######################################################
        text.sprite.set_alpha(1.0 - abs(1.0 - 2.0 * a))
######################################################
    else: # no transition effect safe to resuffle etc
...
  else:
######################################################
    pass
######################################################

  text.draw()
I'm in the process of moving the great list of alternatives into a config (that also allows you to specify options on the command line) so that's why there are occasional config.Xs - basically they're the same as the present const variables.

Let me know if this does what you want, or if I've misunderstood the problem.

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

satnerd
Posts: 9
Joined: Sun Oct 29, 2017 9:23 am

Re: Image viewer with transition between images

Tue May 12, 2020 4:35 pm

Hi Paddy

Thanks for the swift reply. Much appreciated.
I'd rather know how to blend in a transparent png. Seems more flexible. (Single characters can change color, different font size)

Beat

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Image viewer with transition between images

Tue May 12, 2020 5:30 pm

Well in many ways blending an image file is easier. You need to apply it as a texture to a Plane (with the same dimensions as the image), set the z location in front of the slide, use the uv_flat shader, set Texture.blend = True and draw() after drawing slide. Approximately like

Code: Select all

...
libre = pi3d.Textures("myfile.png", blend=True)
plane = pi3d.Plane(w=libre.ix, h=libre.iy, z=0.1) #NB x,y both default zero puts it in the middle of the screen
plane.set_draw_details(flatsh, [libre])
    ...
    plane.set_alpha(1.0 - abs(1.0 - 2.0 * a)) #or whatever behaviour you want
    ...
    plane.draw()
If the images you use to make the Texture don't change then it doesn't really matter where they come from, but if you need to generate text dynamically, Texture can be 'fed' a PIL Image or a numpy array. Either of those two gives you a great deal of flexibility - for instance the PIL.ImageDraw functionality allows you to draw whatever characters you want in whatever colour at whatever location. Which is what pi3d.FixedString uses.

Let me know if you have any problems

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

satnerd
Posts: 9
Joined: Sun Oct 29, 2017 9:23 am

Re: Image viewer with transition between images

Fri May 22, 2020 12:00 pm

Hi Paddy

For long texts, it would be nice to display a subset of the string as horizontally scrolling text.
I implemented scrolling text using pi3d.TextBlock. I just update the text object with a varying substring.
The resulting scrolling is very jerky.
In ~/pi3d_demos/StringMulti.py is an example a «moving string/string moving».
It’s close to what I want. But I don’t know how to make parts of a character appear and disappear.
Is this possible?

Then there is another problem:
In Thai, some characters take no space, for example the character " ั" is always on top of other characters.
When I render text using pi3d.TextBlock with such characters, the result looks "ว ัน" but should look "วัน".
Is this a PIL problem? I updated to PIL 7.1.2, but still the same.

KR Beat

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Image viewer with transition between images

Fri May 22, 2020 5:06 pm

Hi, If you implemented your earlier idea of using a png file with the text on it then you can make a rectangular mask effect by changing the UV values on the plane you use to display the text. Here is a cut-down version to give you an indication what to do.

Code: Select all

import pi3d

SCALE_FACTOR = 2.0 # this will make it half as big

disp = pi3d.Display.create(w=960,h=600, frames_per_second=20)
cam = pi3d.Camera(is_3d=False)
shader = pi3d.Shader("uv_flat")

backg = pi3d.Plane(w=disp.width, h=disp.height, z=5.0)
backtex = pi3d.Texture("textures/pi3d_splash.jpg")
backg.set_draw_details(shader, [backtex])

plane = pi3d.Plane(w=200, h=100, z=4.0)
libre = pi3d.Texture("textures/atlas01.png")
(xfact, yfact) = (SCALE_FACTOR * plane.width / libre.ix, 
                  SCALE_FACTOR * plane.height / libre.iy)
plane.set_draw_details(shader, [libre], umult=xfact, vmult=yfact)

offset = [0.1, 0.1]
kbd = pi3d.Keyboard()
while disp.loop_running():
    backg.draw()
    plane.set_offset(offset)
    plane.draw()
    offset[0] += 0.01
    offset[1] += 0.00872 # non-round number!
    if kbd.read() == 27:
        kbd.close()
        disp.destroy()
        break
If something doesn't make sense or you get stuck, don't hesitate to ask.

PS I will check out the issue with character spacing in languages like Thai. It might be a assumption in pi3d, thanks for pointing it out.
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

satnerd
Posts: 9
Joined: Sun Oct 29, 2017 9:23 am

Re: Image viewer with transition between images

Sat May 23, 2020 5:50 am

Hi Paddy

On the Thai spacing:
there is a good article in https://stackoverflow.com/a/30105788 explaining on how to tackle the spacing.
I had to use regexp to get the character based scrolling working properly. (But jerky)

Yeah, I implemented the PNG rendering. It is a fairly straight forward way well suited for layouts using
different font sizes, alignments and the like. Problem is, the rendering, cropping and adding transparency
to the PNG takes a few seconds per image. If I start generating PNG for all text elements, I probably need to
do all this stuff in a separate thread to prevent the picture on display showing much longer than average.
I retrieve weather information every 30 minutes.

I am currently looking into the pi3d.TextBlock/pi3d.PointText implementation which is offering a rich set
of functionality. Would it not possible to use «moving string/string moving» from StringMulti.py with an
additional layer mask on top of the string?

Beat

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Image viewer with transition between images

Sat May 23, 2020 7:11 am

OK. There are three ways to achieve that (probably more). 1 blend mode where you would draw the text and mask before the main image and probably not get nice edges. 2 stencil mask 3 tweak the shader. The latter two are further into the workings of OpenGL than most of pi3d but not so tricky. I will post some ideas later.

Paddy

EDIT: using the stencil is probably the easiest. Like this, i.e. enable just before drawing the text and disable after.

Code: Select all

import pi3d
from pi3d import opengles
from pi3d.constants import GL_SCISSOR_TEST, GLint, GLsizei

disp = pi3d.Display.create(w=960,h=600, frames_per_second=20)
cam = pi3d.Camera(is_3d=False)
shader = pi3d.Shader("uv_flat")

backg = pi3d.Plane(w=disp.width, h=disp.height, z=5.0)
backtex = pi3d.Texture("textures/pi3d_splash.jpg")
backg.set_draw_details(shader, [backtex])

plane = pi3d.Plane(w=400, h=400, z=4.0)
libre = pi3d.Texture("textures/atlas01.png")
plane.set_draw_details(shader, [libre])

opengles.glScissor(GLint(400), GLint(300),  GLsizei(100), GLsizei(100))

(x, y, z) = (0.0, 0.0, 4.0)
kbd = pi3d.Keyboard()
while disp.loop_running():
    backg.draw()
    opengles.glEnable(GL_SCISSOR_TEST)
    plane.draw()
    opengles.glDisable(GL_SCISSOR_TEST)
    x -= 4 if x > -200 else -400
    y -= 1.231 if y > -100 else -200
    plane.position(x, y, z)
    if kbd.read() == 27:
        kbd.close()
        disp.destroy()
        break
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

satnerd
Posts: 9
Joined: Sun Oct 29, 2017 9:23 am

Re: Image viewer with transition between images

Fri Jun 05, 2020 1:33 pm

Hi Paddy

meanwhile I managed to get the .PNG based scrolling to work.
Now, I noticed that the function tex_load in PictureFrame.py takes quite some time
to load the pi3d.Texture: It takes 0.2s for a 100k picture, but whopping 4s for 3Mb.
The effect on the scrolling items: The scrolling grinds to a halt.

How would you implement some sort of prefetching on the next file? There is ample of time
for this, as the pictures are shown for like 5s each. I have no good grasp on the concepts
used with the DISPLAY.loop_running(). And it probably takes threads, too...

KR Beat

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Image viewer with transition between images

Fri Jun 05, 2020 2:32 pm

Hi, With the slide image loading I check if the variable a (for alpha but it's actually a uniform parameter passed to the shader) is less than 1 https://github.com/pi3d/pi3d_demos/blob ... me.py#L332 and prevent any file loading while the transition is taking place. If you do the image loading and Texture creation in the else block.

On threads: the GPU calls (to libopenGLESv2.so) have to happen on the main thread the program (python) started. Other jobs can happen on other threads but they're not real threads and mainly serve the function of making the code easier to read and write, they are a way of providing async functions rather than using multiple processors, (some modules (such as numpy) do use multiple pthreads and are pretty efficient). OS jobs such as reading or writing streams will be highly optimised and will go as fast as the Raspberry Pi hardware can manage - they almost certainly use a different process and run on a different processor, but if the file reading and Texture creation blocks the main loop then this will cause the frame rate to fluctuate or freeze. So you could do the file reading and some of the Texture creation in a python thread and that wouldn't slow the frame rate down much, but the final GPU work would happen on the main thread and you would probably notice that. TLDR; load Textures while no transition is taking place

Paddy

PS there is quite a major revision called PictureFrame2020 with the latest version of pi3d (v2.37) Probably little of the core has changed but there are a couple of tweaks in MQTT functionality and all the const values have been moved out into a config file that allows modification by passing command line arguments. If you've done lots of modifications you might not want to swap!
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

satnerd
Posts: 9
Joined: Sun Oct 29, 2017 9:23 am

Re: Image viewer with transition between images

Fri Jun 05, 2020 2:59 pm

Hi Paddy

as always: thanks :)
PictureFrame2020.py w/ argparse looks versatile. Makes it much easier to try out different options an see their effect.
Should not be too much work to merge with my changes.

I am also thinking to write a cgi script to facilitate changing PIC_DIR, e.g. from a list of favorite directories.
I played with MQTT and Home Assistant, but I am not satisfied with the convenience.

Beat

User avatar
sapnho
Posts: 244
Joined: Sun Sep 14, 2014 3:49 pm
Location: Frankfurt am Main
Contact: Website

Re: Image viewer with transition between images

Fri Jun 05, 2020 3:21 pm

Hi Beat, while Paddy was busy updating PictureFrame2020, I updated all the tutorials for building digital picture frames: https://www.thedigitalpictureframe.com/?s=pi3d

If you want to change subdirectories you can use PiHelper (https://www.thedigitalpictureframe.com/ ... ure-frame/) or DashMQTT (https://www.thedigitalpictureframe.com/ ... oto-frame/) depending on your mobile platform.

It's summarized here: https://www.thedigitalpictureframe.com/ ... -or-voice/

No need for Home Assistant, all you need it to send the MQTT messages directly.
www.TheDigitalPictureFrame.com - Build a really great digital picture frame with the Raspberry Pi.
With lots of great tips from this forum.
Please submit your digital picture frame project to the user gallery here: bit.ly/2WkyjW1

User avatar
sapnho
Posts: 244
Joined: Sun Sep 14, 2014 3:49 pm
Location: Frankfurt am Main
Contact: Website

Re: Image viewer with transition between images

Fri Jun 05, 2020 3:25 pm

And all the current options of Pi3D are summarized here: https://www.thedigitalpictureframe.com/ ... ry-config/

Thanks, Paddy, for a great update of Pi3D!
www.TheDigitalPictureFrame.com - Build a really great digital picture frame with the Raspberry Pi.
With lots of great tips from this forum.
Please submit your digital picture frame project to the user gallery here: bit.ly/2WkyjW1

User avatar
paddyg
Posts: 2541
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Image viewer with transition between images

Fri Jun 05, 2020 3:27 pm

Beat, Allowing web access to change things is very easy to do in python (almost just a line or two of code (plus HTML and javascript if you want it to look nice)) and it obviously doesn't need any kind of performance... but there would be security issues if you wanted to access it from outside the local network. Using MQTT is quite handy if you have a more IOThings you want to control as well.

Paddy
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

Return to “General discussion”