├── .gitignore ├── example ├── rust_input.png ├── qrcode_input.png ├── qrcode_output.svg ├── qrcode_output_source.txt ├── rust_output.svg └── rust_output_source.txt ├── Cargo.toml ├── src ├── cli.yml └── main.rs ├── README.md └── LICENSE.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .cargo/ 2 | .vscode/ 3 | target/ 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /example/rust_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/STPR/raster2svg/HEAD/example/rust_input.png -------------------------------------------------------------------------------- /example/qrcode_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/STPR/raster2svg/HEAD/example/qrcode_input.png -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raster2svg" 3 | version = "1.0.14" 4 | authors = ["STPR"] 5 | edition = "2021" 6 | rust-version = "1.58.1" 7 | description = "A tool that use the contour_tracing library." 8 | homepage = "https://github.com/STPR/raster2svg" 9 | repository = "https://github.com/STPR/raster2svg" 10 | readme = "README.md" 11 | keywords = ["contour_tracing", "contour", "boundary", "tracing", "algorithm"] 12 | categories = ["algorithms", "graphics", "multimedia::encoding", "multimedia::images"] 13 | license = "EUPL-1.2" 14 | exclude = [".gitignore", "example/*"] 15 | 16 | [[bin]] 17 | name = "raster2svg" 18 | path = "src/main.rs" 19 | 20 | [profile.release] 21 | lto = true 22 | #panic = "abort" 23 | codegen-units = 1 24 | 25 | [dependencies] 26 | image = "0.24.1" 27 | contour_tracing = { version = "1.0.12", features = ["array"] } 28 | 29 | [dependencies.clap] 30 | version = "2.34.0" 31 | default-features = false 32 | features = ["yaml"] 33 | -------------------------------------------------------------------------------- /example/qrcode_output.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/qrcode_output_source.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/cli.yml: -------------------------------------------------------------------------------- 1 | name: raster2svg 2 | version: "1.0.14" 3 | author: "Copyright (c) 2022, STPR - https://github.com/STPR" 4 | about: "For more information, please visit https://crates.io/crates/raster2svg" 5 | args: 6 | - size: 7 | display_order: 1 8 | short: s 9 | long: size 10 | help: "Add the width, height and viewBox attributes" 11 | - PERCENT: 12 | display_order: 2 13 | short: z 14 | long: zoom 15 | help: "Multiply the width and height attributes by a given percent (e.g. 250)" 16 | takes_value: true 17 | requires: 18 | - size 19 | - COLOR: 20 | display_order: 3 21 | short: l 22 | long: color 23 | help: "Trace only one given color in hex notation RRGGBBAA (e.g. 112233FF)" 24 | takes_value: true 25 | conflicts_with: 26 | - AVCOLOR 27 | - AVCOLOR: 28 | display_order: 4 29 | short: a 30 | long: avcolor 31 | help: "Avoid a given color in hex notation RRGGBBAA (e.g. 112233FF)" 32 | takes_value: true 33 | conflicts_with: 34 | - COLOR 35 | - BGCOLOR: 36 | display_order: 5 37 | short: b 38 | long: bgcolor 39 | help: "Add a background rectangle with a given color in hex notation RRGGBBAA (e.g. 112233FF)" 40 | takes_value: true 41 | - ids: 42 | display_order: 6 43 | short: d 44 | long: ids 45 | help: "Add the RGB colors and opacity values as id attributes" 46 | - inkscape: 47 | display_order: 7 48 | short: k 49 | long: inkscape 50 | help: "Add some Inkscape attributes (transparent background, pixel units, grid, snapping, ...)" 51 | - rendering: 52 | display_order: 8 53 | short: r 54 | long: rendering 55 | help: "Set the shape-rendering attribute to crispEdges" 56 | - closepaths: 57 | display_order: 9 58 | short: c 59 | long: closepaths 60 | help: "Close the paths with the SVG Path Z command" 61 | - INPUT: 62 | display_order: 10 63 | short: i 64 | long: input 65 | help: "Input raster image filename (e.g. input.png)" 66 | required: true 67 | takes_value: true 68 | - OUTPUT: 69 | display_order: 11 70 | short: o 71 | long: output 72 | help: "Output SVG filename (e.g. output.svg)" 73 | required: true 74 | takes_value: true 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # raster2svg [![crates.io][cratesio-img]][cratesio-url] 2 | 3 | A tool that use the contour_tracing library [![Package][package-img]][package-url] 4 | 5 | ## Features 6 | 7 | - Support **RGB colors + alpha channel** (fully transparent colors are not traced) 8 | - Sort the colors from the most used to the less used 9 | - Input format: a raster image file 10 | - Output format: an SVG file 11 | 12 | Features from the contour_tracing library: [![Package][package-img]][package-url] 13 | - Trace contours using the Theo Pavlidis' algorithm (connectivity: 4-connected) 14 | - Trace **outlines** in **clockwise direction** 15 | - Trace **holes** in **counterclockwise direction** 16 | 17 | ## Options 18 | ``` 19 | -s, --size Add the width, height and viewBox attributes 20 | -d, --ids Add the RGB colors and opacity values as id attributes 21 | -k, --inkscape Add some Inkscape attributes (transparent background, pixel units, grid, snapping, ...) 22 | -r, --rendering Set the shape-rendering attribute to crispEdges 23 | -c, --closepaths Close the paths with the SVG Path Z command 24 | 25 | -z, --zoom Multiply the width and height attributes by a given percent (e.g. 250) 26 | -l, --color Trace only one given color in hex notation RRGGBBAA (e.g. 112233FF) 27 | -a, --avcolor Avoid a given color in hex notation RRGGBBAA (e.g. 112233FF) 28 | -b, --bgcolor Add a background rectangle with a given color in hex notation RRGGBBAA (e.g. 112233FF) 29 | -i, --input Input raster image filename (e.g. input.png) 30 | -o, --output Output SVG filename (e.g. output.svg) 31 | ``` 32 | ## An example with some transparent colors 33 | 34 | ``` 35 | C:\>raster2svg.exe -s -d -k -r -i rust_input.png -o rust_output.svg 36 | ``` 37 | - rust_input.png: [![rust_input.png][rust-input-img]][rust-input-url] 38 | 39 | - rust_output.svg: [![rust_output.svg][rust-output-img]][rust-output-url] 40 | 41 | (click on it to view the source) 42 | 43 | ## An example of a zoom by 800% 44 | 45 | [(Thanks Nayuki for your QR Code generator)](https://www.nayuki.io/page/qr-code-generator-library) 46 | 47 | ``` 48 | C:\>raster2svg.exe -s -z 800 -k -r -l 000000ff -b ffffffff -i qrcode_input.png -o qrcode_output.svg 49 | ``` 50 | - qrcode_input.png: [![qrcode_input.png][qrcode-input-img]][qrcode-input-url] 51 | 52 | - qrcode_output.svg: [![qrcode_output.svg][qrcode-output-img]][qrcode-output-url] 53 | 54 | (click on it to view the source) 55 | 56 | ## Informations 57 | 58 | - **Be careful with the size and complexity of your input image because the SVG file size grows rapidly...** 59 | - An already compiled executable is available for Windows on GitHub: [https://github.com/STPR/raster2svg/releases](https://github.com/STPR/raster2svg/releases) 60 | 61 | ## License 62 | 63 | raster2svg 64 | https://github.com/STPR/raster2svg 65 | 66 | Copyright (c) 2022, STPR - https://github.com/STPR 67 | 68 | SPDX-License-Identifier: EUPL-1.2 69 | 70 | ## Contribution 71 | 72 | Your contribution is highly appreciated. Do not hesitate to open an issue or a 73 | pull request. Note that any contribution submitted for inclusion in the project 74 | will be licensed according to the terms given in [LICENSE.txt](LICENSE.txt). 75 | 76 | [cratesio-img]: https://img.shields.io/crates/v/raster2svg.svg 77 | [cratesio-url]: https://crates.io/crates/raster2svg 78 | [package-img]: https://img.shields.io/crates/v/contour_tracing.svg 79 | [package-url]: https://crates.io/crates/contour_tracing 80 | [qrcode-input-img]: https://github.com/STPR/raster2svg/raw/main/example/qrcode_input.png 81 | [qrcode-input-url]: https://github.com/STPR/raster2svg/raw/main/example/qrcode_input.png 82 | [qrcode-output-img]: https://github.com/STPR/raster2svg/raw/main/example/qrcode_output.svg?sanitize=true 83 | [qrcode-output-url]: https://github.com/STPR/raster2svg/raw/main/example/qrcode_output_source.txt 84 | [rust-input-img]: https://github.com/STPR/raster2svg/raw/main/example/rust_input.png 85 | [rust-input-url]: https://github.com/STPR/raster2svg/raw/main/example/rust_input.png 86 | [rust-output-img]: https://github.com/STPR/raster2svg/raw/main/example/rust_output.svg?sanitize=true 87 | [rust-output-url]: https://github.com/STPR/raster2svg/raw/main/example/rust_output_source.txt 88 | -------------------------------------------------------------------------------- /example/rust_output.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/rust_output_source.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * raster2svg 3 | * https://github.com/STPR/raster2svg 4 | * 5 | * Copyright (c) 2022, STPR - https://github.com/STPR 6 | * 7 | * SPDX-License-Identifier: EUPL-1.2 8 | */ 9 | 10 | use image::{GenericImageView, Rgba}; 11 | use contour_tracing::array::bits_to_paths; 12 | use std::{process, collections::BTreeMap, fs::File, io::prelude::*, iter::FromIterator}; 13 | 14 | const OPACITY: [&str; 255] = ["0", "0.00392157", "0.00784314", "0.01176471", "0.01568627", "0.01960784", "0.02352941", "0.02745098", "0.03137255", "0.03529412", "0.03921569", "0.04313725", "0.04705882", "0.05098039", "0.05490196", "0.05882353", "0.0627451", "0.06666667", "0.07058824", "0.0745098", "0.07843137", "0.08235294", "0.08627451", "0.09019608", "0.09411765", "0.09803922", "0.10196078", "0.10588235", "0.10980392", "0.11372549", "0.11764706", "0.12156863", "0.1254902", "0.12941176", "0.13333333", "0.1372549", "0.14117647", "0.14509804", "0.14901961", "0.15294118", "0.15686275", "0.16078431", "0.16470588", "0.16862745", "0.17254902", "0.17647059", "0.18039216", "0.18431373", "0.18823529", "0.19215686", "0.19607843", "0.2", "0.20392157", "0.20784314", "0.21176471", "0.21568627", "0.21960784", "0.22352941", "0.22745098", "0.23137255", "0.23529412", "0.23921569", "0.24313725", "0.24705882", "0.25098039", "0.25490196", "0.25882353", "0.2627451", "0.26666667", "0.27058824", "0.2745098", "0.27843137", "0.28235294", "0.28627451", "0.29019608", "0.29411765", "0.29803922", "0.30196078", "0.30588235", "0.30980392", "0.31372549", "0.31764706", "0.32156863", "0.3254902", "0.32941176", "0.33333333", "0.3372549", "0.34117647", "0.34509804", "0.34901961", "0.35294118", "0.35686275", "0.36078431", "0.36470588", "0.36862745", "0.37254902", "0.37647059", "0.38039216", "0.38431373", "0.38823529", "0.39215686", "0.39607843", "0.4", "0.40392157", "0.40784314", "0.41176471", "0.41568627", "0.41960784", "0.42352941", "0.42745098", "0.43137255", "0.43529412", "0.43921569", "0.44313725", "0.44705882", "0.45098039", "0.45490196", "0.45882353", "0.4627451", "0.46666667", "0.47058824", "0.4745098", "0.47843137", "0.48235294", "0.48627451", "0.49019608", "0.49411765", "0.49803922", "0.50196078", "0.50588235", "0.50980392", "0.51372549", "0.51764706", "0.52156863", "0.5254902", "0.52941176", "0.53333333", "0.5372549", "0.54117647", "0.54509804", "0.54901961", "0.55294118", "0.55686275", "0.56078431", "0.56470588", "0.56862745", "0.57254902", "0.57647059", "0.58039216", "0.58431373", "0.58823529", "0.59215686", "0.59607843", "0.6", "0.60392157", "0.60784314", "0.61176471", "0.61568627", "0.61960784", "0.62352941", "0.62745098", "0.63137255", "0.63529412", "0.63921569", "0.64313725", "0.64705882", "0.65098039", "0.65490196", "0.65882353", "0.6627451", "0.66666667", "0.67058824", "0.6745098", "0.67843137", "0.68235294", "0.68627451", "0.69019608", "0.69411765", "0.69803922", "0.70196078", "0.70588235", "0.70980392", "0.71372549", "0.71764706", "0.72156863", "0.7254902", "0.72941176", "0.73333333", "0.7372549", "0.74117647", "0.74509804", "0.74901961", "0.75294118", "0.75686275", "0.76078431", "0.76470588", "0.76862745", "0.77254902", "0.77647059", "0.78039216", "0.78431373", "0.78823529", "0.79215686", "0.79607843", "0.8", "0.80392157", "0.80784314", "0.81176471", "0.81568627", "0.81960784", "0.82352941", "0.82745098", "0.83137255", "0.83529412", "0.83921569", "0.84313725", "0.84705882", "0.85098039", "0.85490196", "0.85882353", "0.8627451", "0.86666667", "0.87058824", "0.8745098", "0.87843137", "0.88235294", "0.88627451", "0.89019608", "0.89411765", "0.89803922", "0.90196078", "0.90588235", "0.90980392", "0.91372549", "0.91764706", "0.92156863", "0.9254902", "0.92941176", "0.93333333", "0.9372549", "0.94117647", "0.94509804", "0.94901961", "0.95294118", "0.95686275", "0.96078431", "0.96470588", "0.96862745", "0.97254902", "0.97647059", "0.98039216", "0.98431373", "0.98823529", "0.99215686", "0.99607843"]; 15 | 16 | fn string_to_color(string: &str) -> Option> { 17 | for c in string.chars() { 18 | if !c.is_digit(16) { 19 | return None; 20 | } 21 | } 22 | unsafe { 23 | if string.chars().count() == 8 { 24 | Some(Rgba::([u8::from_str_radix(string.get_unchecked(0..2), 16).unwrap(), u8::from_str_radix(string.get_unchecked(2..4), 16).unwrap(), u8::from_str_radix(string.get_unchecked(4..6), 16).unwrap(), u8::from_str_radix(string.get_unchecked(6..8), 16).unwrap()])) 25 | } else { 26 | None 27 | } 28 | } 29 | } 30 | 31 | fn main() -> Result<(), std::io::Error> { 32 | 33 | use clap::{load_yaml, App, AppSettings}; 34 | let cli_yaml = load_yaml!("cli.yml"); 35 | let m = App::from_yaml(cli_yaml).setting(AppSettings::ArgRequiredElseHelp).get_matches(); 36 | 37 | let size: bool = m.is_present("size"); 38 | let zoom: u32; 39 | if m.is_present("PERCENT") { 40 | zoom = match m.value_of("PERCENT") { 41 | Some(zoom) => zoom.parse().unwrap_or(100), 42 | None => { 43 | println!("{}", m.usage()); 44 | process::exit(1); 45 | } 46 | }; 47 | } else { 48 | zoom = 100; 49 | } 50 | let color_rgba: Rgba; 51 | if m.is_present("COLOR") { 52 | color_rgba = match string_to_color(m.value_of("COLOR").unwrap()) { 53 | Some(color_rgba) => color_rgba, 54 | None => { 55 | println!("{}", m.usage()); 56 | process::exit(1); 57 | } 58 | }; 59 | } else { 60 | color_rgba = Rgba::([0, 0, 0, 0]); 61 | } 62 | let avcolor_rgba: Rgba; 63 | if m.is_present("AVCOLOR") { 64 | avcolor_rgba = match string_to_color(m.value_of("AVCOLOR").unwrap()) { 65 | Some(avcolor_rgba) => avcolor_rgba, 66 | None => { 67 | println!("{}", m.usage()); 68 | process::exit(1); 69 | } 70 | }; 71 | } else { 72 | avcolor_rgba = Rgba::([0, 0, 0, 0]); 73 | } 74 | let bgcolor_rgba: Rgba; 75 | if m.is_present("BGCOLOR") { 76 | bgcolor_rgba = match string_to_color(m.value_of("BGCOLOR").unwrap()) { 77 | Some(bgcolor_rgba) => bgcolor_rgba, 78 | None => { 79 | println!("{}", m.usage()); 80 | process::exit(1); 81 | } 82 | }; 83 | } else { 84 | bgcolor_rgba = Rgba::([0, 0, 0, 0]); 85 | } 86 | let ids: bool = m.is_present("ids"); 87 | let inkscape: bool = m.is_present("inkscape"); 88 | let rendering: bool = m.is_present("rendering"); 89 | let closepaths: bool = m.is_present("closepaths"); 90 | let input = match m.value_of("INPUT") { 91 | Some(input) => input, 92 | None => { 93 | println!("{}", m.usage()); 94 | process::exit(1); 95 | } 96 | }; 97 | let output = match m.value_of("OUTPUT") { 98 | Some(output) => output, 99 | None => { 100 | println!("{}", m.usage()); 101 | process::exit(1); 102 | } 103 | }; 104 | 105 | let raster = image::open(input).expect("Error while opening the raster image file !"); 106 | let (raster_x, raster_y) = raster.dimensions(); 107 | let zoomed_x: u32; 108 | let zoomed_y: u32; 109 | if m.is_present("PERCENT") { 110 | zoomed_x = (raster_x as f64 * (zoom as f64 / 100.0)).round() as u32; 111 | zoomed_y = (raster_y as f64 * (zoom as f64 / 100.0)).round() as u32; 112 | } else { 113 | zoomed_x = raster_x; 114 | zoomed_y = raster_y; 115 | } 116 | 117 | // FIRST PHASE: Count and sort the colors from the most used to the less used 118 | let mut number_of_colors: usize = 0; 119 | let mut sorted_colors; 120 | if m.is_present("COLOR") { 121 | for p in raster.pixels() { 122 | if p.2 == color_rgba { 123 | number_of_colors = 1; 124 | break; 125 | }; 126 | } 127 | sorted_colors = vec![([color_rgba[0], color_rgba[1], color_rgba[2], color_rgba[3]], 1)]; 128 | } else { 129 | let mut colors = BTreeMap::new(); // Use BTreeMap instead of HashMap to ensure the same arrangement each time (but slower) 130 | if m.is_present("AVCOLOR") { 131 | for p in raster.pixels() { 132 | if !(p.2[3] == 0 || p.2 == avcolor_rgba) { 133 | *colors.entry((p.2).0).or_insert(0) += 1; 134 | } 135 | } 136 | } else { 137 | for p in raster.pixels() { 138 | if p.2[3] != 0 { 139 | *colors.entry((p.2).0).or_insert(0) += 1; 140 | } 141 | } 142 | } 143 | number_of_colors = colors.len(); 144 | sorted_colors = Vec::from_iter(colors); 145 | sorted_colors.sort_by(|&(_, a), &(_, b)| a.cmp(&b).reverse()); 146 | } 147 | // END OF THE FIRST PHASE 148 | 149 | let create_file: bool = number_of_colors > 0; 150 | let file_ref = if create_file { Some(File::create(output)?) } else { None }; 151 | if create_file { 152 | if let Some(mut fsvg) = file_ref.as_ref() { 153 | let mut header: String = format!(r#"{}"#, "\n"); 160 | header += &format!(r#"{}"#, "\n"); 161 | } 162 | write!(fsvg, "{}", header)?; 163 | 164 | if m.is_present("BGCOLOR") { 165 | if bgcolor_rgba[3] == 255 { 166 | writeln!(fsvg, r#""#, raster_x, raster_y, bgcolor_rgba[0], bgcolor_rgba[1], bgcolor_rgba[2])?; 167 | } else { 168 | writeln!(fsvg, r#""#, raster_x, raster_y, bgcolor_rgba[0], bgcolor_rgba[1], bgcolor_rgba[2], OPACITY[bgcolor_rgba[3] as usize])?; 169 | } 170 | } 171 | 172 | for color in sorted_colors.into_iter() { 173 | let red: u8 = color.0[0]; 174 | let green: u8 = color.0[1]; 175 | let blue: u8 = color.0[2]; 176 | let alpha: usize = color.0[3] as usize; 177 | 178 | if alpha == 255 { 179 | write!(fsvg, ""#)?; 206 | } 207 | writeln!(fsvg, "")?; 208 | } 209 | } 210 | 211 | println!("raster2svg 1.0.14\nCopyright (c) 2022, STPR - https://github.com/STPR\nFor more information, please visit https://crates.io/crates/raster2svg\n"); 212 | println!("Input size: {} x {}", raster_x, raster_y); 213 | if m.is_present("PERCENT") { 214 | println!("Zoom: {} %\nZoomed size: {} x {}", zoom, zoomed_x, zoomed_y); 215 | } 216 | println!("Number of colors traced: {}\n", number_of_colors); 217 | if create_file { println!("Done.") } else { println!("No output file has been created...") }; 218 | Ok(()) 219 | } 220 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | EUROPEAN UNION PUBLIC LICENCE v. 1.2 2 | EUPL © the European Union 2007, 2016 3 | 4 | This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined 5 | below) which is provided under the terms of this Licence. Any use of the Work, 6 | other than as authorised under this Licence is prohibited (to the extent such 7 | use is covered by a right of the copyright holder of the Work). 8 | 9 | The Work is provided under the terms of this Licence when the Licensor (as 10 | defined below) has placed the following notice immediately following the 11 | copyright notice for the Work: 12 | 13 | Licensed under the EUPL 14 | 15 | or has expressed by any other means his willingness to license under the EUPL. 16 | 17 | 1. Definitions 18 | 19 | In this Licence, the following terms have the following meaning: 20 | 21 | - ‘The Licence’: this Licence. 22 | 23 | - ‘The Original Work’: the work or software distributed or communicated by the 24 | Licensor under this Licence, available as Source Code and also as Executable 25 | Code as the case may be. 26 | 27 | - ‘Derivative Works’: the works or software that could be created by the 28 | Licensee, based upon the Original Work or modifications thereof. This Licence 29 | does not define the extent of modification or dependence on the Original Work 30 | required in order to classify a work as a Derivative Work; this extent is 31 | determined by copyright law applicable in the country mentioned in Article 15. 32 | 33 | - ‘The Work’: the Original Work or its Derivative Works. 34 | 35 | - ‘The Source Code’: the human-readable form of the Work which is the most 36 | convenient for people to study and modify. 37 | 38 | - ‘The Executable Code’: any code which has generally been compiled and which is 39 | meant to be interpreted by a computer as a program. 40 | 41 | - ‘The Licensor’: the natural or legal person that distributes or communicates 42 | the Work under the Licence. 43 | 44 | - ‘Contributor(s)’: any natural or legal person who modifies the Work under the 45 | Licence, or otherwise contributes to the creation of a Derivative Work. 46 | 47 | - ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of 48 | the Work under the terms of the Licence. 49 | 50 | - ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, 51 | renting, distributing, communicating, transmitting, or otherwise making 52 | available, online or offline, copies of the Work or providing access to its 53 | essential functionalities at the disposal of any other natural or legal 54 | person. 55 | 56 | 2. Scope of the rights granted by the Licence 57 | 58 | The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, 59 | sublicensable licence to do the following, for the duration of copyright vested 60 | in the Original Work: 61 | 62 | - use the Work in any circumstance and for all usage, 63 | - reproduce the Work, 64 | - modify the Work, and make Derivative Works based upon the Work, 65 | - communicate to the public, including the right to make available or display 66 | the Work or copies thereof to the public and perform publicly, as the case may 67 | be, the Work, 68 | - distribute the Work or copies thereof, 69 | - lend and rent the Work or copies thereof, 70 | - sublicense rights in the Work or copies thereof. 71 | 72 | Those rights can be exercised on any media, supports and formats, whether now 73 | known or later invented, as far as the applicable law permits so. 74 | 75 | In the countries where moral rights apply, the Licensor waives his right to 76 | exercise his moral right to the extent allowed by law in order to make effective 77 | the licence of the economic rights here above listed. 78 | 79 | The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to 80 | any patents held by the Licensor, to the extent necessary to make use of the 81 | rights granted on the Work under this Licence. 82 | 83 | 3. Communication of the Source Code 84 | 85 | The Licensor may provide the Work either in its Source Code form, or as 86 | Executable Code. If the Work is provided as Executable Code, the Licensor 87 | provides in addition a machine-readable copy of the Source Code of the Work 88 | along with each copy of the Work that the Licensor distributes or indicates, in 89 | a notice following the copyright notice attached to the Work, a repository where 90 | the Source Code is easily and freely accessible for as long as the Licensor 91 | continues to distribute or communicate the Work. 92 | 93 | 4. Limitations on copyright 94 | 95 | Nothing in this Licence is intended to deprive the Licensee of the benefits from 96 | any exception or limitation to the exclusive rights of the rights owners in the 97 | Work, of the exhaustion of those rights or of other applicable limitations 98 | thereto. 99 | 100 | 5. Obligations of the Licensee 101 | 102 | The grant of the rights mentioned above is subject to some restrictions and 103 | obligations imposed on the Licensee. Those obligations are the following: 104 | 105 | Attribution right: The Licensee shall keep intact all copyright, patent or 106 | trademarks notices and all notices that refer to the Licence and to the 107 | disclaimer of warranties. The Licensee must include a copy of such notices and a 108 | copy of the Licence with every copy of the Work he/she distributes or 109 | communicates. The Licensee must cause any Derivative Work to carry prominent 110 | notices stating that the Work has been modified and the date of modification. 111 | 112 | Copyleft clause: If the Licensee distributes or communicates copies of the 113 | Original Works or Derivative Works, this Distribution or Communication will be 114 | done under the terms of this Licence or of a later version of this Licence 115 | unless the Original Work is expressly distributed only under this version of the 116 | Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee 117 | (becoming Licensor) cannot offer or impose any additional terms or conditions on 118 | the Work or Derivative Work that alter or restrict the terms of the Licence. 119 | 120 | Compatibility clause: If the Licensee Distributes or Communicates Derivative 121 | Works or copies thereof based upon both the Work and another work licensed under 122 | a Compatible Licence, this Distribution or Communication can be done under the 123 | terms of this Compatible Licence. For the sake of this clause, ‘Compatible 124 | Licence’ refers to the licences listed in the appendix attached to this Licence. 125 | Should the Licensee's obligations under the Compatible Licence conflict with 126 | his/her obligations under this Licence, the obligations of the Compatible 127 | Licence shall prevail. 128 | 129 | Provision of Source Code: When distributing or communicating copies of the Work, 130 | the Licensee will provide a machine-readable copy of the Source Code or indicate 131 | a repository where this Source will be easily and freely available for as long 132 | as the Licensee continues to distribute or communicate the Work. 133 | 134 | Legal Protection: This Licence does not grant permission to use the trade names, 135 | trademarks, service marks, or names of the Licensor, except as required for 136 | reasonable and customary use in describing the origin of the Work and 137 | reproducing the content of the copyright notice. 138 | 139 | 6. Chain of Authorship 140 | 141 | The original Licensor warrants that the copyright in the Original Work granted 142 | hereunder is owned by him/her or licensed to him/her and that he/she has the 143 | power and authority to grant the Licence. 144 | 145 | Each Contributor warrants that the copyright in the modifications he/she brings 146 | to the Work are owned by him/her or licensed to him/her and that he/she has the 147 | power and authority to grant the Licence. 148 | 149 | Each time You accept the Licence, the original Licensor and subsequent 150 | Contributors grant You a licence to their contributions to the Work, under the 151 | terms of this Licence. 152 | 153 | 7. Disclaimer of Warranty 154 | 155 | The Work is a work in progress, which is continuously improved by numerous 156 | Contributors. It is not a finished work and may therefore contain defects or 157 | ‘bugs’ inherent to this type of development. 158 | 159 | For the above reason, the Work is provided under the Licence on an ‘as is’ basis 160 | and without warranties of any kind concerning the Work, including without 161 | limitation merchantability, fitness for a particular purpose, absence of defects 162 | or errors, accuracy, non-infringement of intellectual property rights other than 163 | copyright as stated in Article 6 of this Licence. 164 | 165 | This disclaimer of warranty is an essential part of the Licence and a condition 166 | for the grant of any rights to the Work. 167 | 168 | 8. Disclaimer of Liability 169 | 170 | Except in the cases of wilful misconduct or damages directly caused to natural 171 | persons, the Licensor will in no event be liable for any direct or indirect, 172 | material or moral, damages of any kind, arising out of the Licence or of the use 173 | of the Work, including without limitation, damages for loss of goodwill, work 174 | stoppage, computer failure or malfunction, loss of data or any commercial 175 | damage, even if the Licensor has been advised of the possibility of such damage. 176 | However, the Licensor will be liable under statutory product liability laws as 177 | far such laws apply to the Work. 178 | 179 | 9. Additional agreements 180 | 181 | While distributing the Work, You may choose to conclude an additional agreement, 182 | defining obligations or services consistent with this Licence. However, if 183 | accepting obligations, You may act only on your own behalf and on your sole 184 | responsibility, not on behalf of the original Licensor or any other Contributor, 185 | and only if You agree to indemnify, defend, and hold each Contributor harmless 186 | for any liability incurred by, or claims asserted against such Contributor by 187 | the fact You have accepted any warranty or additional liability. 188 | 189 | 10. Acceptance of the Licence 190 | 191 | The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ 192 | placed under the bottom of a window displaying the text of this Licence or by 193 | affirming consent in any other similar way, in accordance with the rules of 194 | applicable law. Clicking on that icon indicates your clear and irrevocable 195 | acceptance of this Licence and all of its terms and conditions. 196 | 197 | Similarly, you irrevocably accept this Licence and all of its terms and 198 | conditions by exercising any rights granted to You by Article 2 of this Licence, 199 | such as the use of the Work, the creation by You of a Derivative Work or the 200 | Distribution or Communication by You of the Work or copies thereof. 201 | 202 | 11. Information to the public 203 | 204 | In case of any Distribution or Communication of the Work by means of electronic 205 | communication by You (for example, by offering to download the Work from a 206 | remote location) the distribution channel or media (for example, a website) must 207 | at least provide to the public the information requested by the applicable law 208 | regarding the Licensor, the Licence and the way it may be accessible, concluded, 209 | stored and reproduced by the Licensee. 210 | 211 | 12. Termination of the Licence 212 | 213 | The Licence and the rights granted hereunder will terminate automatically upon 214 | any breach by the Licensee of the terms of the Licence. 215 | 216 | Such a termination will not terminate the licences of any person who has 217 | received the Work from the Licensee under the Licence, provided such persons 218 | remain in full compliance with the Licence. 219 | 220 | 13. Miscellaneous 221 | 222 | Without prejudice of Article 9 above, the Licence represents the complete 223 | agreement between the Parties as to the Work. 224 | 225 | If any provision of the Licence is invalid or unenforceable under applicable 226 | law, this will not affect the validity or enforceability of the Licence as a 227 | whole. Such provision will be construed or reformed so as necessary to make it 228 | valid and enforceable. 229 | 230 | The European Commission may publish other linguistic versions or new versions of 231 | this Licence or updated versions of the Appendix, so far this is required and 232 | reasonable, without reducing the scope of the rights granted by the Licence. New 233 | versions of the Licence will be published with a unique version number. 234 | 235 | All linguistic versions of this Licence, approved by the European Commission, 236 | have identical value. Parties can take advantage of the linguistic version of 237 | their choice. 238 | 239 | 14. Jurisdiction 240 | 241 | Without prejudice to specific agreement between parties, 242 | 243 | - any litigation resulting from the interpretation of this License, arising 244 | between the European Union institutions, bodies, offices or agencies, as a 245 | Licensor, and any Licensee, will be subject to the jurisdiction of the Court 246 | of Justice of the European Union, as laid down in article 272 of the Treaty on 247 | the Functioning of the European Union, 248 | 249 | - any litigation arising between other parties and resulting from the 250 | interpretation of this License, will be subject to the exclusive jurisdiction 251 | of the competent court where the Licensor resides or conducts its primary 252 | business. 253 | 254 | 15. Applicable Law 255 | 256 | Without prejudice to specific agreement between parties, 257 | 258 | - this Licence shall be governed by the law of the European Union Member State 259 | where the Licensor has his seat, resides or has his registered office, 260 | 261 | - this licence shall be governed by Belgian law if the Licensor has no seat, 262 | residence or registered office inside a European Union Member State. 263 | 264 | Appendix 265 | 266 | ‘Compatible Licences’ according to Article 5 EUPL are: 267 | 268 | - GNU General Public License (GPL) v. 2, v. 3 269 | - GNU Affero General Public License (AGPL) v. 3 270 | - Open Software License (OSL) v. 2.1, v. 3.0 271 | - Eclipse Public License (EPL) v. 1.0 272 | - CeCILL v. 2.0, v. 2.1 273 | - Mozilla Public Licence (MPL) v. 2 274 | - GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 275 | - Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for 276 | works other than software 277 | - European Union Public Licence (EUPL) v. 1.1, v. 1.2 278 | - Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong 279 | Reciprocity (LiLiQ-R+). 280 | 281 | The European Commission may update this Appendix to later versions of the above 282 | licences without producing a new version of the EUPL, as long as they provide 283 | the rights granted in Article 2 of this Licence and protect the covered Source 284 | Code from exclusive appropriation. 285 | 286 | All other changes or additions to this Appendix require the production of a new 287 | EUPL version. 288 | --------------------------------------------------------------------------------