I am utilising a cargo lib called image = 0.23.14 where, I am trying to overlay the image on top of each other.
On their repository, there is an example where you can concat the images side by side.
use image::{
GenericImage,
GenericImageView,
ImageBuffer,
Pixel,
Primitive
};
fn h_concat<I, P, S>(images: &[I]) -> ImageBuffer<P, Vec<S>>
where
I: GenericImageView<Pixel = P>,
P: Pixel<Subpixel = S> + 'static,
S: Primitive + 'static {
let mut imgbuf = image::ImageBuffer::new(100, 100);
for img in images {
imgbuf.copy_from(img, 0, 0).unwrap();
}
imgbug
}
fn main() -> Result<()> {
h_concat(&[
image::open("images/img1.png").unwrap(),
image::open("images/img2.png").unwrap(),
]).save("random.png").unwrap();
Ok(())
}
I am wondering what if I want to append more files together.
Okay, after some fiddling and doing a bit more research on the documentation. I did found that there is a method image::imageops::overlay which solves my problem.
use image::{DynamicImage, imageops};
fn h_concat(mut base: DynamicImage, imgs: &[DynamicImage]) -> DynamicImage {
for img in imgs {
imageops::overlay(&mut base, img, 0, 0);
}
base
}
fn main() -> Result<()> {
let base = image::open("images/img1.png").unwrap();
h_concat(base, &[
image::open("images/img2.png").unwrap()
]).save("random.png").unwrap();
}
Related
i am trying to import a backdrop for my application and using a image as that backdrop, but cant seem to get it to work. Im using this example on loading images in; https://github.com/emilk/egui/blob/c69fe941afdea5ef6f3f84ed063554500b6262e8/eframe/examples/image.rs
Here is my code:
use eframe::{run_native, epi::App, egui, NativeOptions};
use image::GenericImageView;
struct Tasks{
texture: Option<(egui::Vec2, egui::TextureId)>,
}
impl App for Tasks {
fn name(&self) -> &str {
"CheckIt"
}
fn update(&mut self,ctx: &eframe::egui::CtxRef,frame: &mut eframe::epi::Frame<'_>) {
//background color
let frame = egui::containers::Frame {
fill: egui::Color32::from_rgb(241, 233, 218),
..Default::default()
};
if self.texture.is_none() {
// Load the image:
let image_data = include_bytes!("date_backdrop.png");
let image = image::load_from_memory(image_data).expect("Failed to load image");
let image_buffer = image.to_rgba8();
let size = (image.width() as usize, image.height() as usize);
let pixels = image_buffer.into_vec();
assert_eq!(size.0 * size.1 * 4, pixels.len());
let pixels: Vec<_> = pixels
.chunks_exact(4)
.map(|p| egui::Color32::from_rgba_unmultiplied(p[0], p[1], p[2], p[3]))
.collect();
// Allocate a texture:
let texture = ctx.tex_allocator().alloc_srgba_premultiplied(size, &pixels);
let size = egui::Vec2::new(size.0 as f32, size.1 as f32);
self.texture = Some((size, texture));
}
//main window
egui::CentralPanel::default().frame(frame).show(ctx, |ui| {
if let Some((size, texture)) = self.texture {
ui.heading("This is an image:");
ui.image(texture, size);
ui.heading("This is an image you can click:");
ui.add(egui::ImageButton::new(texture, size));
}
});
}
}
fn main(){
let app: Tasks = Tasks{texture: None};
let win_options = eframe::NativeOptions{
initial_window_size: Some(egui::Vec2::new(386.0, 636.0)),
always_on_top: true,
resizable: false,
..Default::default()
};
run_native(Box::new(app), win_options);
}
im getting an error on this line of code
let texture = ctx.tex_allocator().alloc_srgba_premultiplied(size, &pixels);
here is the error message: no method named tex_allocator found for reference &CtxRef in the current scope
method not found in &CtxRef
im still new to rust and building ui with it.
I have tried asking ChatGPT and googleing the problem but to no success
I'd like to have a container of points that are sorted by the distance to some point, which is given at runtime. In other languages, I could supply the container with a custom compare function, however, I understand this is not possible in rust.
Consider the following code problem:
/// distance between two points
fn distance(a: &(f32, f32), b: &(f32, f32)) -> f32 {
((a.0-b.0)*(a.0-b.0) + (a.1-b.1)*(a.1-b.1)).sqrt()
}
fn main() {
let origin = (1, 1); // assume values are provided at runtime
let mut container = BTreeSet::new(); // should be sorted by distance to origin
container.insert((1 ,9));
container.insert((2 ,2));
container.insert((1 ,5));
}
After the insertions I want the container to be sorted as [(2,2),(1,5),(1,9)]. The example uses BTreeSet, which I don't insist on using, but it feels like the closest to what I need.
I do NOT want a Vec that I have to resort manually after every insert().
So how do I connect distance(), origin, and container, preferably without third-party dependencies?
I don't think there is a good way to do this without storing the origin along with each point so that you can use it in the Cmp implementation.
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use std::collections::BTreeSet;
#[derive(Debug, Clone, Copy)]
struct Point2D {
origin: (f32, f32),
point: (f32, f32),
}
impl Point2D {
fn length(self) -> f32 {
let (x1, y1) = self.origin;
let (x2, y2) = self.point;
((x1 - x2).powi(2) + (y1 - y2).powi(2)).sqrt()
}
}
impl PartialEq for Point2D {
fn eq(&self, rhs: &Self) -> bool {
self.origin == rhs.origin && self.length() == rhs.length()
}
}
impl Eq for Point2D {}
impl PartialOrd for Point2D {
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
(self.origin == rhs.origin).then_some(self.cmp(rhs))
}
}
impl Ord for Point2D {
fn cmp(&self, rhs: &Self) -> Ordering {
self.length().total_cmp(&rhs.length())
}
}
fn main() {
let origin = (1.0, 1.0); // assume values are provided at runtime
let mut container = BTreeSet::new(); // should be sorted by distance to origin
container.insert(Point2D {
origin,
point: (1.0, 9.0),
});
container.insert(Point2D {
origin,
point: (2.0, 2.0),
});
container.insert(Point2D {
origin,
point: (1.0, 5.0),
});
println!("{:?}", container.iter().map(|p| p.point).collect::<Vec<_>>());
// [(2.0, 2.0), (1.0, 5.0), (1.0, 9.0)]
}
I have a working solution to filtering out an input vec of strings compared to a vector of a struct. However, my code seems complicated and I tried simplify the code using a iter::filter(https://doc.rust-lang.org/stable/std/iter/struct.Filter.html). This caused issues because the iterator gave back values that were references and could not be directly used. It seems like my understanding of the iter and what can be done in a structs vector needs refreshing. Below is the simplified filtering code that works:
#[derive(Debug)]
pub struct Widget {
name: String,
pin: u16,
}
impl Widget{
pub fn new(widget_name: String, widget_pin: String) -> Widget {
let widget_pin_u16 = widget_pin.parse::<u16>().expect("Unable to parse");
let nw = Widget {
name: widget_name,
pin: widget_pin_u16
};
return nw
}
}
pub struct WidgetHolder {
widgets: Vec<Widget>,
widget_holder_name: String
}
impl WidgetHolder {
fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
let mut widgets_to_add: Vec<String> = Vec::new();
for widget in valid_widgets_found {
// The string musy be compared to pin field, so we're converting
let widget_offset = widget
.clone()
.parse::<u16>()
.expect("Unable to parse widget base into int.");
// If it doesnt exist in our widgetHolder widgets vector, then lets add it.
let mut widget_exists = false;
for existing_widget in &self.widgets {
if widget_offset == existing_widget.pin {
widget_exists = true;
break;
}
}
if !widget_exists {
widgets_to_add.push(widget.clone());
}
}
if widgets_to_add.is_empty() {
return;
}
for widget in widgets_to_add {
let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
self.widgets.push(loaded_widget);
}
}
}
pub fn main() {
let init_vec = Vec::new();
let mut wh = WidgetHolder {
widgets: init_vec,
widget_holder_name: "MyWidget".to_string()
};
let vec1 = vec!["1".to_string(), "2".to_string(), "3".to_string()];
wh.add_widgets(vec1);
println!("{:?}", wh.widgets);
let vec2 = vec!["2".to_string(), "3".to_string(), "4".to_string()];
wh.add_widgets(vec2);
println!("{:?}", wh.widgets);
}
Is there a way I can clean up this code without having to use so many data structures and loops? The filter api looks clean but does it work with a vector inside of a struct that I am trying to mutate(append to it)?
EDIT
After trying to get a stack trace, I actually got the filter to work...
fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
let widgets_to_add: Vec<String> = valid_widgets_found.into_iter()
.filter(|widget_pin| {
let widget_offset = widget_pin.clone().parse::<u16>().expect("Unable to parse widget base into int.");
let mut widget_exists = false;
for existing_widget in &self.widgets {
if widget_offset == existing_widget.pin {
widget_exists = true;
break;
}
}
!widget_exists
})
.collect();
if widgets_to_add.is_empty() {
return;
}
for widget in widgets_to_add {
let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
self.widgets.push(loaded_widget);
}
}
I figured out the answer. Seemed like a syntax error when I initially tried it. For anyone who's looking for a filter example in the future:
fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
let widgets_to_add: Vec<String> = valid_widgets_found.into_iter()
.filter(|widget_pin| {
let widget_offset = widget_pin.clone().parse::<u16>().expect("Unable to parse widget base into int.");
let mut widget_exists = false;
for existing_widget in &self.widgets {
if widget_offset == existing_widget.pin {
widget_exists = true;
break;
}
}
!widget_exists
})
.collect();
if widgets_to_add.is_empty() {
return;
}
for widget in widgets_to_add {
let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
self.widgets.push(loaded_widget);
}
}
I have a structure like
struct Node {
pub id: String,
pub dis: String,
pub parent: Option<NodeRefNodeRefWeak>,
pub children: Vec<NodeRef>,
}
pub type NodeRef = Rc<RefCell<Node>>;
pub type NodeRefNodeRefWeak = Weak<RefCell<Node>>;
I also have a start of a function that can iterate this structure to
pull out a match on a node id but it has issues.
What I would like is for this function to return the parent node of the whole tree with ONLY the branches that have a match somewhere on the branch.
Children past the search node can be removed.
Ie a function that filters all other nodes out of the tree.
For example with my rust playground link I would like it to return
level0_node_#1 (level0_node_#1)
level1_node_4 (level1_node_4)
level2_node_4_3 (level2_node_4_3)
level3_node_4_3_2 (level3_node_4_3_2)
However, using the recursive approach as below causes real issue with already borrowed errors when trying to remove branches etc.
Is there a way to achieve this filter function?
I have a test in the Rust playground.
fn tree_filter_node_objects<F>(node: &NodeRef, f: F) -> Vec<NodeRef>
where F: Fn(&str) -> bool + Copy {
let mut filtered_nodes: Vec<NodeRef> = vec![];
let mut borrow = node.borrow_mut();
if f(&borrow.id) {
filtered_nodes.push(node.clone());
}
for n in borrow.children.iter() {
let children_filtered = tree_filter_node_objects(n, f);
for c in children_filtered.iter() {
filtered_nodes.push(c.clone());
}
}
filtered_nodes
}
In the end I used this iterative approach.
pub fn tree_filter_node_dfs<F>(root: &NodeRef, f: F) -> Vec<NodeRef>
where F: Fn(&BmosHaystackObject) -> bool + Copy {
let mut filtered_nodes: Vec<NodeRef> = vec![];
let mut cur_node: Option<NodeRef> = Some(root.clone());
let mut last_visited_child: Option<NodeRef> = None;
let mut next_child: Option<NodeRef>;
let mut run_visit: bool = true;
while cur_node.is_some() {
if run_visit {
let n = cur_node.as_ref().unwrap();
if f(&n.borrow().object) {
}
}
if last_visited_child.is_none() {
let children = cur_node.as_ref().unwrap().borrow().children.clone();
if children.len() > 0 {
next_child = Some(children[0].clone());
}
else {
next_child = None;
}
}
else {
next_child = tree_filter_node_get_next_sibling(last_visited_child.as_ref().unwrap());
}
if next_child.is_some() {
last_visited_child = None;
cur_node = next_child;
run_visit = true;
}
else {
last_visited_child = cur_node;
cur_node = tree_node_parent_node(&last_visited_child.clone().unwrap().clone());
run_visit = false;
}
}
filtered_nodes
}
I'm trying to write a kd-tree implementation, but I keep getting the error cannot move out of borrowed content.
This is my KDTree struct
pub struct KDTree {
pub bounding_box: Aabb,
pub axis: Option<Axis>,
left: Option<Box<KDTree>>,
right: Option<Box<KDTree>>,
pub objects: Option<Vec<Box<Geometry>>>,
}
This method, however, throws that error.
pub fn direct_samples(&self) -> Vec<u32> {
assert!(self.objects.is_some());
let mut direct_samples = Vec::new();
for (i, object) in self.objects
.expect("Expected tree to have objects")
.iter()
.enumerate() {
if object.material().emittance > 0f32 {
direct_samples.push(i as u32);
}
}
if self.left.is_some() {
direct_samples.extend(self.left.unwrap().direct_samples());
}
if self.right.is_some() {
direct_samples.extend(self.right.unwrap().direct_samples());
}
direct_samples
}
I understand that if I change the parameter to self instead of &self, it should work, but then when I call it, it gives the error use of moved value.
pub fn from_objects(objects: Vec<Box<Geometry>>) -> Scene {
let tree = KDTree::from_objects(objects);
Scene {
camera: Camera::new(),
objects: tree,
direct_samples: tree.direct_samples(),
}
}
Do I need to implement Copy on my KDTree? Won't this use a lot of cpu/memory to copy the entire thing?
The reason your code requires ownership of the KDTree is because you are calling Option::expect and Option::unwrap. The docs for these can be found here.
impl<T> Option<T> {
fn unwrap(self) -> T {
...
}
}
So when you are calling unwrap (or expect) the compiler rightly complains that you are taking the elements of your struct by value. To fix this, use the Option::as_ref method.
impl<T> Option<T> {
fn as_ref(&self) -> Option<&T> {
...
}
}
This will turn a reference to an option into an optional reference, which does not require ownership. You can see this in the signature of the function - it takes &self rather than self.
pub fn direct_samples(&self) -> Vec<u32> {
assert!(self.objects.is_some());
let mut direct_samples = Vec::new();
for (i, object) in self.objects.as_ref()
.expect("Expected tree to have objects")
.iter()
.enumerate() {
if object.material().emittance > 0f32 {
direct_samples.push(i as u32);
}
}
if self.left.is_some() {
direct_samples.extend(self.left.as_ref().unwrap().direct_samples());
}
if self.right.is_some() {
direct_samples.extend(self.right.as_ref().unwrap().direct_samples());
}
direct_samples
}
Do I need to implement Copy on my KDTree? Won't this use a lot of cpu/memory to copy the entire thing?
You can't implement Copy on your KDTree because it contains heap-allocated memory (boxes) - Copy means that your type can be copied just by copying its bytes, but that can't happen without invalidating single ownership in this case.