Skip to content

Instantly share code, notes, and snippets.

@sevenc-nanashi
Created August 30, 2025 23:54
Show Gist options
  • Select an option

  • Save sevenc-nanashi/11fab9b4f4b9b65f58cbbf0130d2fba0 to your computer and use it in GitHub Desktop.

Select an option

Save sevenc-nanashi/11fab9b4f4b9b65f58cbbf0130d2fba0 to your computer and use it in GitHub Desktop.
use aviutl2::{anyhow, input::*, utils::flip_vertical};
struct MyPngInputPlugin;
impl InputPlugin for MyPngInputPlugin {
type InputHandle = image::RgbaImage;
fn new() -> Self {
MyPngInputPlugin
}
fn plugin_info(&self) -> InputPluginTable {
InputPluginTable {
name: "My PNG Input Plugin".to_string(),
information: "A simple PNG input plugin".to_string(),
input_type: InputType::Video,
concurrent: false,
file_filters: vec![FileFilter {
name: "PNG Files".to_string(),
extensions: vec!["png".to_string()],
}],
can_config: false,
}
}
fn open(&self, file: std::path::PathBuf) -> AnyResult<Self::InputHandle> {
let img = image::open(file)?.to_rgba8();
Ok(img)
}
fn close(&self, handle: Self::InputHandle) -> AnyResult<()> {
drop(handle);
Ok(())
}
fn get_input_info(
&self,
handle: &mut Self::InputHandle,
_video_track: u32,
_audio_track: u32,
) -> AnyResult<InputInfo> {
let (width, height) = handle.dimensions();
Ok(InputInfo {
video: Some(VideoInputInfo {
fps: Rational32::new(30, 1),
num_frames: 1,
manual_frame_index: false,
width,
height,
format: InputPixelFormat::Bgra,
}),
audio: None,
})
}
fn read_video(
&self,
handle: &Self::InputHandle,
frame: u32,
returner: &mut ImageReturner,
) -> AnyResult<()> {
anyhow::ensure!(frame == 0, "Only one frame available");
let (width, height) = handle.dimensions();
let mut pixels = handle
.pixels()
.map(|p| (p[2], p[1], p[0], p[3]))
.collect::<Vec<_>>();
flip_vertical(&mut pixels, width as usize, height as usize);
returner.write(&pixels);
Ok(())
}
}
aviutl2::register_input_plugin!(MyPngInputPlugin);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment