pixoo icon indicating copy to clipboard operation
pixoo copied to clipboard

No GIF animations possible?

Open satoer opened this issue 2 years ago • 14 comments

First of al, thank you for this great library!

I was wondering how to load a GIF animation. If i use the draw_image function with a GIF animation only the first image is visible, and it's not animated.

According to the Divoom api it should be possible with Json: { “Command”:”Device/PlayTFGif”, “FileType”:2, “FileName”:”http://f.divoom-gz.com/64_64.gif“ } But it seems that this is not integrated?

Cheers.

satoer avatar May 02 '22 20:05 satoer

That's a good point, I'll look into it! I remember testing something similar but crashing my Pixoo over and over. But I did notice there's been quite a few updates to the firmware, so it's worth another shot, surely.

SomethingWithComputers avatar May 02 '22 22:05 SomethingWithComputers

Thanks for the reply!

Before I tried your library I used this piece of javascript. (I dynamically replaced the gif every couple of minutes in the actual script). I didn't encounter any crashes over the course of 4 weeks. Except when I refer a GIF animation link that it does not understand (like a tenor link with no .gif extension).

fetch('http://192.168.178.206:80/post', {
  method: 'POST',

  body: JSON.stringify(
      {
    "Command":"Device/PlayTFGif",
    "FileType":2,
    "FileName": "http://kimchigraphics.com/wp-content/uploads/2022/04/Solar-flag-64x64-1.gif"
    })

}).then(res => res.json())
  .then(res => console.log(res));

I was kind of hoping I could create small gif-animations and put custom text on top of it. Like those the pre-made examples in the Divoom app. (or they could be full screen GIF animation with text on top of it, I don't know).

Anyhow, the possibility of adding support for GIF animations would be great.

satoer avatar May 03 '22 12:05 satoer

Alright it seems like "PlayTFGif" can only play GIFs that are stored on an internal SD card.

However, I'm looking into the animation call, which theoretically can display a GIF, if I can convert it to some sort of buffered image first. I'll be looking into it!

SomethingWithComputers avatar Oct 02 '22 02:10 SomethingWithComputers

@SomethingWithComputers Any progress on this one? I'd love to see this feature in your library.

Phlogi avatar Jan 05 '23 12:01 Phlogi

@Phlogi Hey! I've been working on a system to locally load GIFs as a background image basically, and display them with a specific FPS! But I'm currently really occupied with my work.. Real life. But I'll make it work sometime in the near future if somebody else doesn't pick it up first :)!

It'll basically be the same method that loads an image currently, but with some extra in-memory bookkeeping for displaying the correct frame and loop it if needed But in order for that to work correctly there needs to be some sort of internal clock/timer and I'm not a fan of that in the current version. I'd rather it'd be pased on the manual push calls and I want to keep it as light-weight as possible. But we'll see how it works!

SomethingWithComputers avatar Jan 05 '23 22:01 SomethingWithComputers

maybe i can push my solution for this problem. Currently some refactoring and optimization necessary. :)

Pfleiderer-Adrian avatar Jan 07 '23 13:01 Pfleiderer-Adrian

Thanks to both of you. In the meantime I'll use pixoo-rest which supports animated GIFS.

Phlogi avatar Jan 07 '23 15:01 Phlogi

Would love to see the current progress here from @SomethingWithComputers - maybe I can pickup and help from where you currently are? Even simple gif-animations with no speed/FPS-control would be awesome!

Kudos and a big thanks for what you've achieved so far!

markus-barta avatar Jan 20 '23 16:01 markus-barta

Agreed! Thank you so much for this awesome API. I am also investigating how to get gifs to work properly. Looking forward to the update.

stylerhall avatar Mar 04 '23 23:03 stylerhall

I've been tinkering with the Pixoo 64, and I believe I've solved this.

The key is to set PicNum to the number of frames your animation has.

So here's the parameters you need:

PicNum = 10 # The number of frames in your GIF. In this example, my GIF has 10 frames. You can use `Image.open("yourfile.gif").n_frames` to determine this programmatically
PicWidth = 64 # The width of your picture, obviously.
PicOffset = 1 # This is the current frame number you're sending. As you send each frame, you need to increment this
PicId = 1 # You can use `Draw/GetHttpGifId` to get this number, then add 1. Or you can just use `Draw/ResetHttpGifId` to reset it back to 1. You can send more than one GIF at a time, and it'll play each one for a short while, but it'll loop the last one indefinitely instead of looping back to ID 1
PicSpeed = 500 # The duration of the frame. You can use the `.info` property of a PIL image object to get the duration of the frame, like so: `yourimage.info["duration"]`
PicData = "" # Your data here. The data is just a list in the format `[R, G, B, R, G, B, R, G, B]`, repeated for `size * size` times (e.g. 4096 times)

And side note, PIL (or rather, Pillow) has a function, getdata(), which returns a list of tuples with R, G and B data in it. This means that you can create a base64 string like so:

# Open the GIF
img = Image.open(filename)

# Loop through all the frames in the animation
for frame in range(0, img.n_frames):
    # Go the frame in question
    img.seek(frame)
    
    # Convert it to RGB because the device expects a list of red, green and blue pixels
    imgrgb = img.convert(mode="RGB")

    # This line gets all the RGB values from a frame as a list of tuples. The tuples are then just flattened out to a list
    # The result will look similar to this: `[255, 0, 0, 255, 0, 0, 255, 0, 0 ...]` for a purely red image
    pixels = [item for p in list(imgrgb.getdata()) for item in p]
            
    # Base64 encode the pixels we grabbed from the frame. Turn the list into a bytearray
    b64 = base64.b64encode(bytearray(pixels))

    # frameData contains the data you need to send to the Pixoo 64
    frameData = b64.decode("utf-8")

Much smaller code than what your library currently has, if you want to use it.

Anyway, hopefully this code helps you out. I've spent about a week poking around, writing my own Python library, mostly to just teach myself Python and map out the pretty crappy Divoom API documentation they give us.

Grayda avatar Mar 05 '23 10:03 Grayda

@Grayda , I have also been tinkering with the API. That suggestion looks great, I'm still trying to understand how to get it to work. From your code, it looks like you're looping over each frame to encode every pixel of every frame, however at the end of the logic you're overwriting the frameData each frame? How are you passing in all of the frames?

stylerhall avatar Mar 10 '23 18:03 stylerhall

@Grayda , I have also been tinkering with the API. That suggestion looks great, I'm still trying to understand how to get it to work. From your code, it looks like you're looping over each frame to encode every pixel of every frame, however at the end of the logic you're overwriting the frameData each frame? How are you passing in all of the frames?

What I forgot to add to my reply is, at the end of every iteration, I'm POSTing that data to the Pixoo.

So yeah, I'm overwriting frameData every time, because I'm sending every frame of the animation separately. It's a horrible way to do it, but that's how the Pixoo expects the data, as individual API calls of individual frames

Grayda avatar Mar 10 '23 22:03 Grayda

@Grayda , ahh gotcha. thanks for the response! I'm curious. Have you tried the play gif API command? It looks like loading gifs is a first-class command and may alleviate the need for processing each frame.

stylerhall avatar Mar 10 '23 23:03 stylerhall

@Grayda , ahh gotcha. thanks for the response! I'm curious. Have you tried the play gif API command? It looks like loading gifs is a first-class command and may alleviate the need for processing each frame.

Yep, but unfortunately you can't display text on the screen with that, only when you send individual frames. That's fine if you want to just show images, but my end goal is to use it to show Home Assistant notifications on there, plus write my own clock face to display stats like upcoming calendar events.

Grayda avatar Mar 11 '23 00:03 Grayda

It is now possible to load gifs from the internet and display them on the device, or load them from the local TF card.

Supported GIF sizes are: 16 x 16, 32 x 32, 64 x 64

  • Added play_net_gif to loop the GIF from a URL on the device
  • Added play_local_gif to play a GIF from the TF-card in the device (untested)
  • Added play_local_gif_directory to play the GIFs in a directory on the TF-card in the device (untested)

SomethingWithComputers avatar Aug 18 '24 17:08 SomethingWithComputers