feat: implement cbz writing and pdf reading
All checks were successful
Build and test / Clippy (pull_request) Successful in 44s
Build and test / Tests (pull_request) Successful in 48s
Checking yaml / Run yamllint (pull_request) Successful in 5s
Checking Renovate configuration / validate (pull_request) Successful in 1m4s
Build and test / Build AMD64 (pull_request) Successful in 49s
Build and test / Generate Documentation (pull_request) Successful in 59s

This commit is contained in:
Marc Plano-Lesay 2025-10-13 16:52:25 +11:00
parent 3aa68fbe12
commit b35ccbe271
Signed by: kernald
GPG key ID: 66A41B08CC62A6CF
10 changed files with 643 additions and 57 deletions

View file

@ -1,6 +1,6 @@
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::io::{Read, Write};
use std::path::Path;
use anyhow::Result;
@ -9,7 +9,7 @@ use zip::ZipArchive;
use crate::model::{Document, ImagePage};
use super::FormatReader;
use super::{FormatReader, FormatWriter};
pub struct CbzReader;
@ -51,3 +51,40 @@ impl FormatReader for CbzReader {
Ok(Document::new(pages))
}
}
pub struct CbzWriter;
impl FormatWriter for CbzWriter {
fn write(&self, doc: &Document, output: &Path) -> Result<()> {
use zip::write::SimpleFileOptions;
let file = File::create(output)?;
let mut zip = zip::ZipWriter::new(file);
let options = SimpleFileOptions::default();
for (idx, page) in doc.pages.iter().enumerate() {
let mut name = page.name.clone();
if Path::new(&name).extension().and_then(OsStr::to_str) != Some("jpg") {
name = format!("{:03}.jpg", idx + 1);
}
zip.start_file(&name, options)?;
if let Some(dct) = &page.jpeg_dct {
zip.write_all(dct)?;
} else {
// Encode to JPEG
let rgb = page.image.to_rgb8();
let (w, h) = (rgb.width(), rgb.height());
let mut cursor = std::io::Cursor::new(Vec::new());
{
let mut enc =
image::codecs::jpeg::JpegEncoder::new_with_quality(&mut cursor, 85);
enc.encode(&rgb.into_raw(), w, h, image::ColorType::Rgb8.into())?;
}
let data = cursor.into_inner();
zip.write_all(&data)?;
}
}
zip.finish()?;
Ok(())
}
}