Decode images in parallel
This commit is contained in:
		
							parent
							
								
									c968d9086d
								
							
						
					
					
						commit
						04f03b4efc
					
				
					 1 changed files with 27 additions and 5 deletions
				
			
		
							
								
								
									
										32
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										32
									
								
								src/main.rs
									
										
									
									
									
								
							| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
use clap::{Parser, ValueHint};
 | 
					use clap::{Parser, ValueHint};
 | 
				
			||||||
 | 
					use image::DynamicImage;
 | 
				
			||||||
use log::info;
 | 
					use log::info;
 | 
				
			||||||
use pdf_writer::{Content, Filter, Finish, Name, Pdf, Rect, Ref};
 | 
					use pdf_writer::{Content, Filter, Finish, Name, Pdf, Rect, Ref};
 | 
				
			||||||
use rayon::prelude::*;
 | 
					use rayon::prelude::*;
 | 
				
			||||||
| 
						 | 
					@ -56,20 +57,37 @@ struct ImageFile {
 | 
				
			||||||
    pub data: Vec<u8>,
 | 
					    pub data: Vec<u8>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct DecodedImageFile {
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub data: Vec<u8>,
 | 
				
			||||||
 | 
					    pub image: DynamicImage,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<&ImageFile> for DecodedImageFile {
 | 
				
			||||||
 | 
					    fn from(value: &ImageFile) -> Self {
 | 
				
			||||||
 | 
					        let image = image::load_from_memory(&value.data).unwrap();
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            name: value.name.clone(),
 | 
				
			||||||
 | 
					            data: value.data.clone(),
 | 
				
			||||||
 | 
					            image,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn convert_cbz(cbz_path: &Path, output_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
 | 
					fn convert_cbz(cbz_path: &Path, output_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
 | 
				
			||||||
    info!("Converting {:?}", cbz_path);
 | 
					    info!("Converting {:?}", cbz_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let a4 = Rect::new(0.0, 0.0, 595.0, 842.0);
 | 
					    let a4 = Rect::new(0.0, 0.0, 595.0, 842.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut zip = ZipArchive::new(File::open(cbz_path)?)?;
 | 
					    let mut zip = ZipArchive::new(File::open(cbz_path)?)?;
 | 
				
			||||||
    let mut images = Vec::new();
 | 
					    let mut files = Vec::new();
 | 
				
			||||||
    for i in 0..zip.len() {
 | 
					    for i in 0..zip.len() {
 | 
				
			||||||
        let mut file = zip.by_index(i)?;
 | 
					        let mut file = zip.by_index(i)?;
 | 
				
			||||||
        let mut image_data = Vec::new();
 | 
					        let mut image_data = Vec::new();
 | 
				
			||||||
        let name = file.enclosed_name().expect("Failed to read file name");
 | 
					        let name = file.enclosed_name().expect("Failed to read file name");
 | 
				
			||||||
        if name.extension() == Some(OsStr::new("jpg")) {
 | 
					        if name.extension() == Some(OsStr::new("jpg")) {
 | 
				
			||||||
            file.read_to_end(&mut image_data)?;
 | 
					            file.read_to_end(&mut image_data)?;
 | 
				
			||||||
            images.push(ImageFile {
 | 
					            files.push(ImageFile {
 | 
				
			||||||
                name: name
 | 
					                name: name
 | 
				
			||||||
                    .file_name()
 | 
					                    .file_name()
 | 
				
			||||||
                    .expect("Failed to read file name")
 | 
					                    .expect("Failed to read file name")
 | 
				
			||||||
| 
						 | 
					@ -80,6 +98,11 @@ fn convert_cbz(cbz_path: &Path, output_dir: &Path) -> Result<(), Box<dyn std::er
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut images = Vec::new();
 | 
				
			||||||
 | 
					    files
 | 
				
			||||||
 | 
					        .par_iter()
 | 
				
			||||||
 | 
					        .map(|f| DecodedImageFile::from(f))
 | 
				
			||||||
 | 
					        .collect_into_vec(&mut images);
 | 
				
			||||||
    images.par_sort_by_key(|img| img.name.clone());
 | 
					    images.par_sort_by_key(|img| img.name.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut pdf = Pdf::new();
 | 
					    let mut pdf = Pdf::new();
 | 
				
			||||||
| 
						 | 
					@ -98,7 +121,6 @@ fn convert_cbz(cbz_path: &Path, output_dir: &Path) -> Result<(), Box<dyn std::er
 | 
				
			||||||
        pages.push(page_id);
 | 
					        pages.push(page_id);
 | 
				
			||||||
        let mut page = pdf.page(page_id);
 | 
					        let mut page = pdf.page(page_id);
 | 
				
			||||||
        let image_name = Name(b"Im1");
 | 
					        let image_name = Name(b"Im1");
 | 
				
			||||||
        let dynamic = image::load_from_memory(&image.data).unwrap();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        page.media_box(a4);
 | 
					        page.media_box(a4);
 | 
				
			||||||
        page.parent(page_tree_id);
 | 
					        page.parent(page_tree_id);
 | 
				
			||||||
| 
						 | 
					@ -108,8 +130,8 @@ fn convert_cbz(cbz_path: &Path, output_dir: &Path) -> Result<(), Box<dyn std::er
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut pdf_image = pdf.image_xobject(image_id, &image.data);
 | 
					        let mut pdf_image = pdf.image_xobject(image_id, &image.data);
 | 
				
			||||||
        pdf_image.filter(Filter::DctDecode);
 | 
					        pdf_image.filter(Filter::DctDecode);
 | 
				
			||||||
        pdf_image.width(dynamic.width() as i32);
 | 
					        pdf_image.width(image.image.width() as i32);
 | 
				
			||||||
        pdf_image.height(dynamic.height() as i32);
 | 
					        pdf_image.height(image.image.height() as i32);
 | 
				
			||||||
        pdf_image.color_space().device_rgb();
 | 
					        pdf_image.color_space().device_rgb();
 | 
				
			||||||
        pdf_image.bits_per_component(8);
 | 
					        pdf_image.bits_per_component(8);
 | 
				
			||||||
        pdf_image.finish();
 | 
					        pdf_image.finish();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue