16
16
#include " stb-image-source.h"
17
17
18
18
#define STB_IMAGE_IMPLEMENTATION
19
+ #include < unistd.h>
20
+
19
21
#include < algorithm>
20
22
#include < csignal>
21
23
#include < cstdint>
@@ -39,9 +41,9 @@ static constexpr int kDesiredChannels = 4; // RGBA, our framebuffer format
39
41
namespace timg {
40
42
class STBImageSource ::PreprocessedFrame {
41
43
public:
42
- PreprocessedFrame (const uint8_t *image_data, int source_w, int source_h ,
43
- int target_w, int target_h, const Duration &delay ,
44
- const DisplayOptions &opt)
44
+ PreprocessedFrame (const uint8_t *image_data, size_t source_w,
45
+ size_t source_h, size_t target_w, size_t target_h ,
46
+ const Duration &delay, const DisplayOptions &opt)
45
47
: delay_(delay), framebuffer_(target_w, target_h) {
46
48
const size_t len = source_w * source_h * 4 ;
47
49
Framebuffer source_img (source_w, source_h); // TODO: avoid copy.
@@ -89,14 +91,26 @@ bool STBImageSource::LoadAndScale(const DisplayOptions &options,
89
91
}
90
92
#endif
91
93
92
- FILE *img_file = (filename () == " -" )
93
- ? fdopen (STDIN_FILENO, " rb" )
94
- : stbi__fopen (filename ().c_str (), " rb" );
94
+ stbi__context context;
95
95
96
- if (!img_file) return false ;
96
+ FILE *img_file = nullptr ;
97
+ std::string mem_buffer;
97
98
98
- stbi__context context;
99
- stbi__start_file (&context, img_file);
99
+ if (filename () == " -" ) {
100
+ // For stdin, we need to fill a buffer, as stb needs seek functionality.
101
+ char buffer[4096 ];
102
+ ssize_t r;
103
+ while ((r = read (STDIN_FILENO, buffer, sizeof (buffer))) > 0 ) {
104
+ mem_buffer.append (buffer, r);
105
+ }
106
+ stbi__start_mem (&context, (const uint8_t *)mem_buffer.data (),
107
+ mem_buffer.size ());
108
+ }
109
+ else {
110
+ img_file = stbi__fopen (filename ().c_str (), " rb" );
111
+ if (!img_file) return false ;
112
+ stbi__start_file (&context, img_file);
113
+ }
100
114
101
115
int channels;
102
116
int target_width = 0 ;
@@ -108,7 +122,7 @@ bool STBImageSource::LoadAndScale(const DisplayOptions &options,
108
122
memset (&gdata, 0 , sizeof (gdata));
109
123
uint8_t *data;
110
124
while ((data = stbi__gif_load_next (&context, &gdata, &channels,
111
- kDesiredChannels , 0 ))) {
125
+ kDesiredChannels , nullptr ))) {
112
126
if (data == (const uint8_t *)&context) break ;
113
127
orig_width_ = gdata.w ;
114
128
orig_height_ = gdata.h ;
@@ -124,7 +138,8 @@ bool STBImageSource::LoadAndScale(const DisplayOptions &options,
124
138
STBI_FREE (gdata.background );
125
139
}
126
140
else {
127
- int w, h;
141
+ int w = 0 ;
142
+ int h = 0 ;
128
143
uint8_t *data = stbi__load_and_postprocess_8bit (
129
144
&context, &w, &h, &channels, kDesiredChannels );
130
145
if (!data) {
@@ -149,7 +164,7 @@ bool STBImageSource::LoadAndScale(const DisplayOptions &options,
149
164
? (int )frames_.size ()
150
165
: std::min (frame_count, (int )frames_.size ());
151
166
152
- fclose (img_file);
167
+ if (img_file) fclose (img_file);
153
168
154
169
return !frames_.empty ();
155
170
}
@@ -159,12 +174,13 @@ void STBImageSource::SendFrames(const Duration &duration, int loops,
159
174
const Renderer::WriteFramebufferFun &sink) {
160
175
int last_height = -1 ; // First image emit will not have a height.
161
176
const bool is_animation = frames_.size () > 1 ;
162
- if (frames_.size () == 1 || !is_animation)
177
+ if (frames_.size () == 1 || !is_animation) {
163
178
loops = 1 ; // If there is no animation, nothing to repeat.
164
-
179
+ }
165
180
// Not initialized or negative value wants us to loop forever.
166
181
// (note, kNotInitialized is actually negative, but here for clarity
167
- const bool loop_forever = (loops < 0 ) || (loops == timg::kNotInitialized );
182
+ const bool loop_forever =
183
+ (loops < 0 ) || (loops == timg::kNotInitialized ); // NOLINT
168
184
169
185
timg::Duration time_from_first_frame;
170
186
bool is_first = true ;
0 commit comments