Skip to content

Commit

Permalink
Merge pull request #321 from B-LechCode/big_images
Browse files Browse the repository at this point in the history
Big images
  • Loading branch information
woelper authored Sep 8, 2024
2 parents 11d1539 + a9c911b commit 479df66
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 137 deletions.
76 changes: 41 additions & 35 deletions src/appstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl Message {
}

pub struct TexWrap{
pub texture_array:Vec<Texture>,
texture_array:Vec<Texture>,
pub col_count:u32,
pub row_count:u32,
pub col_translation:u32,
Expand All @@ -59,16 +59,16 @@ pub struct TexWrap{

pub struct TextureResponse<'a>{
pub texture: &'a Texture,
pub u_tex_left_global : f32,
pub v_tex_top_global : f32,
pub u_offset_texture : f32,
pub v_offset_texture : f32,
u_tex_right_global : f32,
v_tex_bottom_global : f32,
pub u_tex_next_right_global : f32,
pub v_tex_next_bottom_global : f32,
pub u_scale:f32,
pub v_scale:f32
pub u_tex_left_global : f64,
pub v_tex_top_global : f64,
pub u_offset_texture : f64,
pub v_offset_texture : f64,
pub u_tex_right_global : f64,
pub v_tex_bottom_global : f64,
pub u_tex_next_right_global : f64,
pub v_tex_next_bottom_global : f64,
pub u_scale:f64,
pub v_scale:f64
}

impl TexWrap{
Expand Down Expand Up @@ -132,7 +132,7 @@ impl TexWrap{
let im_w = image.width();
let im_h = image.height();
let s = (im_w as f32, im_h as f32);
let max_texture_size = 128;//gfx.limits().max_texture_size; //
let max_texture_size = gfx.limits().max_texture_size; //128;//
let col_count = (im_w as f32/max_texture_size as f32).ceil() as u32;
let row_count = (im_h as f32/max_texture_size as f32).ceil() as u32;

Expand Down Expand Up @@ -227,40 +227,46 @@ impl TexWrap{
}
}

pub fn get_texture_at_uv(&self, ua:f32, va:f32)->TextureResponse {
let v = (va).max(0.0).min(1.0);
let u = ua.max(0.0).min(1.0);
let x = u*self.width();
let y = v*self.height();
pub fn get_texture_at_uv(&self, ua:f64, va:f64)->TextureResponse {
let xa = ua as f64*self.width()as f64;
let ya = va as f64*self.height()as f64;

let v = (va).max(0.0).min(1.0)as f64;
let u = ua.max(0.0).min(1.0)as f64;
let x = u*self.width()as f64;
let y = v*self.height()as f64;

let x_idx = (x /self.col_translation as f32).floor() as i32;
let y_idx = (y /self.row_translation as f32).floor() as i32;
let x_idx = (x /self.col_translation as f64).floor() as i32;
let y_idx = (y /self.row_translation as f64).floor() as i32;
let tex_idx = (y_idx*self.col_count as i32+x_idx).min((self.texture_array.len() as i32 -1));

let my_tex = &self.texture_array[tex_idx as usize];

let tex_left = x_idx*self.col_translation as i32;
let tex_top = y_idx*self.row_translation as i32;

let tex_right = tex_left+self.col_translation as i32;
let tex_bottom = tex_top+self.row_translation as i32;
let tex_right_next = tex_left+self.col_translation as i32;
let tex_bottom_next = tex_top+self.row_translation as i32;
//the current texture might be smaller than the set translation. (Last element on x or y axis)
let tex_right_next = tex_left+my_tex.width() as i32;
let tex_bottom_next = tex_top+my_tex.height() as i32;
let tex_right = tex_right_next;
let tex_bottom = tex_bottom_next;
let u_scale = my_tex.width() as f64/self.width() as f64;
let v_scale = my_tex.height() as f64/self.height() as f64;

let u_tex_left_global = tex_left as f32/self.width();
let v_tex_top_global = tex_top as f32/self.height();

let u_offset = (x-tex_left as f32)/self.col_translation as f32;
let v_offset = (y-tex_top as f32)/self.row_translation as f32;
let u_tex_left_global = tex_left as f64/self.width() as f64;
let v_tex_top_global = tex_top as f64/self.height() as f64;

let u_tex_right = tex_right as f32 /self.width();
let v_tex_bottom = tex_bottom as f32 /self.height();
let u_tex_next_right_global = tex_right_next as f32 /self.width();
let v_tex_next_bottom_global = tex_bottom_next as f32 /self.height();
let u_offset = (xa-tex_left as f64)/my_tex.width()as f64;
let v_offset = (ya-tex_top as f64)/my_tex.height()as f64;

let u_tex_right = tex_right as f64 /self.width()as f64;
let v_tex_bottom = tex_bottom as f64 /self.height()as f64;
let u_tex_next_right_global = tex_right_next as f64 /self.width()as f64;
let v_tex_next_bottom_global = tex_bottom_next as f64 /self.height()as f64;

let u_scale = self.col_translation as f32/self.width();
let v_scale = self.row_translation as f32/self.height();

TextureResponse {texture: &self.texture_array[tex_idx as usize],

TextureResponse {texture: my_tex,
u_tex_left_global,
v_tex_top_global,
u_offset_texture:u_offset,
Expand Down
4 changes: 2 additions & 2 deletions src/image_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,8 @@ pub fn open_image(img_location: &Path) -> Result<Receiver<Frame>> {
let mut decoder = PngDecoder::new(&contents);
decoder.set_options(
DecoderOptions::new_fast()
.set_max_height(50000)
.set_max_width(50000),
.set_max_height(128000)
.set_max_width(128000),
);

//animation
Expand Down
21 changes: 13 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1083,14 +1083,19 @@ fn drawe(app: &mut App, gfx: &mut Graphics, plugins: &mut Plugins, state: &mut O
state.image_geometry.offset.y,
state.image_geometry.scale);
} else {
//TODO: How to implement this efficient?
draw.pattern(&texture.texture_array[0])
.scale(state.image_geometry.scale, state.image_geometry.scale)
.translate(state.image_geometry.offset.x, state.image_geometry.offset.y)
.size(
texture.texture_array[0].width() * state.tiling as f32,
texture.texture_array[0].height() * state.tiling as f32,
);

for yi in 0..state.tiling {
for xi in 0..state.tiling {
//The "old" version used only a static offset, is this correct?
let translate_x = xi as f32* texture.width()*state.image_geometry.scale + state.image_geometry.offset.x;
let translate_y = yi as f32* texture.height()*state.image_geometry.scale + state.image_geometry.offset.y;

texture.draw_textures(&mut draw,
translate_x,
translate_y,
state.image_geometry.scale);
}
}
}

if state.persistent_settings.show_frame {
Expand Down
157 changes: 96 additions & 61 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ use log::{debug, error, info};
use mouse_position::mouse_position::Mouse;
use notan::{
egui::{self, *},
prelude::{App, Graphics},
prelude::{App, Graphics, BlendMode},
};
use notan::draw::*;
use std::{collections::BTreeSet, ops::RangeInclusive, path::PathBuf, time::Instant};
use strum::IntoEnumIterator;
const PANEL_WIDTH: f32 = 240.0;
Expand Down Expand Up @@ -183,7 +184,7 @@ impl EguiExt for Ui {
#[allow(unused)]
pub fn image_ui(ctx: &Context, state: &mut OculanteState, gfx: &mut Graphics) {
if let Some(texture) = &state.current_texture {
let tex_id = gfx.egui_register_texture(&texture.texture_array[0]); //TODO: Adapt if needed
//let tex_id = gfx.egui_register_texture(&texture.texture_array[0]); //TODO: Adapt if needed

let image_rect = Rect::from_center_size(
Pos2::new(
Expand All @@ -198,12 +199,12 @@ pub fn image_ui(ctx: &Context, state: &mut OculanteState, gfx: &mut Graphics) {
) * state.image_geometry.scale,
);

egui::Painter::new(ctx.clone(), LayerId::background(), ctx.available_rect()).image(
/*egui::Painter::new(ctx.clone(), LayerId::background(), ctx.available_rect()).image(
tex_id.id,
image_rect,
Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)),
Color32::WHITE,
);
);*/
}

// state.image_geometry.scale;
Expand Down Expand Up @@ -247,18 +248,14 @@ pub fn info_ui(ctx: &Context, state: &mut OculanteState, gfx: &mut Graphics) {
egui::ScrollArea::vertical().auto_shrink([false,true])
.show(ui, |ui| {
if let Some(texture) = &state.current_texture {
// texture.
let tex_id = gfx.egui_register_texture(&texture.texture_array[0]);

// width of image widget
// let desired_width = ui.available_width() - ui.spacing().indent;
let desired_width = PANEL_WIDTH - PANEL_WIDGET_OFFSET;

let desired_width = PANEL_WIDTH as f64 - PANEL_WIDGET_OFFSET as f64;

let scale = (desired_width / 8.) / texture.size().0;
let scale = (desired_width / 8.) / texture.size().0 as f64;

let uv_center = (
state.cursor_relative.x / state.image_geometry.dimensions.0 as f32,
(state.cursor_relative.y / state.image_geometry.dimensions.1 as f32),
state.cursor_relative.x as f64 / state.image_geometry.dimensions.0 as f64,
(state.cursor_relative.y as f64 / state.image_geometry.dimensions.1 as f64),
);

egui::Grid::new("info").show(ui, |ui| {
Expand Down Expand Up @@ -329,10 +326,11 @@ pub fn info_ui(ctx: &Context, state: &mut OculanteState, gfx: &mut Graphics) {
ui.end_row();
});


// make sure aspect ratio is compensated for the square preview
let ratio = texture.size().0 / texture.size().1;
let uv_size = (scale, scale * ratio);

let uv_size = (scale, scale * ratio as f64);
let bg_color = Color32::BLACK.linear_multiply(0.5);

/*let preview_rect = ui
.add(
Expand All @@ -346,43 +344,49 @@ pub fn info_ui(ctx: &Context, state: &mut OculanteState, gfx: &mut Graphics) {
)
.rect;*/

//Pre initialize the rectangle coordinates of the preview window
let mut bbox_tl = egui::pos2(f32::MAX, f32::MAX);
let mut bbox_br = egui::pos2(f32::MIN, f32::MIN);

//The uv positions in the image, we iterate over
let mut curr_cursor_v = uv_center.1 - uv_size.1;
let end_cursor_u = uv_center.0 + uv_size.0;
let end_cursor_v = uv_center.1 + uv_size.1;

let curr_spacing = ui.spacing().item_spacing;

ui.spacing_mut().item_spacing = egui::vec2(0.0, 0.0);
let mut curr_cursor_v = uv_center.1 - uv_size.1;
ui.vertical(|ui| {
//Ui position to start at
let base_ui_curs = nalgebra::Vector2::new(ui.cursor().min.x as f64, ui.cursor().min.y as f64);
let mut curr_ui_curs = base_ui_curs; //our start position

let mut counter_v = 0; //Safety measure...
while(curr_cursor_v<end_cursor_v && counter_v<10){
while(curr_cursor_v<end_cursor_v && counter_v<100){
counter_v += 1;
let mut counter_u = 0; //Safety measure...
let mut curr_cursor_u = uv_center.0 - uv_size.0;
let mut curr_tex_v_end:f32 = 0.0;
let mut curr_cursor_u = uv_center.0 - uv_size.0;
let mut next_tex_v_begin:f64 = 0.0;
let mut last_v_size: f64 = 0.0;

ui.horizontal(|ui| {
ui.spacing_mut().item_spacing = egui::vec2(0.0, 0.0);

while(curr_cursor_u<end_cursor_u && counter_u<10){
curr_ui_curs.x = base_ui_curs.x;

while(curr_cursor_u<end_cursor_u && counter_u<100){
counter_u += 1;


//Get Texure at current cursor position
let curr_tex = texture.get_texture_at_uv(curr_cursor_u, curr_cursor_v);

//Where does the picked texture end globally?
let mut curr_tex_u_end = f32::min(curr_tex.u_tex_next_right_global, end_cursor_u);
curr_tex_v_end = f32::min(curr_tex.v_tex_next_bottom_global, end_cursor_v);
let mut curr_tex_u_end = f64::min(curr_tex.u_tex_right_global, end_cursor_u);
let mut curr_tex_v_end = f64::min(curr_tex.v_tex_bottom_global, end_cursor_v);
let mut next_tex_u_begin = f64::min(curr_tex.u_tex_next_right_global, end_cursor_u);
next_tex_v_begin = f64::min(curr_tex.v_tex_next_bottom_global, end_cursor_v);

if end_cursor_u>1.0 && f32::abs(curr_tex.u_tex_next_right_global-1.0)< f32::EPSILON {
if end_cursor_u>1.0 && f64::abs(curr_tex.u_tex_right_global-1.0)< f64::EPSILON {
curr_tex_u_end = end_cursor_u;
next_tex_u_begin = end_cursor_u;
}

if end_cursor_v>1.0 && f32::abs(curr_tex.v_tex_next_bottom_global-1.0)< f32::EPSILON {
if end_cursor_v>1.0 && f64::abs(curr_tex.v_tex_bottom_global-1.0)< f64::EPSILON {
curr_tex_v_end = end_cursor_v;
next_tex_v_begin = end_cursor_v;
}

//The uv coordinates to draw the picked texture
Expand All @@ -394,43 +398,74 @@ pub fn info_ui(ctx: &Context, state: &mut OculanteState, gfx: &mut Graphics) {
//Display size
let u_size = desired_width*(curr_tex_u_end-curr_cursor_u)/(2.0*uv_size.0);
let v_size = desired_width*(curr_tex_v_end-curr_cursor_v)/(2.0*uv_size.1);

last_v_size = v_size;
let curr_ui_curs_after = curr_ui_curs+nalgebra::Vector2::new(u_size, 0.0);

//Safety measure: the cursor could perfectly hit the boundary between tiles
if(u_size<=f64::EPSILON)
{
curr_cursor_u += f64::EPSILON;
continue;
}

if(v_size<=f64::EPSILON)
{
curr_cursor_v += f64::EPSILON;
continue;
}


let tex_id2 = gfx.egui_register_texture(curr_tex.texture);

let r_ret = ui
.add(
let tex_id2 = gfx.egui_register_texture(curr_tex.texture);
let draw_tl_32 = Pos2::new(curr_ui_curs.x as f32, curr_ui_curs.y as f32);
let draw_br_64 = curr_ui_curs_after+nalgebra::Vector2::new(0.0, v_size);
let draw_br_32 = Pos2::new(draw_br_64.x as f32, draw_br_64.y as f32);
let r_ret =egui::Rect::from_min_max(draw_tl_32, draw_br_32);

egui::Image::new(tex_id2)
.maintain_aspect_ratio(false)
.fit_to_exact_size(egui::Vec2::new(u_size, v_size)
)

.fit_to_exact_size(egui::Vec2::new(u_size as f32, v_size as f32))
.uv(egui::Rect::from_x_y_ranges(
u_offset_texture_snipped ..=curr_tex_u_end_texture,
v_offset_texture_snipped ..=curr_tex_v_end_texture,
))
.texture_options(TextureOptions::LINEAR)
).rect;

//Update coordinates for preview rectangle
bbox_tl.x = bbox_tl.x.min(r_ret.left());
bbox_tl.y = bbox_tl.y.min(r_ret.top());

bbox_br.x = bbox_br.x.max(r_ret.right());
bbox_br.y = bbox_br.y.max(r_ret.bottom());

curr_cursor_u = curr_tex_u_end;
curr_tex_v_end = curr_tex_v_end;

}
});

curr_cursor_v = curr_tex_v_end;
}});
u_offset_texture_snipped as f32 ..=curr_tex_u_end_texture as f32,
v_offset_texture_snipped as f32 ..=curr_tex_v_end_texture as f32,
)
)
.paint_at(ui, r_ret);


//.texture_options(TextureOptions::LINEAR)
//).rect;

/*draw.image(&curr_tex.texture)
.blend_mode(BlendMode::NORMAL)
//.scale(u_size, scale)
.size(u_size, v_size)
.translate(curr_ui_curs.x, curr_ui_curs.y);*/

//Update coordinates for preview rectangle
bbox_tl.x = bbox_tl.x.min(r_ret.left());
bbox_tl.y = bbox_tl.y.min(r_ret.top());

bbox_br.x = bbox_br.x.max(r_ret.right());
bbox_br.y = bbox_br.y.max(r_ret.bottom());

curr_ui_curs = curr_ui_curs_after;
curr_cursor_u = next_tex_u_begin;
}

curr_ui_curs += nalgebra::Vector2::new(0.0, last_v_size);
curr_cursor_v = next_tex_v_begin;
}


let preview_rect = egui::Rect::from_min_max(bbox_tl, bbox_br);
ui.spacing_mut().item_spacing = curr_spacing;

ui.advance_cursor_after_rect(preview_rect);


let stroke_color = Color32::from_white_alpha(240);
let bg_color = Color32::BLACK.linear_multiply(0.5);

ui.painter_at(preview_rect).line_segment(
[preview_rect.center_bottom(), preview_rect.center_top()],
Stroke::new(4., bg_color),
Expand Down
Loading

0 comments on commit 479df66

Please sign in to comment.