Added RST image parsing
+ Added DIP project
This commit is contained in:
		
							parent
							
								
									9fbad90eb8
								
							
						
					
					
						commit
						68ecb118a9
					
				
							
								
								
									
										31
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -5,9 +5,10 @@ extern crate rocket; | ||||
| #[macro_use] | ||||
| extern crate serde_derive; | ||||
| 
 | ||||
| mod rst_parser; | ||||
| mod tests; | ||||
| mod rst_parser; | ||||
| 
 | ||||
| use crate::rst_parser::parse_images; | ||||
| use regex::Regex; | ||||
| use rocket::Request; | ||||
| use rocket_contrib::serve::StaticFiles; | ||||
| @ -16,9 +17,9 @@ use rst_parser::parse_links; | ||||
| use std::collections::HashMap; | ||||
| use std::error; | ||||
| use std::fmt; | ||||
| use std::path::{PathBuf, Path}; | ||||
| use std::{fs, io}; | ||||
| use std::io::Error; | ||||
| use std::path::{Path, PathBuf}; | ||||
| use std::{fs, io}; | ||||
| 
 | ||||
| type PageResult<T> = std::result::Result<T, JSiteError>; | ||||
| 
 | ||||
| @ -117,7 +118,7 @@ fn get_pages(path: &str, pages: &mut Vec<SiteFile>) -> io::Result<()> { | ||||
|             } else { | ||||
|                 match rank.parse() { | ||||
|                     Ok(r) => r, | ||||
|                     Err(_) => std::u32::MAX | ||||
|                     Err(_) => std::u32::MAX, | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
| @ -144,16 +145,15 @@ fn get_pages(path: &str, pages: &mut Vec<SiteFile>) -> io::Result<()> { | ||||
| /// * `page_name` - file to look for
 | ||||
| fn get_page(path: &Path) -> PageResult<SiteFile> { | ||||
|     let file_name = path.file_name().ok_or(PageNotFoundError)?; | ||||
|     let file_name =  file_name.to_str().ok_or(PageNotFoundError)?.to_string(); | ||||
|     let file_name = file_name.to_str().ok_or(PageNotFoundError)?.to_string(); | ||||
|     if path.exists() { | ||||
|         return Ok(SiteFile { | ||||
|             rank: 0, | ||||
|             file_name: file_name.clone(), | ||||
|             link_name: file_name, | ||||
|             path: path.to_path_buf() | ||||
|         }) | ||||
|     } | ||||
|     else { | ||||
|             path: path.to_path_buf(), | ||||
|         }); | ||||
|     } else { | ||||
|         let mut dir_path = path.to_path_buf(); | ||||
|         dir_path.pop(); | ||||
| 
 | ||||
| @ -166,8 +166,8 @@ fn get_page(path: &Path) -> PageResult<SiteFile> { | ||||
|                     rank: 0, | ||||
|                     file_name: entry_name, | ||||
|                     link_name: file_name, | ||||
|                     path: entry.path() | ||||
|                 }) | ||||
|                     path: entry.path(), | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -191,9 +191,7 @@ fn rst_page(page: PathBuf) -> Template { | ||||
|     path.push(page); | ||||
| 
 | ||||
|     // Try and get the page
 | ||||
|     let site_page = match get_page( | ||||
|         path.as_path() | ||||
|     ) { | ||||
|     let site_page = match get_page(path.as_path()) { | ||||
|         Ok(site_page) => site_page, | ||||
|         Err(_) => { | ||||
|             return error_page(path.to_str().unwrap()); | ||||
| @ -206,7 +204,7 @@ fn rst_page(page: PathBuf) -> Template { | ||||
|         let mut sub_files: Vec<SiteFile> = Vec::new(); | ||||
|         match get_pages(site_page.path.to_str().unwrap(), &mut sub_files) { | ||||
|             Ok(_) => (), | ||||
|             Err(_) => return error_page(&site_page.link_name) | ||||
|             Err(_) => return error_page(&site_page.link_name), | ||||
|         } | ||||
| 
 | ||||
|         let page_data = PageData { | ||||
| @ -229,7 +227,8 @@ fn rst_page(page: PathBuf) -> Template { | ||||
|         }; | ||||
| 
 | ||||
|         // Render links
 | ||||
|         let mut contents = parse_links(&contents); | ||||
|         let mut contents = parse_links(&contents).unwrap(); | ||||
|         contents = parse_images(contents.as_str()).unwrap(); | ||||
| 
 | ||||
|         // Ensure render will look good
 | ||||
|         contents = contents.replace("\n", "<br>"); | ||||
|  | ||||
| @ -1,32 +0,0 @@ | ||||
| use regex::{Regex, Captures}; | ||||
| use std::collections::HashMap; | ||||
| 
 | ||||
| /// Renders RST links as HTML links
 | ||||
| ///
 | ||||
| /// # Arguments
 | ||||
| ///
 | ||||
| /// * `string` - input RST string
 | ||||
| ///
 | ||||
| pub fn parse_links(string: &str) -> String { | ||||
|     let re_link_ref = Regex::new(r"\n?.. _(.*): (.*)\n").unwrap(); | ||||
|     let mut link_map: HashMap<String, String> = HashMap::new(); | ||||
| 
 | ||||
|     for cap in re_link_ref.captures_iter(string) { | ||||
|         link_map.insert(String::from(&cap[1]), String::from(&cap[2])); | ||||
|     } | ||||
| 
 | ||||
|     let text: String = re_link_ref.replace_all(string, "").to_string(); | ||||
| 
 | ||||
|     let re_link = Regex::new(r"`(.*)`_").unwrap(); | ||||
| 
 | ||||
|     let output = re_link.replace_all(&text, |cap: &Captures| { | ||||
|         let link = match link_map.get(&cap[1]) { | ||||
|             None => String::from(""), | ||||
|             Some(link) => link.to_owned(), | ||||
|         }; | ||||
| 
 | ||||
|         format!("<a class=\"link\" href=\"{}\">{}</a>", link, &cap[1]) | ||||
|     }); | ||||
| 
 | ||||
|     output.to_string() | ||||
| } | ||||
							
								
								
									
										111
									
								
								src/rst_parser/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/rst_parser/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| pub mod rst_error; | ||||
| 
 | ||||
| use regex::{Captures, Regex}; | ||||
| use std::collections::HashMap; | ||||
| use rst_error::RSTError; | ||||
| use std::convert::TryFrom; | ||||
| 
 | ||||
| /// RST Image
 | ||||
| struct RSTImage { | ||||
|     /// File location
 | ||||
|     image_file: String, | ||||
|     /// Height
 | ||||
|     height: Option<String>, | ||||
|     /// Width
 | ||||
|     width: Option<String>, | ||||
|     /// Alt Text
 | ||||
|     alt: Option<String>, | ||||
|     /// Align (not implemented)
 | ||||
|     #[allow(dead_code)] | ||||
|     align: Option<String>, | ||||
| } | ||||
| 
 | ||||
| impl RSTImage { | ||||
|     /// Convert to HTML img tag
 | ||||
|     fn to_html(&self) -> String { | ||||
|         let mut html = format!("<img src=\"{}\"", self.image_file); | ||||
|         let mut style = "".to_string(); | ||||
| 
 | ||||
|         if let Some(alt) = &self.alt { | ||||
|             html = format!("{} {}", html, alt); | ||||
|         } | ||||
| 
 | ||||
|         if let Some(height) = &self.height { | ||||
|             style = format!("{}height;{};", style, height); | ||||
|         } | ||||
|         if let Some(width) = &self.width { | ||||
|             style = format!("{}width:{};", style, width); | ||||
|         } | ||||
| 
 | ||||
|         html = format!("{} style=\"{}\">", html, style); | ||||
| 
 | ||||
|         html | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl TryFrom<&Captures<'_>> for RSTImage { | ||||
|     type Error = RSTError; | ||||
|     /// Convert from a regex capture to a RSTImage
 | ||||
|     ///
 | ||||
|     /// # Arguments
 | ||||
|     ///
 | ||||
|     /// * cap - regex capture
 | ||||
|     fn try_from(cap: &Captures<'_>) -> Result<Self, Self::Error> { | ||||
|         let image = Self { | ||||
|             image_file: cap | ||||
|                 .name("file_name") | ||||
|                 .map(|m| m.as_str().to_string()) | ||||
|                 .ok_or(RSTError::NotFound("file_name"))?, | ||||
|             height: cap.name("width").map(|m| m.as_str().to_string()), | ||||
|             width: cap.name("width").map(|m| m.as_str().to_string()), | ||||
|             alt: cap.name("alt").map(|m| m.as_str().to_string()), | ||||
|             align: cap.name("align").map(|m| m.as_str().to_string()), | ||||
|         }; | ||||
| 
 | ||||
|         Ok(image) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Renders RST links as HTML links
 | ||||
| ///
 | ||||
| /// # Arguments
 | ||||
| ///
 | ||||
| /// * `string` - input RST string
 | ||||
| pub fn parse_links(string: &str) -> Result<String, RSTError> { | ||||
|     let re_link_ref = Regex::new(r"\n?.. _(.*): (.*)\n")?; | ||||
|     let mut link_map: HashMap<String, String> = HashMap::new(); | ||||
| 
 | ||||
|     for cap in re_link_ref.captures_iter(string) { | ||||
|         link_map.insert(String::from(&cap[1]), String::from(&cap[2])); | ||||
|     } | ||||
| 
 | ||||
|     let text: String = re_link_ref.replace_all(string, "").to_string(); | ||||
| 
 | ||||
|     let re_link = Regex::new(r"`(.*)`_")?; | ||||
| 
 | ||||
|     let output = re_link.replace_all(&text, |cap: &Captures| { | ||||
|         let link = match link_map.get(&cap[1]) { | ||||
|             None => String::from(""), | ||||
|             Some(link) => link.to_owned(), | ||||
|         }; | ||||
| 
 | ||||
|         format!("<a class=\"link\" href=\"{}\">{}</a>", link, &cap[1]) | ||||
|     }); | ||||
| 
 | ||||
|     Ok(output.to_string()) | ||||
| } | ||||
| 
 | ||||
| /// Renders RST images as HTML embedded images
 | ||||
| ///
 | ||||
| /// # Arguments
 | ||||
| ///
 | ||||
| /// * `string` - input rst string
 | ||||
| pub fn parse_images(string: &str) -> Result<String, RSTError> { | ||||
|     let re_image = Regex::new( | ||||
|         r".. image:: (?P<file_name>.*)\n( *((:height: (?P<height>.*))|(:width: (?P<width>.*))|(:scale: (?P<scale>.*%))|(:alt: (?P<alt>.*))|(:align: (?P<align>.*)))\n)*", | ||||
|     )?; | ||||
| 
 | ||||
|     Ok(re_image | ||||
|         .replace_all(string, |cap: &Captures| RSTImage::try_from(cap).unwrap().to_html()) | ||||
|         .to_string()) | ||||
| } | ||||
							
								
								
									
										28
									
								
								src/rst_parser/rst_error.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/rst_parser/rst_error.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| use regex::Error; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub enum RSTError { | ||||
|     /// Regex compile error
 | ||||
|     RegexError(regex::Error), | ||||
|     /// Required element not found
 | ||||
|     NotFound(&'static str), | ||||
| } | ||||
| 
 | ||||
| impl std::error::Error for RSTError {} | ||||
| 
 | ||||
| impl From<regex::Error> for RSTError { | ||||
|     /// From regex error
 | ||||
|     fn from(e: Error) -> Self { | ||||
|         Self::RegexError(e) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl std::fmt::Display for RSTError { | ||||
|     /// fmt error
 | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||||
|         match self { | ||||
|             RSTError::NotFound(s) => write!(f, "required element missing: `{}`", s), | ||||
|             RSTError::RegexError(e) => write!(f, "regex compile error: `{:?}`", e), | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										33
									
								
								static/raw_rst/projects/motion_detector.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								static/raw_rst/projects/motion_detector.rst
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| Motion Detector | ||||
| =============== | ||||
| A project made for Auburn ELEC 7450: Digtal Image Processing. The source code can be found on my `Github`_ | ||||
| 
 | ||||
| .. _GitHub: https://github.com/joeyahines/motion_detector | ||||
| 
 | ||||
| Goal | ||||
| ++++ | ||||
| The goal of this project was to detect motion on a video stream from a `VideoForLinux`_ source. The algorithm | ||||
| can also be tested by loading in individual frames. | ||||
| 
 | ||||
| .. _VideoForLinux: https://en.wikipedia.org/wiki/Video4Linux | ||||
| 
 | ||||
| Implementation | ||||
| ++++++++++++++ | ||||
| The project was written in C and VideoForLinux for grabbing image data and `SDL`_ for rendering the video | ||||
| output. A background model is built by implementing a moving average of the image. In addition to this, | ||||
| a motion mask is implemented to desensitise the algorithm from background motion objects. | ||||
| 
 | ||||
| .. _SDL: https://www.libsdl.org/ | ||||
| 
 | ||||
| Webcam output w/ motion highlighted: | ||||
| 
 | ||||
| .. image:: https://github.com/joeyahines/motion_detector/blob/master/docs/final_report/motion.png?&raw=true | ||||
|     :width: 60% | ||||
|     :height: auto | ||||
| 
 | ||||
| Motion detection layer: | ||||
| 
 | ||||
| .. image:: https://github.com/joeyahines/motion_detector/blob/master/docs/final_report/motion_image.png?raw=true | ||||
|     :width: 60% | ||||
|     :height: auto | ||||
| 
 | ||||
| @ -42,5 +42,6 @@ improving how the site looked on mobile. | ||||
| 
 | ||||
| Future Improvements | ||||
| ------------------- | ||||
| As I continue to learn Rust, I plan to implement more features of RST into the raw file displays. For example, | ||||
| embedding images. I want to strike a balance between the aesthetic of a terminal and ease of use of a website. | ||||
| As I continue to learn Rust, I plan to implement more features of RST into the raw file displays. ~~For example, | ||||
| embedding images~~ (now onto text formatting...). I want to strike a balance between the aesthetic of a terminal and | ||||
| ease of use of a website. | ||||
|  | ||||
| @ -5,8 +5,8 @@ ls {{ page_data.site_file.link_name }} | ||||
| {% endblock command %} | ||||
| 
 | ||||
| {% block content %} | ||||
| {% for link in page_data.links %} | ||||
| <br> | ||||
| {% for link in page_data.links %} | ||||
| <a class="link" href="{{ page_data.site_file.link_name}}/{{ link.link_name }}">{{ link.link_name }}</a>   | ||||
| {% endfor %} | ||||
| <br> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user