olikraus / u8g2

U8glib library for monochrome displays, version 2
Other
5.07k stars 1.05k forks source link

GIF files? #1008

Closed eried closed 5 years ago

eried commented 5 years ago

What would be the easiest way to get a gif file on a SH1106 using U8g2lib? I want to add some interactivity in between frames but I have not found a straightforward solution :/

v1993 commented 5 years ago

You can't show GIF at all, displays are far away from supporting that and u8g2 is designed tiny for such functional. Closest thing that you want is loading a set of bitmaps and drawing them with some delay.

eried commented 5 years ago

Yes, I am doing that (the gif is 1 bit) but I am trying to find a streamlined solution to go from 1 bit gif to the bitmaps :/

v1993 commented 5 years ago

Which uC are you using? If it is powerful enough, you can try to find some lightweight image reader library (which have nothing to do with u8g2). I've seen some for jpeg and png, no idea for gif...

But just converting every frame into separate .xmp and then manually merging them is probably much easier and will lead to much better target system performance.

eried commented 5 years ago

ESP8266, I think there is a lot of space, I was used to the limitations in the Arduboy (Leonardo) that is why it made sense with the new u8g2, I will keep checking and post my solution here

v1993 commented 5 years ago

Reading images, especially animated GIFs, is always pain, especially on microcontrollers. Good luck!

olikraus commented 5 years ago

Just to complete this: You can simply convert gif to xbm with tools like gimp.

eried commented 5 years ago

OK, thanks. I need to find that, but in the shape of https://framagit.org/zeduckmaster/ardu-imconvert

So I can work on the gif files and get the c arrays without doing more processing of small files. I have not tried gimp but I am guessing it does not export all frames to 1 file, but to several ones with weird headers.

olikraus commented 5 years ago

Here is a complete different approach: https://github.com/olikraus/u8g2/tree/master/tools/font/png2bdf

For one of my own projects, i had a similar problem. Solution is this:

  1. create multiple 1-bit (monochrome) png files (preferable of the same size)
  2. Create a .bdf font file out of all tbe png files with png2bdf
  3. Use bdfconv from this project to convert the bdf (with all the png files included) into the internal u8g2 font format.

As a bonus: The internal u8g2 font format is a compressed font format, so your pictures will be compressed (maybe not as good as gif, but still better than raw data).

eried commented 5 years ago

Hey @olikraus thanks for the input! this is an absolute gem now!

So, complementing the answer: 1) Draw your animation layer in piskelapp.com, export as png frames directly 2) Run png2bdf.exe -o your_name.bdf *.png 3) Run bdfconv.exe -f 1 -o your_name.h your_name.bdf 4) Print using:

    u8g2.setFont(bdf_font); // choose a suitable font
    u8g2.setCursor(0, 64); // left bottom align (my screen is 64 pix h in this example)
    u8g2.print((char)i); // From 50, so I guess the maximum frames is 205

My 50 frames gif is using 5 kb 💯

eried commented 5 years ago

Here is a complete different approach: https://github.com/olikraus/u8g2/tree/master/tools/font/png2bdf

For one of my own projects, i had a similar problem. Solution is this:

  1. create multiple 1-bit (monochrome) png files (preferable of the same size)
  2. Create a .bdf font file out of all tbe png files with png2bdf
  3. Use bdfconv from this project to convert the bdf (with all the png files included) into the internal u8g2 font format.

As a bonus: The internal u8g2 font format is a compressed font format, so your pictures will be compressed (maybe not as good as gif, but still better than raw data).

Just 1 question: is there is a way to save the "black" pixels as erase in a u8g2 font?, for making a multilayered animation? or should I make masks in white and print them in black?

olikraus commented 5 years ago

u8g2.print((char)i); // From 50, so I guess the maximum frames is 205

U8g2 font supports up to 2^16 gylphs, so the number of frames is more than 65000. You can (should) also specify the glyph number of the first frame. There is an option "-e #" for this in png2bdf (https://github.com/olikraus/u8g2/blob/master/tools/font/png2bdf/png2bdf.c#L296)

My 50 frames gif is using 5 kb

wow, looks good...

Just 1 question: is there is a way to save the "black" pixels as erase in a u8g2 font?

You want to invert the meaning of the pixel value? If so, there are three options:

Last option of course will slow down the uC, so better use the first two options.

olikraus commented 5 years ago

More notes: Instead of set curser and print, better use drawGlyph command. The drawGlyph just takses the 16 bit glyph number, where for print you would need to use the UTF8 encoded number (which is a little bit difficult to convert).

drawGylph is documented here: https://github.com/olikraus/u8g2/wiki/u8g2reference#drawglyph

As a conclusion, you bdf conversion may look like this:

png2bdf.exe -i -e 40 -o your_name.bdf *.png

Then the first frame will be 40 and you can just draw the second frame with drawGlyph(0, 64, 41)

If you have much more frames or if you start with a large number like this: png2bdf.exe -i -e 1000 -o your_name.bdf *.png

you need to ensure to use the correct range in bdfconv:

bdfconv.exe -f 1 -m '1000-1050' -o your_name.h your_name.bdf

After this, the first frame will be accessable with 1000: drawGlyph(0, 64, 1000)

eried commented 5 years ago

You want to invert the meaning of the pixel value? If so, there are three options:

I want to have a way to do some simple masking, imagine I have: image

And I want to overlay on top: image

So, for now, the solution I could think is to pre-process all the images and convert black to white (hence creating a mask of the siluettes) and then create 2 fonts, draw the first Glyph always in black

olikraus commented 5 years ago

Should be possible. Also crosscheck the font mode: https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontmode I assume this should offer all the things you need.