Skip to content
Snippets Groups Projects
Commit ecc3b823 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

add more configurable image formats

parent 188f0862
No related branches found
No related tags found
No related merge requests found
use std::path::Path; use std::path::Path;
use failure::{format_err, Error}; use failure::{format_err, Error};
use image::ImageOutputFormat;
use crate::ffmpeg_api::api::*; use crate::ffmpeg_api::api::*;
use crate::ffmpeg_api::enums::*; use crate::ffmpeg_api::enums::*;
...@@ -15,7 +16,7 @@ pub fn extract( ...@@ -15,7 +16,7 @@ pub fn extract(
frame_interval: MediaTime, frame_interval: MediaTime,
input_file: &Path, input_file: &Path,
output_folder: &Path, output_folder: &Path,
format: impl AsRef<str>, format: ImageOutputFormat,
scaler: SwsScaler, scaler: SwsScaler,
flags: SwsFlags, flags: SwsFlags,
) -> Result<(), Error> { ) -> Result<(), Error> {
......
use std::fs::File;
use std::io::BufWriter;
use std::path::PathBuf; use std::path::PathBuf;
use failure::{bail, format_err, Error}; use failure::{bail, format_err, Error};
use image::{ImageBuffer, RgbImage}; use image::{DynamicImage, ImageOutputFormat, RgbImage};
use crate::util::media_time::MediaTime; use crate::util::media_time::MediaTime;
use crate::util::webvtt::{WebVTTCue, WebVTTFile}; use crate::util::webvtt::{WebVTTCue, WebVTTFile};
pub enum ImageFormat {
Jpeg(i32),
Png,
}
pub struct SpritesheetManager { pub struct SpritesheetManager {
num_horizontal: u32, num_horizontal: u32,
num_vertical: u32, num_vertical: u32,
...@@ -19,7 +26,7 @@ pub struct SpritesheetManager { ...@@ -19,7 +26,7 @@ pub struct SpritesheetManager {
metadata: WebVTTFile, metadata: WebVTTFile,
output_path: PathBuf, output_path: PathBuf,
name: String, name: String,
format: String, format: ImageOutputFormat,
initialized: bool, initialized: bool,
} }
...@@ -31,7 +38,7 @@ impl SpritesheetManager { ...@@ -31,7 +38,7 @@ impl SpritesheetManager {
frame_interval: MediaTime, frame_interval: MediaTime,
output_path: impl Into<PathBuf>, output_path: impl Into<PathBuf>,
name: impl AsRef<str>, name: impl AsRef<str>,
format: impl AsRef<str>, format: ImageOutputFormat,
) -> SpritesheetManager { ) -> SpritesheetManager {
SpritesheetManager { SpritesheetManager {
num_horizontal, num_horizontal,
...@@ -39,14 +46,14 @@ impl SpritesheetManager { ...@@ -39,14 +46,14 @@ impl SpritesheetManager {
max_side, max_side,
sprite_width: 0, sprite_width: 0,
sprite_height: 0, sprite_height: 0,
spritesheet: ImageBuffer::new(0, 0), spritesheet: RgbImage::new(0, 0),
current_image: 0, current_image: 0,
last_timestamp: MediaTime::from_millis(0), last_timestamp: MediaTime::from_millis(0),
frame_interval, frame_interval,
metadata: WebVTTFile::new(), metadata: WebVTTFile::new(),
output_path: output_path.into(), output_path: output_path.into(),
name: String::from(name.as_ref()), name: String::from(name.as_ref()),
format: String::from(format.as_ref()), format,
initialized: false, initialized: false,
} }
} }
...@@ -59,15 +66,15 @@ impl SpritesheetManager { ...@@ -59,15 +66,15 @@ impl SpritesheetManager {
self.sprite_height = self.max_side; self.sprite_height = self.max_side;
self.sprite_width = self.sprite_height * width / height; self.sprite_width = self.sprite_height * width / height;
} }
self.reinit_buffer(); self.spritesheet = self.reinit_buffer();
self.initialized = true; self.initialized = true;
} }
fn reinit_buffer(&mut self) { fn reinit_buffer(&self) -> RgbImage {
self.spritesheet = ImageBuffer::new( RgbImage::new(
self.sprite_width * self.num_horizontal, self.sprite_width * self.num_horizontal,
self.sprite_height * self.num_vertical, self.sprite_height * self.num_vertical,
); )
} }
pub fn initialized(&self) -> bool { pub fn initialized(&self) -> bool {
...@@ -95,6 +102,15 @@ impl SpritesheetManager { ...@@ -95,6 +102,15 @@ impl SpritesheetManager {
index * self.sprite_width index * self.sprite_width
} }
fn ending(&self) -> String {
String::from(match self.format {
ImageOutputFormat::Png => "png",
ImageOutputFormat::Jpeg(_) => "jpeg",
ImageOutputFormat::Bmp => "bmp",
_ => panic!("Invalid image format: {:?}", self.format),
})
}
fn y(&self, current: u32) -> u32 { fn y(&self, current: u32) -> u32 {
let index = (current / self.num_horizontal) % self.num_vertical; let index = (current / self.num_horizontal) % self.num_vertical;
index * self.sprite_height index * self.sprite_height
...@@ -141,7 +157,7 @@ impl SpritesheetManager { ...@@ -141,7 +157,7 @@ impl SpritesheetManager {
"{}_{}.{}#xywh={},{},{},{}", "{}_{}.{}#xywh={},{},{},{}",
self.name, self.name,
self.spritesheet_index(self.current_image - 1), self.spritesheet_index(self.current_image - 1),
self.format, self.ending(),
self.x(self.current_image - 1), self.x(self.current_image - 1),
self.y(self.current_image - 1), self.y(self.current_image - 1),
self.sprite_width, self.sprite_width,
...@@ -151,15 +167,21 @@ impl SpritesheetManager { ...@@ -151,15 +167,21 @@ impl SpritesheetManager {
} }
fn save_spritesheet(&mut self) -> Result<(), Error> { fn save_spritesheet(&mut self) -> Result<(), Error> {
self.spritesheet let name = format!(
.save(self.output_path.join(format!(
"{}_{}.{}", "{}_{}.{}",
self.name, self.name,
self.spritesheet_index(self.current_image), self.spritesheet_index(self.current_image),
self.format self.ending(),
))) );
.map_err(|error| format_err!("Could not write spritesheet: {}", error))?;
self.reinit_buffer(); let file = File::create(self.output_path.join(&name))
.map_err(|err| format_err!("Could not create spritesheet {}: {}", &name, err))?;
let new_buffer = self.reinit_buffer();
DynamicImage::ImageRgb8(std::mem::replace(&mut self.spritesheet, new_buffer))
.write_to(&mut BufWriter::new(file), self.format.clone())
.map_err(|err| format_err!("Could not write spritesheet {}: {}", &name, err))?;
Ok(()) Ok(())
} }
......
...@@ -11,6 +11,7 @@ use structopt::StructOpt; ...@@ -11,6 +11,7 @@ use structopt::StructOpt;
use crate::ffmpeg_api::enums::{SwsFlags, SwsScaler}; use crate::ffmpeg_api::enums::{SwsFlags, SwsScaler};
use crate::util::media_time::MediaTime; use crate::util::media_time::MediaTime;
use image::ImageOutputFormat;
fn parse_scaler(src: &str) -> Result<SwsScaler, String> { fn parse_scaler(src: &str) -> Result<SwsScaler, String> {
match src { match src {
...@@ -40,10 +41,12 @@ struct Options { ...@@ -40,10 +41,12 @@ struct Options {
num_horizontal: u32, num_horizontal: u32,
#[structopt(long = "num-vertical", default_value = "5")] #[structopt(long = "num-vertical", default_value = "5")]
num_vertical: u32, num_vertical: u32,
#[structopt(long = "max-size", default_value = "160")] #[structopt(long = "max-size", default_value = "240")]
max_size: u32, max_size: u32,
#[structopt(long = "format", default_value = "png")] #[structopt(long = "format", default_value = "jpg")]
format: String, format: String,
#[structopt(long = "quality", default_value = "90")]
quality: u8,
#[structopt(long = "scaler", default_value = "area", parse(try_from_str = parse_scaler))] #[structopt(long = "scaler", default_value = "area", parse(try_from_str = parse_scaler))]
scaler: SwsScaler, scaler: SwsScaler,
#[structopt(long = "fast-chroma")] #[structopt(long = "fast-chroma")]
...@@ -75,7 +78,12 @@ fn main() -> Result<(), Error> { ...@@ -75,7 +78,12 @@ fn main() -> Result<(), Error> {
MediaTime::from_seconds(options.frame_interval), MediaTime::from_seconds(options.frame_interval),
Path::new(&options.input), Path::new(&options.input),
Path::new(&options.output), Path::new(&options.output),
options.format, match options.format.as_str() {
"jpeg" | "jpg" => ImageOutputFormat::Jpeg(options.quality),
"png" => ImageOutputFormat::Png,
"bmp" => ImageOutputFormat::Bmp,
_ => panic!("Unsupported image format: {}", options.format),
},
options.scaler, options.scaler,
flags, flags,
)?; )?;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment