arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
JpegTFT.h
1#pragma once
2#include "AudioTools/CoreAudio/AudioBasic/Collections/Vector.h"
3#include "JPEGDecoder.h" // https://github.com/Bodmer/JPEGDecoder
4#include "TFT_eSPI.h" // https://github.com/Bodmer/TFT_eSPI
5#include "Video/Video.h"
6#include <algorithm> // std::min
7
8namespace audio_tools {
9
17class JpegTFT : public VideoOutput {
18public:
19 JpegTFT(TFT_eSPI &TFTscreen) { p_screen = &TFTscreen; }
20
21 // Allocate memory and create window
22 void beginFrame(size_t jpegSize) override {
23 if (start == 0l)
24 start = millis();
25 LOGI("jpegSize: %d", (int)jpegSize);
26 // prevent memory fragmentation, change size only if more memory is needed
27 if (img_vector.size() < jpegSize) {
28 img_vector.resize(jpegSize);
29 }
30 this->pos = 0;
31 this->open = jpegSize;
32 this->size = jpegSize;
33 }
34
37 uint32_t endFrame() override {
38 assert(open == 0);
39 jpeg_decoder.decodeArray((const uint8_t *)&img_vector[0], size);
40 renderJPEG(0, 0);
41 return millis() - start;
42 }
43
44 // Add some more data to the image vector
45 size_t write(const uint8_t *data, size_t len) override {
46 memcpy(&img_vector[pos], data, len);
47 pos += len;
48 open -= len;
49 return len;
50 }
51
52protected:
53 Vector<uint8_t> img_vector;
54 size_t pos = 0;
55 size_t size = 0;
56 int open = 0;
57 uint64_t start = 0;
58 JPEGDecoder jpeg_decoder;
59 TFT_eSPI *p_screen = nullptr;
60
61 //====================================================================================
62 // Decode and paint onto the TFT screen
63 //====================================================================================
64 uint32_t renderJPEG(int xpos, int ypos) {
65 // retrieve infomration about the image
66 uint16_t *pImg;
67 uint16_t mcu_w = jpeg_decoder.MCUWidth;
68 uint16_t mcu_h = jpeg_decoder.MCUHeight;
69 uint32_t max_x = jpeg_decoder.width;
70 uint32_t max_y = jpeg_decoder.height;
71
72 // Jpeg images are draw as a set of image block (tiles) called Minimum
73 // Coding Units (MCUs) Typically these MCUs are 16x16 pixel blocks Determine
74 // the width and height of the right and bottom edge image blocks
75 uint32_t min_w = std::min((uint32_t)mcu_w, max_x % mcu_w);
76 uint32_t min_h = std::min((uint32_t)mcu_h, max_y % mcu_h);
77
78 // save the current image block size
79 uint32_t win_w = mcu_w;
80 uint32_t win_h = mcu_h;
81
82 // record the current time so we can measure how long it takes to draw an
83 // image
84 uint32_t drawTime = millis();
85
86 // save the coordinate of the right and bottom edges to assist image
87 // cropping to the screen size
88 max_x += xpos;
89 max_y += ypos;
90
91 // read each MCU block until there are no more
92 while (jpeg_decoder.read()) {
93 // save a pointer to the image block
94 pImg = jpeg_decoder.pImage;
95
96 // calculate where the image block should be drawn on the screen
97 int mcu_x = jpeg_decoder.MCUx * mcu_w + xpos;
98 int mcu_y = jpeg_decoder.MCUy * mcu_h + ypos;
99
100 // check if the image block size needs to be changed for the right and
101 // bottom edges
102 if (mcu_x + mcu_w <= max_x)
103 win_w = mcu_w;
104 else
105 win_w = min_w;
106 if (mcu_y + mcu_h <= max_y)
107 win_h = mcu_h;
108 else
109 win_h = min_h;
110
111 // calculate how many pixels must be drawn
112 uint32_t mcu_pixels = win_w * win_h;
113
114 // draw image block if it will fit on the screen
115 if ((mcu_x + win_w) <= p_screen->width() &&
116 (mcu_y + win_h) <= p_screen->height()) {
117 // open a window onto the screen to paint the pixels into
118 // p_screen->setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y +
119 // win_h - 1);
120 p_screen->setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1,
121 mcu_y + win_h - 1);
122 // push all the image block pixels to the screen
123 while (mcu_pixels--)
124 p_screen->pushColor(*pImg++); // Send to TFT 16 bits at a time
125 }
126
127 // stop drawing blocks if the bottom of the screen has been reached
128 // the abort function will close the file
129 else if ((mcu_y + win_h) >= p_screen->height())
130 jpeg_decoder.abort();
131 }
132
133 // calculate how long it took to draw the image
134 drawTime = millis() - drawTime; // Calculate the time it took
135 return drawTime;
136 }
137}; // JpegTFT
138
139} // namespace audio_tools
Display jpeg image using https://github.com/Bodmer/TFT_eSPI and https://github.com/Bodmer/JPEGDecoder...
Definition JpegTFT.h:17
uint32_t endFrame() override
Definition JpegTFT.h:37
Abstract class for video playback. This class is used to assemble a complete video frame in memory.
Definition Video.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12