Compare commits
No commits in common. "go-ui" and "main" have entirely different histories.
|
@ -0,0 +1,16 @@
|
||||||
|
# ---> Rust
|
||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
debug/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
cowgen/tests/out
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
members = [
|
||||||
|
"cowgen",
|
||||||
|
"cowmic"
|
||||||
|
]
|
|
@ -0,0 +1 @@
|
||||||
|
You do not have, nor can you ever acquire the right to use, copy or distribute this software; Should you use this software for any purpose, or copy and distribute it to anyone or in any manner, you are breaking the laws of whatever soi-disant jurisdiction, and you promise to continue doing so for the indefinite future. In any case, please always: read and understand any software; verify any PGP signatures that you use - for any purpose.
|
|
@ -0,0 +1,5 @@
|
||||||
|
# cowmic
|
||||||
|
|
||||||
|
generates memes
|
||||||
|
|
||||||
|
`mogrify -define png:format=png32 -format png *.png`
|
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "cowgen"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["cel <cel@blos.sm>", "emilis <emilis@puff.place>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ril = { version = "0", features = ["all"] }
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
use ril::prelude::*;
|
||||||
|
|
||||||
|
pub fn produce(base: &Vec<u8>, elements: Vec<Element>) -> Result<Vec<u8>, CowError> {
|
||||||
|
let base = Image::<Rgba>::from_bytes_inferred(base)?;
|
||||||
|
let size = base.dimensions();
|
||||||
|
let mut base_image = base.with_overlay_mode(OverlayMode::Merge);
|
||||||
|
for element in elements {
|
||||||
|
let mut pos = element.position;
|
||||||
|
let mut img: Image = element.into_image()?;
|
||||||
|
if pos.0 < 0 {
|
||||||
|
img.crop(-pos.0 as u32, 0, size.0, size.1);
|
||||||
|
pos.0 = 0;
|
||||||
|
}
|
||||||
|
if pos.1 < 0 {
|
||||||
|
img.crop(0, -pos.1 as u32, size.0, size.1);
|
||||||
|
pos.1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_image.draw(&Paste::new(&img.convert()).with_position(pos.0 as u32, pos.1 as u32));
|
||||||
|
}
|
||||||
|
let mut buf = Vec::<u8>::new();
|
||||||
|
base_image.encode(ImageFormat::Png, &mut buf).unwrap();
|
||||||
|
|
||||||
|
Ok(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Element {
|
||||||
|
position: (i32, i32),
|
||||||
|
dimensions: (u32, u32),
|
||||||
|
media: Media,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Element {
|
||||||
|
pub fn new(media: Media, position: (i32, i32), dimensions: (u32, u32)) -> Self {
|
||||||
|
Self {
|
||||||
|
position,
|
||||||
|
dimensions,
|
||||||
|
media,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_image(self) -> Result<Image, CowError> {
|
||||||
|
match self.media {
|
||||||
|
// TODO: allow changing treatment of image
|
||||||
|
Media::Image((image, _)) => Ok(Image::from_bytes_inferred(*image)?.resized(
|
||||||
|
self.dimensions.0,
|
||||||
|
self.dimensions.1,
|
||||||
|
ResizeAlgorithm::Bicubic,
|
||||||
|
)),
|
||||||
|
Media::Text(text) => Ok(Image::new(
|
||||||
|
self.dimensions.0,
|
||||||
|
self.dimensions.1,
|
||||||
|
Dynamic::Rgba(Rgba::transparent()),
|
||||||
|
)
|
||||||
|
.with(
|
||||||
|
&TextSegment::new(
|
||||||
|
&Font::from_bytes(&text.font, 12.0).unwrap(),
|
||||||
|
text.text,
|
||||||
|
Dynamic::Rgba(Rgba::new(
|
||||||
|
text.fill.0,
|
||||||
|
text.fill.1,
|
||||||
|
text.fill.2,
|
||||||
|
text.fill.3,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.with_size(text.size),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Media {
|
||||||
|
Text(Text),
|
||||||
|
Image((Box<Vec<u8>>, ImageMode)),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Text {
|
||||||
|
text: String,
|
||||||
|
font: Box<Vec<u8>>,
|
||||||
|
size: f32,
|
||||||
|
fill: (u8, u8, u8, u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ImageMode {
|
||||||
|
Stretch,
|
||||||
|
Fill,
|
||||||
|
Crop,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Text {
|
||||||
|
pub fn new(text: String, font: Box<Vec<u8>>, size: f32, fill: (u8, u8, u8, u8)) -> Self {
|
||||||
|
Self {
|
||||||
|
text,
|
||||||
|
font,
|
||||||
|
size,
|
||||||
|
fill,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum CowError {
|
||||||
|
Magick(String),
|
||||||
|
Other(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ril::Error> for CowError {
|
||||||
|
fn from(r: ril::Error) -> Self {
|
||||||
|
CowError::Other(r.to_string())
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
Binary file not shown.
After Width: | Height: | Size: 240 KiB |
|
@ -0,0 +1,37 @@
|
||||||
|
use cowgen::*;
|
||||||
|
use std::{
|
||||||
|
fs::{self, File},
|
||||||
|
io::Write,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_overlay_text_and_image() {
|
||||||
|
println!("{}", std::env::current_dir().unwrap().to_str().unwrap());
|
||||||
|
let base = Box::new(include_bytes!("assets/cow.png").to_vec());
|
||||||
|
let font = Box::new(include_bytes!("assets/OpenSans-ExtraBold.ttf").to_vec());
|
||||||
|
let superimpose = Box::new(include_bytes!("assets/mariah.jpg").to_vec());
|
||||||
|
|
||||||
|
let out = produce(
|
||||||
|
&base,
|
||||||
|
vec![
|
||||||
|
Element::new(
|
||||||
|
Media::Text(Text::new("Hello".to_string(), font, 20.0, (0, 0, 0, 128))),
|
||||||
|
(0, 0),
|
||||||
|
(64, 64),
|
||||||
|
),
|
||||||
|
Element::new(
|
||||||
|
Media::Image((superimpose, ImageMode::Stretch)),
|
||||||
|
(400, 400),
|
||||||
|
(800, 200),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let mut f = File::create("tests/out/one.png").unwrap();
|
||||||
|
f.write_all(&out).unwrap();
|
||||||
|
f.flush().unwrap();
|
||||||
|
|
||||||
|
let actual = fs::read("tests/out/one.png").unwrap();
|
||||||
|
let expected = include_bytes!("expected/one.png").to_vec();
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "cowmic"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["cel <cel@blos.sm>", "emilis <emilis@puff.place>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cowgen = { path = "../cowgen" }
|
||||||
|
iced = "0.6"
|
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println!("hello, world");
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
use std::path::Path;
|
||||||
|
use std::{fs::File, io::Write};
|
||||||
|
|
||||||
|
use cowgen::{CowError, Text};
|
||||||
|
use iced::Sandbox;
|
||||||
|
use iced::Settings;
|
||||||
|
|
||||||
|
fn main() -> Result<(), CowError> {
|
||||||
|
Cowmic::run(Settings::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Element {
|
||||||
|
position: (i32, i32),
|
||||||
|
dimensions: (i32, i32),
|
||||||
|
media: Media,
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct Text {}
|
||||||
|
|
||||||
|
struct Image {}
|
||||||
|
|
||||||
|
enum Media {
|
||||||
|
Image(Path),
|
||||||
|
Text(Text),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Template {
|
||||||
|
image_path: String,
|
||||||
|
elements: Vec<Element>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Cowmic {
|
||||||
|
templates: Vec<Template>,
|
||||||
|
view: View,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Message {}
|
||||||
|
|
||||||
|
impl Sandbox for Cowmic {
|
||||||
|
type Message = Message;
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
view: View::Library(Library::View::new()),
|
||||||
|
templates: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self) -> String {
|
||||||
|
"Cowmic".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, message: Self::Message) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self) -> iced::Element<'_, Self::Message> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// library -> view template -> create image (fill out template) -> save to filesystem
|
||||||
|
// \-> new template
|
||||||
|
enum View {
|
||||||
|
Library(Library::View),
|
||||||
|
// Templatep(Template),
|
||||||
|
// Generate(Generate),
|
||||||
|
}
|
||||||
|
|
||||||
|
// features:
|
||||||
|
// import template
|
||||||
|
// delete template
|
||||||
|
// rename template
|
||||||
|
// autosave all templates
|
||||||
|
mod Library {
|
||||||
|
use super::Template;
|
||||||
|
|
||||||
|
pub struct View;
|
||||||
|
|
||||||
|
impl View {
|
||||||
|
pub fn new(templates: Vec<Template>) -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, message: Message) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self) -> iced::Element<'_, Message> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enum Message {}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod NewTemplate {
|
||||||
|
struct View {
|
||||||
|
image: Image,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Message {}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod Generate {
|
||||||
|
enum Message {}
|
||||||
|
}
|
Loading…
Reference in New Issue