Skip to content

Commit

Permalink
u16 output format
Browse files Browse the repository at this point in the history
  • Loading branch information
Constantin Berhard committed Aug 10, 2016
1 parent cb3405d commit 63d4a5c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "sdfgen"
version = "0.2.2"
version = "0.3.0"
authors = [ "Constantin Berhard <[email protected]>" ]

[[bin]]
Expand Down
15 changes: 13 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ You need Rust. The dependencies (image and getopts) are on crates.io so they wil
--save-mipmaps BASENAME
save the mipmaps used for accelerated calculation to
BASENAMEi.png, where 'i' is the mipmap level
-t --type TYPE One of 'png', 'f32', 'f64'. f32 and f64 are raw
floating point formats. Default: png
-t, --type TYPE One of 'png', 'u16', 'f32', 'f64'. f32 and f64 are raw
floating point formats, u16 is raw unsigned 16 bit
integers. Default: png
--threads THREADCOUNT
How many CPU computing threads to use.

Expand Down Expand Up @@ -70,3 +71,13 @@ With normal (bilinear) filtering it would have looked like this:
But this is not all you can do with an SDF texture. Your pixel shader can also map the different distances to different colors. You can simulate this outside OpenGL with [Gimp](http://en.wikipedia.org/wiki/GIMP)s [Gradient Map](http://docs.gimp.org/en/plug-in-gradmap.html) tool (Colors -> Map -> To Gradient).

![artistic shader using SDF](http://cberhard.de/github/sdfgen/catsdfarts.jpg)

### 16 Bit PNG

Unfortunately the image library in use does not (yet?) support exporting PNG images with 16 bit color depth.
You can however use the output mode `u16` and convert it to a PNG16 using ImageMagick like so:

convert -depth 16 -size 512x512 gray:sdf_file -depth 16 out.png

For the `-size` parameter you must use the actual size of the output image.
This is e.g. useful to open the signed distance field in GIMP (version 2.9 or newer) for further manipulation.
28 changes: 24 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn main() {
opts.optopt ("s","size","size of the output signed distance field image, must be a power of 2. Defaults to input size / 4","OUTPUT_SIZE");
opts.optopt ( "","maxdst","saturation distance (i.e. 'most far away meaningful distance') in half pixels of the input image. Defaults to input size / 4","SATURATION_DISTANCE");
opts.optopt ( "","save-mipmaps","save the mipmaps used for accelerated calculation to BASENAMEi.png, where 'i' is the mipmap level","BASENAME");
opts.optopt ("t","type","One of 'png', 'f32', 'f64'. f32 and f64 are raw floating point formats. Default: png","TYPE");
opts.optopt ("t","type","One of 'png', 'u16', 'f32', 'f64'. f32 and f64 are raw floating point formats, u16 is raw unsigned 16 bit integers. Default: png","TYPE");
opts.optopt ( "","threads","How many CPU computing threads to use.","THREADCOUNT");
if args.len() == 1 {
print_usage(&program_name, &opts);
Expand Down Expand Up @@ -95,7 +95,7 @@ fn main() {
};
let n_threads : usize = match parsed_opts.opt_str("threads") {
Some(s) => s.parse::<usize>().unwrap(),
None => 32,
None => 32,
};
if verbose {
println!("Calculating signed distance field of size {} with saturation distance {} using {} thread(s)", sdf_size, sat_dst, n_threads);
Expand All @@ -107,7 +107,7 @@ fn main() {
}
let output_type = match parsed_opts.opt_str("type") {
Some(s) => s,
None => format!("png") // FIXME we don't really need "format!" here
None => format!("png") // FIXME we don't really need "format!" here
};
match output_type.as_ref() {
"png" => {
Expand All @@ -119,9 +119,29 @@ fn main() {
let pngenc = image::png::PNGEncoder::<std::fs::File>::new(outf);
let (w,h) = sdf_u8.dimensions();
pngenc.encode(sdf_u8.into_raw().as_ref(), w, h, image::ColorType::Gray(8)).unwrap();
//sdf_u8.save(output_image_name).unwrap();
}
// TODO: remove code duplication here
"u16" => {
let mut buf = vec![];
for px in sdf.into_raw() {
let mut dst = px;
dst = dst / sat_dst * 32767_f64;
if dst < -32767_f64 {
dst = -32767_f64;
} else if dst > 32767_f64 {
dst = 32767_f64;
}
debug_assert!(dst <= 32767_f64);
debug_assert!(dst >= -32767_f64);
let v:u16 = (dst as i32 + 32767) as u16;
buf.write_u16::<LittleEndian>(v).unwrap();
}
if verbose {
println!("Saving signed distance field image in u16 raw format as '{}'", output_image_name);
}
let mut outf = File::create(output_image_name).unwrap();
outf.write_all(buf.as_ref()).unwrap();
}
"f64" => {
let mut buf = vec![];
for px in sdf.into_raw() {
Expand Down

0 comments on commit 63d4a5c

Please sign in to comment.