Merge branch 'master' of github.com:timvisee/pixelpwnr
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -221,6 +221,7 @@ dependencies = [
|
||||
"bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
||||
@@ -7,4 +7,5 @@ authors = ["Tim Visée <timvisee@gmail.com>"]
|
||||
bufstream = "0.1"
|
||||
clap = "2.29"
|
||||
image = "0.18"
|
||||
num_cpus = "1.8"
|
||||
regex = "0.2"
|
||||
|
||||
37
README.md
37
README.md
@@ -39,11 +39,14 @@ Pixelflut an animated image:
|
||||
pixelpwnr 127.0.0.1:8080 -i *.png --fps 5 -c 4 -w 400 -h 400 -x 100 -y 100
|
||||
```
|
||||
|
||||
Use the `--help` flag, or see the [help](#help) section for all available
|
||||
options.
|
||||
|
||||
## Installation
|
||||
For installation, Git and Rust cargo are required.
|
||||
Install the latest version of Rust with [rustup][rustup].
|
||||
|
||||
Then, clone and install pixelpwnr with:
|
||||
Then, clone and install `pixelpwnr` with:
|
||||
|
||||
```bash
|
||||
# Clone the project
|
||||
@@ -60,7 +63,7 @@ pixelpwnr --help
|
||||
cargo run --release -- --help
|
||||
```
|
||||
|
||||
Or just build it and invoke the binary directly:
|
||||
Or just build it and invoke the binary directly (Linux/macOS):
|
||||
|
||||
```bash
|
||||
# Clone the project
|
||||
@@ -74,6 +77,28 @@ cargo build --release
|
||||
./target/release/pixelpwnr --help
|
||||
```
|
||||
|
||||
## Performance & speed optimization
|
||||
There are many things that affect how quickly pixels can be painted on a
|
||||
pixelflut server.
|
||||
Some of them are:
|
||||
- Size of the image that is drawn.
|
||||
- Amount of connections used to push pixels.
|
||||
- Performance of the machine `pixelpwnr` is running on.
|
||||
- Network interface performance of the client.
|
||||
- Network interface performance of the server.
|
||||
- Performance of the pixelflut server.
|
||||
|
||||
Things that improve painting performance:
|
||||
- Use a wired connection.
|
||||
- Use a LAN connection, closely linked to the pixelflut server. The lower
|
||||
latency the better, due to the connection being over TCP.
|
||||
- Use as many threads (`-c` flag) as the server, your connection and your
|
||||
machine allows.
|
||||
- Paint a smaller image (`-w`, `-h` flags).
|
||||
- Paint in an area on the screen, where the least other things are pained.
|
||||
- Use multiple machines (servers) with multiple `pixelpwnr` instances to push
|
||||
pixels to the screen.
|
||||
|
||||
## Help
|
||||
```text
|
||||
pixelpwnr --help
|
||||
@@ -93,9 +118,9 @@ OPTIONS:
|
||||
-i, --image <PATH>... Image paths
|
||||
-w, --width <PIXELS> Draw width (def: screen width)
|
||||
-h, --height <PIXELS> Draw height (def: screen height)
|
||||
-x, --x <PIXELS> Draw X offset (def: 0)
|
||||
-y, --y <PIXELS> Draw Y offset (def: 0)
|
||||
-c, --count <COUNT> Number of concurrent threads (def: 4)
|
||||
-x <PIXELS> Draw X offset (def: 0)
|
||||
-y <PIXELS> Draw Y offset (def: 0)
|
||||
-c, --count <COUNT> Number of concurrent threads (def: CPUs)
|
||||
-r, --fps <RATE> Frames per second with multiple images (def: 1)
|
||||
|
||||
ARGS:
|
||||
@@ -110,5 +135,5 @@ Check out the [LICENSE](LICENSE) file for more information.
|
||||
[34C3]: https://events.ccc.de/congress/2017/wiki/index.php/Main_Page
|
||||
[pixelflut]: https://cccgoe.de/wiki/Pixelflut
|
||||
[pixelflut-video]: https://vimeo.com/92827556/
|
||||
[rust]: https://rust-lang.org/
|
||||
[rust]: https://www.rust-lang.org/
|
||||
[rustup]: https://rustup.rs/
|
||||
|
||||
19
TODO.md
19
TODO.md
@@ -1,10 +1,19 @@
|
||||
# TODO
|
||||
- Don't draw pixels outside screen.
|
||||
- Resolve relative paths, or paths with a `~` correctly.
|
||||
- Add alpha support.
|
||||
- Do not draw invisible (alpha) pixels.
|
||||
- Read size from screen.
|
||||
- Instantly update images in painter threads,
|
||||
not just when the stopped drawing.
|
||||
- Process all images at start.
|
||||
- Combine many pixel messages to improve performance.
|
||||
- Create a small listening server, to benchmark throughput.
|
||||
|
||||
# Further optimizations
|
||||
- Process and slice all images before starting, don't process them each frame
|
||||
again.
|
||||
- Create a pixel map at start, instead of continuously getting pixels from the
|
||||
image.
|
||||
- Convert whole image blocks to a single large command string, to push in one
|
||||
piece to the pixelflut server. Instead of pushing each pixel command
|
||||
separately.
|
||||
- Do not draw transparant (alpha) pixels.
|
||||
- Do not draw pixels outside the screen size.
|
||||
- Further control buffering in drawing pipes.
|
||||
- Allow UDP mode (for pixelflut servers that support it).
|
||||
|
||||
@@ -4,8 +4,5 @@ pub const APP_VERSION: &'static str = "0.1";
|
||||
pub const APP_AUTHOR: &'static str = "Tim Visee <timvisee@gmail.com>";
|
||||
pub const APP_ABOUT: &'static str = "A quick pixelflut client, that pwns pixelflut panels.";
|
||||
|
||||
// The default thread count
|
||||
pub const DEFAULT_THREAD_COUNT: usize = 4;
|
||||
|
||||
// The default frames per second rate
|
||||
pub const DEFAULT_IMAGE_FPS: u32 = 1;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
extern crate clap;
|
||||
extern crate num_cpus;
|
||||
|
||||
use clap::{Arg, ArgMatches, App};
|
||||
|
||||
@@ -50,14 +51,12 @@ impl<'a: 'b, 'b> ArgHandler<'a> {
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("x")
|
||||
.short("x")
|
||||
.long("x")
|
||||
.value_name("PIXELS")
|
||||
.help("Draw X offset (def: 0)")
|
||||
.display_order(4)
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("y")
|
||||
.short("y")
|
||||
.long("y")
|
||||
.value_name("PIXELS")
|
||||
.help("Draw Y offset (def: 0)")
|
||||
.display_order(5)
|
||||
@@ -68,7 +67,7 @@ impl<'a: 'b, 'b> ArgHandler<'a> {
|
||||
.alias("thread")
|
||||
.alias("threads")
|
||||
.value_name("COUNT")
|
||||
.help("Number of concurrent threads (def: 4)")
|
||||
.help("Number of concurrent threads (def: CPUs)")
|
||||
.display_order(6)
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("fps")
|
||||
@@ -95,9 +94,10 @@ impl<'a: 'b, 'b> ArgHandler<'a> {
|
||||
/// Get the thread count.
|
||||
pub fn count(&self) -> usize {
|
||||
self.matches.value_of("count")
|
||||
.unwrap_or(&format!("{}", DEFAULT_THREAD_COUNT))
|
||||
.parse::<usize>()
|
||||
.expect("Invalid count specified")
|
||||
.map(|count| count.parse::<usize>()
|
||||
.expect("Invalid count specified")
|
||||
)
|
||||
.unwrap_or(num_cpus::get())
|
||||
}
|
||||
|
||||
/// Get the image paths.
|
||||
@@ -112,17 +112,19 @@ impl<'a: 'b, 'b> ArgHandler<'a> {
|
||||
pub fn size(&self, def: Option<(u32, u32)>) -> (u32, u32) {
|
||||
(
|
||||
self.matches.value_of("width")
|
||||
.unwrap_or(
|
||||
&format!("{}", def.expect("No screen width set or known").0)
|
||||
.map(|width| width.parse::<u32>()
|
||||
.expect("Invalid image width")
|
||||
)
|
||||
.parse::<u32>()
|
||||
.expect("Invalid image width"),
|
||||
.unwrap_or(
|
||||
def.expect("No screen width set or known").0
|
||||
),
|
||||
self.matches.value_of("height")
|
||||
.unwrap_or(
|
||||
&format!("{}", def.expect("No screen height set or known").1)
|
||||
.map(|height| height.parse::<u32>()
|
||||
.expect("Invalid image height")
|
||||
)
|
||||
.parse::<u32>()
|
||||
.expect("Invalid image height"),
|
||||
.unwrap_or(
|
||||
def.expect("No screen height set or known").1
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -130,21 +132,24 @@ impl<'a: 'b, 'b> ArgHandler<'a> {
|
||||
pub fn offset(&self) -> (u32, u32) {
|
||||
(
|
||||
self.matches.value_of("x")
|
||||
.unwrap_or("0")
|
||||
.parse::<u32>()
|
||||
.expect("Invalid X offset"),
|
||||
.map(|x| x.parse::<u32>()
|
||||
.expect("Invalid X offset")
|
||||
)
|
||||
.unwrap_or(0),
|
||||
self.matches.value_of("y")
|
||||
.unwrap_or("0")
|
||||
.parse::<u32>()
|
||||
.expect("Invalid Y offset"),
|
||||
.map(|y| y.parse::<u32>()
|
||||
.expect("Invalid Y offset")
|
||||
)
|
||||
.unwrap_or(0),
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the FPS.
|
||||
pub fn fps(&self) -> u32 {
|
||||
self.matches.value_of("fps")
|
||||
.unwrap_or(&format!("{}", DEFAULT_IMAGE_FPS))
|
||||
.parse::<u32>()
|
||||
.expect("Invalid frames per second rate")
|
||||
.map(|fps| fps.parse::<u32>()
|
||||
.expect("Invalid frames per second rate")
|
||||
)
|
||||
.unwrap_or(DEFAULT_IMAGE_FPS)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// Re-export modules
|
||||
// Reexport modules
|
||||
pub mod painter;
|
||||
pub mod handle;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// Re-export modules
|
||||
// Reexport modules
|
||||
pub mod canvas;
|
||||
pub mod client;
|
||||
|
||||
Reference in New Issue
Block a user