ESP32-HUB75-MatrixPanel-DMA
ESP32-HUB75-MatrixPanel-DMA copied to clipboard
Display Text on top of GIF files
Hi there and thank you so much for this library
So i had a question, i am using the Animated GIF SPIFF example. Is there any way to display text on top of the GIF files, like continuously for an entire GIF and not only for a particular frame
Use two display buffers - first with text and second for GIF frames. Combine them before outputs each frame.
This is a question of how the AnimatedGIF library writes pixels to the display.
The issue is the AnimatedGIF library writes to every pixel for the dimensions of the GIF/Display, so any other 'drawPixels' you do will be overridden for each frame that the AnimatedGIF library wants to print to the display using this DMA library.
I think you will need to write to the display after each GIF frame, around here:
while (gif.playFrame(true, NULL))
{
dma_display->print("TEST"); /// <---------- ADD something like this I think? Write text after the AnimatedGIF library has written the GIF frame to the display.
if ( (millis() - start_tick) > 8000) { // we'll get bored after about 8 seconds of the same looping gif
break;
}
}
Thanks for your help doing it in void ShowGIF(char *name) didnt seem to work like mrfaptastic suggested
so i did it like this and it seemed to work
I did it in the void GIFDraw(GIFDRAW *pDraw) part
{
s = pDraw->pPixels;
// Translate the 8-bit pixels through the RGB565 palette (already byte reversed)
for (x=0; x<pDraw->iWidth; x++)
{
OneEightMatrixDisplay->drawPixel(x, y, usPalette[*s++]); // color 565
}
}
OneEightMatrixDisplay->setCursor(0, 12);
OneEightMatrixDisplay->print("test"); // display text on each frame of GIF after its displayed
In the same way time via NTP can be displayed on top of GIFs
reopening this issue as i noticed an issue the text seems to flicker (slight but noticeable) for some reason, so is there some other way to do it, as my approach seems to have issues
Use double buffering
Use double buffering
yes i am going to do that, as far as i understand i have to play the gif normally and then use
display->flipDMABuffer()
and then print the text
but then how do i combine them both?
as far as i understand i have to play the gif normally and then use
display->flipDMABuffer()
and then print the text
No, not in that order. To take advantage of using double buffer you must flip the buffer as the very LAST command after all drawings. So: a) play the gif b) print the text c) display->flipDMABuffer()
so i did as you suggested and the gif lags like hell with this (my usage of this function is probably wrong)
so then i tried
a) flipDMABuffer b) print GIF c) FlipDMABuffer d) print text
this worked better, but still jittery and flickring
this worked better,
but double buffering doesn't work in this case...
i honestly ain't sure how to use it correctly, since flipping the buffer always causes major slowdowns for me here is the code i am trying to use it for, its from the AnimatedGIFSPIFF example and just take this part and modify it slightly i honestly am not even sure why the text flickers and the gif dosent
void GIFDraw(GIFDRAW *pDraw) { uint8_t *s; uint16_t *d, *usPalette, usTemp[320]; int x, y, iWidth; iWidth = pDraw->iWidth; if (iWidth > MATRIX_WIDTH) iWidth = MATRIX_WIDTH; usPalette = pDraw->pPalette; y = pDraw->iY + pDraw->y; // current line s = pDraw->pPixels; if (pDraw->ucDisposalMethod == 2) // restore to background color { for (x=0; x<iWidth; x++) { if (s[x] == pDraw->ucTransparent) s[x] = pDraw->ucBackground; } pDraw->ucHasTransparency = 0; } // Apply the new pixels to the main image if (pDraw->ucHasTransparency) // if transparency used { uint8_t *pEnd, c, ucTransparent = pDraw->ucTransparent; int x, iCount; pEnd = s + pDraw->iWidth; x = 0; iCount = 0; // count non-transparent pixels while(x < pDraw->iWidth) { c = ucTransparent-1; d = usTemp; while (c != ucTransparent && s < pEnd) { c = *s++; if (c == ucTransparent) // done, stop { s--; // back up to treat it like transparent } else // opaque { *d++ = usPalette[c]; iCount++; } } // while looking for opaque pixels if (iCount) // any opaque pixels? { for(int xOffset = 0; xOffset < iCount; xOffset++ ){ dma_display->drawPixel(x + xOffset, y, usTemp[xOffset]); // 565 Color Format } x += iCount; iCount = 0; } // no, look for a run of transparent pixels c = ucTransparent; while (c == ucTransparent && s < pEnd) { c = *s++; if (c == ucTransparent) iCount++; else s--; } if (iCount) { x += iCount; // skip these iCount = 0; } } } else // does not have transparency { s = pDraw->pPixels; // Translate the 8-bit pixels through the RGB565 palette (already byte reversed) for (x=0; x<pDraw->iWidth; x++) { dma_display->drawPixel(x, y, usPalette[*s++]); // color 565 } } dma_display->setTextSize(2); // modified part dma_display->setCursor(7, 22); dma_display->setTextColor(dma_display->color565(250, 250, 250)); dma_display->print("8 3"); // test text that i want to print dma_display->setCursor(35, 22); dma_display->setTextColor(dma_display->color565(250, 250, 250)); dma_display->print("0 8"); } // GIFDraw()
so i managed to get a video of the issue, i had to add a delay after the draw function so that it could be slow enough to capture, irl its fast but still visible flicker, its on text only, so any idea what could be the issue
https://user-images.githubusercontent.com/58217787/234651043-1fd6dc96-7722-44da-acdb-366a6e66db06.mp4
This is a behavior of the AnimatedGif library that's outside the scope of this repo.... but from my experimentation GIFDraw is called multiple times for each frame because the GIF decoder doesn't decode a whole frame at once, but in 'chunks'.
So it's re-drawing that text many times for each GifFrame, slowing stuff down I think.
You need to some how re-write the sketch to write to an 'off-screen' buffer and apply the text over the top and then display it. I can't help you with that however.
yes it seems like so, according to bitbank2
The concept is very simple - as you decode each line, draw the pixels of the text which should appear on that line on top of the decoded pixels, then send it to the display. No flickering. If you try to draw text on the display AFTER transmitting the GIF pixels, you'll see the flicker.
so will have to try this solution or try to properly implement a double buffer.
Zip up your project / sketch and I'll take a look if I get a moment to look at it if you can't figure it out.
Hi, I am using the Aurora demo, managed to "brute force" the text overlay by shoving print commands in the drawFrame function. apparently it works well for some effects, but flickers for others.
void ShowFrame() {
//#if (FASTLED_VERSION >= 3001000)
// nblendPaletteTowardPalette(currentPalette, targetPalette, 24);
//#else
currentPalette = targetPalette;
//#endif
// backgroundLayer.swapBuffers();
// leds = (CRGB*) backgroundLayer.backBuffer();
// LEDS.countFPS();
for (int y = 0; y < MATRIX_HEIGHT; ++y) {
for (int x = 0; x < MATRIX_WIDTH; ++x) {
//Serial.printf("Flushing x, y coord %d, %d\n", x, y);
uint16_t _pixel = XY16(x, y);
dma_display->drawPixelRGB888(x, y, leds[_pixel].r, leds[_pixel].g, leds[_pixel].b);
} // end loop to copy fast led to the dma matrix
}
dma_display->setTextSize(2); // size 1 == 8 pixels high
dma_display->setCursor(10, text_height); // start at top left, with 8 pixel of spacing
dma_display->setTextColor(dma_display->color444(15, 15, 15));
dma_display->print("ICST");
dma_display->setTextSize(1); // size 1 == 8 pixels high
dma_display->setCursor(12, text_height + 25); // start at top left, with 8 pixel of spacing
dma_display->print("Taub CS");
}
Please take a look at my other library: https://github.com/mrcodetastic/GFX_Lite
You can do this easily now with an off-screen buffer.