Skip to content

Commit 0968fd2

Browse files
authored
Add resource loader from buffer and Read trait (#25)
1 parent 88de34c commit 0968fd2

File tree

5 files changed

+89
-49
lines changed

5 files changed

+89
-49
lines changed

README.md

+10-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ clock
3232

3333
## How to use
3434

35+
To use this library, please add the following into the dependencies in the `Cargo.toml` file:
36+
37+
```toml
38+
[dependencies]
39+
divoom = "0.1"
40+
```
41+
3542
The library contains 2 major parts:
3643

3744
- Divoom service APIs, that is used for talking to Divoom's backend service for device discovery etc.
@@ -131,7 +138,7 @@ all the GIF frames into it one by one. To help with this process, we created a r
131138
use divoom::*;
132139

133140
// Load the resource.
134-
let frames = DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo-16-rotate-4-frames.gif").unwrap();
141+
let frames = DivoomAnimationResourceLoader::gif_file("test_data/animation_builder_tests/logo-16-rotate-4-frames.gif").unwrap();
135142

136143
// Build animation with 16 pixel canvas and 100ms frame play speed.
137144
let builder = DivoomAnimationBuilder::new(16, Duration::from_millis(100)).unwrap();
@@ -150,9 +157,9 @@ let pixoo = PixooClient::new("192.168.0.123");
150157
pixoo.send_gif_as_animation(16, Duration::from_millis(100), "test_data/animation_builder_tests/logo-16-rotate-4-frames.gif").await
151158
```
152159

153-
For more on how to use it, feel free to check our doc here: <https://docs.rs/divoom/latest/divoom/struct.DivoomAnimationBuilder.html>.
160+
Besides gif, we also support png and jpeg format. And besides reading from file, we also support loading resource from any `Read` trait. For more on how to use it, feel free to check our doc here: <https://docs.rs/divoom/latest/divoom/struct.DivoomAnimationBuilder.html>.
154161

155-
And if you don't want this animation builder, we can exclude it by specifying the features with:
162+
And for any reason, if you don't want the builtin animation builder, we can exclude it by specifying the features with:
156163

157164
```toml
158165
[dependencies]

divoom/src/animation/animation_builder.rs

+29-22
Original file line numberDiff line numberDiff line change
@@ -206,17 +206,19 @@ mod tests {
206206
let mut frame = frame_builder.canvas_mut();
207207
assert_eq!(frame.width(), 64);
208208

209-
let frames =
210-
DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo-16-0.gif")
211-
.unwrap();
209+
let frames = DivoomAnimationResourceLoader::gif_file(
210+
"test_data/animation_builder_tests/logo-16-0.gif",
211+
)
212+
.unwrap();
212213
frame_builder = frame_builder.draw_frame(&frames[0]);
213214
}
214215

215216
#[test]
216217
fn divoom_animation_builder_can_build_single_frame_animation() {
217-
let frames =
218-
DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo-16-0.gif")
219-
.unwrap();
218+
let frames = DivoomAnimationResourceLoader::gif_file(
219+
"test_data/animation_builder_tests/logo-16-0.gif",
220+
)
221+
.unwrap();
220222
assert_eq!(frames.len(), 1);
221223

222224
let builder = DivoomAnimationBuilder::new(16, Duration::from_millis(100)).unwrap();
@@ -229,9 +231,10 @@ mod tests {
229231

230232
#[test]
231233
fn divoom_animation_builder_can_build_animation_with_fit() {
232-
let frames =
233-
DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo-16-0.gif")
234-
.unwrap();
234+
let frames = DivoomAnimationResourceLoader::gif_file(
235+
"test_data/animation_builder_tests/logo-16-0.gif",
236+
)
237+
.unwrap();
235238
assert_eq!(frames.len(), 1);
236239

237240
let builder = DivoomAnimationBuilder::new(32, Duration::from_millis(100)).unwrap();
@@ -278,9 +281,10 @@ mod tests {
278281

279282
#[test]
280283
fn divoom_animation_builder_can_build_animation_with_rotation() {
281-
let frames =
282-
DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo-16-0.gif")
283-
.unwrap();
284+
let frames = DivoomAnimationResourceLoader::gif_file(
285+
"test_data/animation_builder_tests/logo-16-0.gif",
286+
)
287+
.unwrap();
284288
assert_eq!(frames.len(), 1);
285289

286290
let builder = DivoomAnimationBuilder::new(32, Duration::from_millis(100)).unwrap();
@@ -303,9 +307,10 @@ mod tests {
303307

304308
#[test]
305309
fn divoom_animation_builder_can_build_animation_with_opacity() {
306-
let frames =
307-
DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo-16-0.gif")
308-
.unwrap();
310+
let frames = DivoomAnimationResourceLoader::gif_file(
311+
"test_data/animation_builder_tests/logo-16-0.gif",
312+
)
313+
.unwrap();
309314
assert_eq!(frames.len(), 1);
310315

311316
let builder = DivoomAnimationBuilder::new(32, Duration::from_millis(100)).unwrap();
@@ -328,9 +333,10 @@ mod tests {
328333

329334
#[test]
330335
fn divoom_animation_builder_can_build_animation_with_sized() {
331-
let frames =
332-
DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo-16-0.gif")
333-
.unwrap();
336+
let frames = DivoomAnimationResourceLoader::gif_file(
337+
"test_data/animation_builder_tests/logo-16-0.gif",
338+
)
339+
.unwrap();
334340
assert_eq!(frames.len(), 1);
335341

336342
let builder = DivoomAnimationBuilder::new(32, Duration::from_millis(100)).unwrap();
@@ -346,9 +352,10 @@ mod tests {
346352

347353
#[test]
348354
fn divoom_animation_builder_can_build_animation_with_scaled() {
349-
let frames =
350-
DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo-16-0.gif")
351-
.unwrap();
355+
let frames = DivoomAnimationResourceLoader::gif_file(
356+
"test_data/animation_builder_tests/logo-16-0.gif",
357+
)
358+
.unwrap();
352359
assert_eq!(frames.len(), 1);
353360

354361
let builder = DivoomAnimationBuilder::new(32, Duration::from_millis(100)).unwrap();
@@ -364,7 +371,7 @@ mod tests {
364371

365372
#[test]
366373
fn divoom_animation_builder_can_build_multi_frame_animation() {
367-
let frames = DivoomAnimationResourceLoader::gif(
374+
let frames = DivoomAnimationResourceLoader::gif_file(
368375
"test_data/animation_builder_tests/logo-16-rotate-4-frames.gif",
369376
)
370377
.unwrap();

divoom/src/animation/animation_resource_loader.rs

+47-19
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,43 @@
11
use crate::{DivoomAPIError, DivoomAPIResult};
22
use std::fs::File;
3-
use std::io::BufReader;
3+
use std::io::{BufReader, Read};
44
use tiny_skia::Pixmap;
55

66
/// Load resources into a series of `tiny_skia::Pixmap`, so we can use them to build the animations.
77
pub struct DivoomAnimationResourceLoader {}
88

99
impl DivoomAnimationResourceLoader {
10-
/// Load from local png file
11-
pub fn png(file_path: &str) -> DivoomAPIResult<Pixmap> {
10+
/// Load png resource from local file
11+
pub fn png_file(file_path: &str) -> DivoomAPIResult<Pixmap> {
1212
let frame = Pixmap::load_png(file_path)?;
1313
Ok(frame)
1414
}
1515

16-
/// Load from jpeg file
16+
/// Load png resource from a memory buffer
17+
pub fn png_buf(buf: &[u8]) -> DivoomAPIResult<Pixmap> {
18+
let frame = Pixmap::decode_png(buf)?;
19+
Ok(frame)
20+
}
21+
22+
/// Load png resource from Read trait
23+
pub fn png<R: Read>(reader: R) -> DivoomAPIResult<Pixmap> {
24+
let mut buffer = Vec::new();
25+
let mut buf_reader = BufReader::new(reader);
26+
buf_reader.read_to_end(&mut buffer)?;
27+
DivoomAnimationResourceLoader::png_buf(&buffer)
28+
}
29+
30+
/// Load jpeg resource from local file
1731
#[cfg(feature = "resource-loader-jpeg")]
18-
pub fn jpeg(file_path: &str) -> DivoomAPIResult<Pixmap> {
32+
pub fn jpeg_file(file_path: &str) -> DivoomAPIResult<Pixmap> {
1933
let file = File::open(file_path)?;
20-
let mut decoder = jpeg_decoder::Decoder::new(BufReader::new(file));
34+
DivoomAnimationResourceLoader::jpeg(file)
35+
}
36+
37+
/// Load jpeg resource from Read trait
38+
#[cfg(feature = "resource-loader-jpeg")]
39+
pub fn jpeg<R: Read>(reader: R) -> DivoomAPIResult<Pixmap> {
40+
let mut decoder = jpeg_decoder::Decoder::new(BufReader::new(reader));
2141
let pixels = decoder.decode()?;
2242

2343
let metadata = decoder.info().unwrap();
@@ -80,16 +100,22 @@ impl DivoomAnimationResourceLoader {
80100
Ok(frame)
81101
}
82102

83-
/// Load from local gif file
103+
/// Load gif resource from local file
84104
#[cfg(feature = "resource-loader-gif")]
85-
pub fn gif(file_path: &str) -> DivoomAPIResult<Vec<Pixmap>> {
86-
let mut frames = vec![];
105+
pub fn gif_file(file_path: &str) -> DivoomAPIResult<Vec<Pixmap>> {
87106
let input = File::open(file_path)?;
107+
DivoomAnimationResourceLoader::gif(input)
108+
}
109+
110+
/// Load gif resource from Read trait
111+
#[cfg(feature = "resource-loader-gif")]
112+
pub fn gif<R: Read>(reader: R) -> DivoomAPIResult<Vec<Pixmap>> {
113+
let mut frames = vec![];
88114

89115
let mut options = gif::DecodeOptions::new();
90116
options.set_color_output(gif::ColorOutput::RGBA);
91117

92-
let mut decoder = options.read_info(input)?;
118+
let mut decoder = options.read_info(reader)?;
93119
while let Some(frame) = decoder.read_next_frame()? {
94120
let mut frame_pixmap = Pixmap::new(frame.width as u32, frame.height as u32).unwrap();
95121
assert_eq!(frame_pixmap.data().len(), frame.buffer.len());
@@ -128,7 +154,7 @@ mod tests {
128154
#[test]
129155
fn divoom_resource_loader_can_load_png_file() {
130156
let frame =
131-
DivoomAnimationResourceLoader::png("test_data/animation_builder_tests/logo.png")
157+
DivoomAnimationResourceLoader::png_file("test_data/animation_builder_tests/logo.png")
132158
.unwrap();
133159

134160
let non_zero_bits_count = frame.data().as_ref().iter().filter(|x| **x != 0u8).count();
@@ -137,7 +163,7 @@ mod tests {
137163

138164
#[test]
139165
fn divoom_resource_loader_can_load_jpeg_grayscale_file() {
140-
let frame = DivoomAnimationResourceLoader::jpeg(
166+
let frame = DivoomAnimationResourceLoader::jpeg_file(
141167
"test_data/animation_builder_tests/logo_grayscale.jpg",
142168
)
143169
.unwrap();
@@ -148,19 +174,21 @@ mod tests {
148174

149175
#[test]
150176
fn divoom_resource_loader_can_load_jpeg_rgb_file() {
151-
let frame =
152-
DivoomAnimationResourceLoader::jpeg("test_data/animation_builder_tests/logo_rgb.jpg")
153-
.unwrap();
177+
let frame = DivoomAnimationResourceLoader::jpeg_file(
178+
"test_data/animation_builder_tests/logo_rgb.jpg",
179+
)
180+
.unwrap();
154181

155182
let non_zero_bits_count = frame.data().as_ref().iter().filter(|x| **x != 0u8).count();
156183
assert_ne!(non_zero_bits_count, 0);
157184
}
158185

159186
#[test]
160187
fn divoom_resource_loader_can_load_jpeg_cmyk_file() {
161-
let frame =
162-
DivoomAnimationResourceLoader::jpeg("test_data/animation_builder_tests/logo_cmyk.jpg")
163-
.unwrap();
188+
let frame = DivoomAnimationResourceLoader::jpeg_file(
189+
"test_data/animation_builder_tests/logo_cmyk.jpg",
190+
)
191+
.unwrap();
164192

165193
let non_zero_bits_count = frame.data().as_ref().iter().filter(|x| **x != 0u8).count();
166194
assert_ne!(non_zero_bits_count, 0);
@@ -169,7 +197,7 @@ mod tests {
169197
#[test]
170198
fn divoom_resource_loader_can_load_gif_file() {
171199
let frames =
172-
DivoomAnimationResourceLoader::gif("test_data/animation_builder_tests/logo.gif")
200+
DivoomAnimationResourceLoader::gif_file("test_data/animation_builder_tests/logo.gif")
173201
.unwrap();
174202
assert_eq!(frames.len(), 1);
175203

divoom/src/clients/pixoo/pixoo_client.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ impl PixooClient {
328328
file_path: &str,
329329
) -> DivoomAPIResult<()> {
330330
let animation_builder = DivoomAnimationBuilder::new(canvas_size, speed)?;
331-
let gif = DivoomAnimationResourceLoader::gif(file_path)?;
331+
let gif = DivoomAnimationResourceLoader::gif_file(file_path)?;
332332
let animation = animation_builder
333333
.draw_frames_fit(
334334
&gif,
@@ -361,7 +361,7 @@ impl PixooClient {
361361
blend: BlendMode,
362362
) -> DivoomAPIResult<()> {
363363
let animation_builder = DivoomAnimationBuilder::new(canvas_size, speed)?;
364-
let gif = DivoomAnimationResourceLoader::gif(file_path)?;
364+
let gif = DivoomAnimationResourceLoader::gif_file(file_path)?;
365365
let animation = animation_builder
366366
.draw_frames_fit(&gif, 0, fit, rotation, opacity, blend)
367367
.build();

divoom_cli/src/main.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -303,9 +303,7 @@ fn new_pixoo_client(common: &DivoomCliDeviceCommandCommonOpts) -> PixooClient {
303303
.device_address
304304
.as_ref()
305305
.expect("Device Address is not set!"),
306-
common
307-
.timeout
308-
.map_or(None, |x| Some(Duration::from_millis(x))),
306+
common.timeout.map(|x| Duration::from_millis(x)),
309307
)
310308
}
311309

0 commit comments

Comments
 (0)