Skip to content

Commit

Permalink
Add region{x1,y1,x2,y2,background_color} command and test
Browse files Browse the repository at this point in the history
  • Loading branch information
lilith committed Apr 17, 2020
1 parent 2acf6ad commit 3b9f0e5
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 26 deletions.
3 changes: 3 additions & 0 deletions imageflow_core/src/flow/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ impl From<s::Node> for Node {
s::Node::RegionPercent { .. } => {
Node::n(&nodes::REGION_PERCENT, NodeParams::Json(node))
}
s::Node::Region { .. } => {
Node::n(&nodes::REGION, NodeParams::Json(node))
}
s::Node::CopyRectToCanvas { .. } => {
Node::n(&nodes::COPY_RECT, NodeParams::Json(node))
}
Expand Down
98 changes: 78 additions & 20 deletions imageflow_core/src/flow/nodes/clone_crop_fill_expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub static CLONE: CloneDef = CloneDef{};
pub static EXPAND_CANVAS: ExpandCanvasDef = ExpandCanvasDef{};
pub static CROP_WHITESPACE: CropWhitespaceDef = CropWhitespaceDef{};
pub static REGION_PERCENT: RegionPercentDef = RegionPercentDef {};
pub static REGION: RegionDef = RegionDef {};

#[derive(Debug, Clone)]
pub struct CopyRectNodeDef;
Expand Down Expand Up @@ -232,17 +233,18 @@ pub struct RegionPercentDef;
impl RegionPercentDef {
fn get_coords(info:FrameInfo, left: f32, top: f32, right: f32, bottom: f32) -> (i32,i32,i32,i32){
let (x1, y1, mut x2, mut y2) =
((info.w as f32 * left).round() as i32,
(info.h as f32 * top).round() as i32,
(info.w as f32 * right).round() as i32,
(info.h as f32 * bottom).round() as i32);
((info.w as f32 * left / 100f32).round() as i32,
(info.h as f32 * top / 100f32).round() as i32,
(info.w as f32 * right / 100f32).round() as i32,
(info.h as f32 * bottom / 100f32).round() as i32);
//Round up to 1px if our percentages land on the same pixel
if x2 < x1 {
x2 = x1 + 1;
}
if y2 < y1{
y2 = y1 + 1;
}
//eprintln!("{}x{} {},{},{},{} -> {},{},{},{}", info.w, info.h, left, top, right, bottom, x1,y1,x2,y2);
return (x1,y1,x2,y2);

}
Expand All @@ -253,45 +255,102 @@ impl NodeDef for RegionPercentDef {
}
}
impl NodeDefOneInputExpand for RegionPercentDef {
fn fqn(&self) -> &'static str{
fn fqn(&self) -> &'static str {
"imazen.region_percent"
}
fn estimate(&self, p: &NodeParams, input: FrameEstimate) -> Result<FrameEstimate> {
if let NodeParams::Json(s::Node::RegionPercent { left, top, bottom, right, ref color }) = *p {
input.map_frame( |info| {
let (x1, y1, x2, y2) = RegionPercentDef::get_coords(info, left, top, right, bottom);
if let NodeParams::Json(imageflow_types::Node::RegionPercent { x1, y1, x2, y2, ref background_color }) = *p {
input.map_frame(|info| {
let (x1, y1, x2, y2) = RegionPercentDef::get_coords(info, x1, y1, x2, y2);
Ok(FrameInfo {
w: x2 - x1,
h: y2 - y1,
fmt: ffi::PixelFormat::from(info.fmt)
})
})
} else {
Err(nerror!(crate::ErrorKind::NodeParamsMismatch, "Need ExpandCanvas, got {:?}", p))
Err(nerror!(crate::ErrorKind::NodeParamsMismatch, "Need RegionPercent, got {:?}", p))
}
}
//TODO: If we want to support transparency on jpeg inputs we have to fix expand_canvas and copy_rect too
fn expand(&self, ctx: &mut OpCtxMut, ix: NodeIndex, p: NodeParams, input: FrameInfo) -> Result<()>{
if let NodeParams::Json(imageflow_types::Node::RegionPercent { left, top, bottom, right, color }) = p {
fn expand(&self, ctx: &mut OpCtxMut, ix: NodeIndex, p: NodeParams, input: FrameInfo) -> Result<()> {
if let NodeParams::Json(imageflow_types::Node::RegionPercent { x1: left, y1: top, y2: bottom, x2: right, background_color }) = p {
if bottom <= top || right <= left {
return Err(nerror!(crate::ErrorKind::InvalidNodeParams, "Invalid coordinates: {},{} {},{} should describe the top-left and bottom-right corners of the region in percentages. Not a rectangle.", left, top, right, bottom));
}

let (x1, y1, x2, y2) = RegionPercentDef::get_coords(input, left, top, right, bottom);

let region_params = imageflow_types::Node::Region {
x1,
y1,
x2,
y2,
background_color: background_color.clone()
};

//First crop, then expand
ctx.replace_node(ix, vec![
Node::n(&REGION,
NodeParams::Json(region_params)),
]);


Ok(())
} else {
Err(nerror!(crate::ErrorKind::NodeParamsMismatch, "Need RegionPercent, got {:?}", p))
}
}
}

#[derive(Debug,Clone)]
pub struct RegionDef;
impl NodeDef for RegionDef {
fn as_one_input_expand(&self) -> Option<&dyn NodeDefOneInputExpand>{
Some(self)
}
}
impl NodeDefOneInputExpand for RegionDef {
fn fqn(&self) -> &'static str{
"imazen.region"
}
fn estimate(&self, p: &NodeParams, input: FrameEstimate) -> Result<FrameEstimate> {
if let NodeParams::Json(imageflow_types::Node::Region { x1, y1, x2, y2, ref background_color }) = *p {
input.map_frame( |info| {
if y2 <= y1 || x2 <= x1 {
return Err(nerror!(crate::ErrorKind::InvalidNodeParams, "Invalid coordinates: {},{} {},{} should describe the top-left and bottom-right corners of the region in pixels. Not a rectangle.", x1, y1, x2, y2));
}
Ok(FrameInfo {
w: x2 - x1,
h: y2 - y1,
fmt: ffi::PixelFormat::from(info.fmt)
})
})
} else {
Err(nerror!(crate::ErrorKind::NodeParamsMismatch, "Need Region, got {:?}", p))
}
}
//TODO: If we want to support transparency on jpeg inputs we have to fix expand_canvas and copy_rect too
fn expand(&self, ctx: &mut OpCtxMut, ix: NodeIndex, p: NodeParams, input: FrameInfo) -> Result<()>{
if let NodeParams::Json(imageflow_types::Node::Region { x1, y1, y2, x2, background_color }) = p {
if y2 <= y1 || x2 <= x1 {
return Err(nerror!(crate::ErrorKind::InvalidNodeParams, "Invalid coordinates: {},{} {},{} should describe the top-left and bottom-righ corners of the region in pixels. Not a rectangle.", x1, y1, x2, y2));
}

if x1 >= input.w || y1 >= input.h || x2 <= 0 || y2 <= 0{
// No cropping of input image, we just create a canvas
let canvas_params = s::Node::CreateCanvas {
w: (x2-x1) as usize,
h: (y2-y1) as usize,
format: s::PixelFormat::from(input.fmt),
color: color.clone(),
color: background_color.clone(),
};
let canvas = ctx.graph
.add_node(Node::n(&CREATE_CANVAS,
NodeParams::Json(canvas_params)));
ctx.replace_node_with_existing(ix, canvas);

ctx.copy_edges_to(ix, canvas, EdgeDirection::Outgoing);
ctx.graph.remove_node(ix).unwrap();
}else{
let crop_params = imageflow_types::Node::Crop {
x1: i32::min(input.w, i32::max(0,x1)) as u32,
Expand All @@ -300,11 +359,11 @@ impl NodeDefOneInputExpand for RegionPercentDef {
y2: i32::min(input.h, i32::max(0,y2)) as u32
};
let expand_params = imageflow_types::Node::ExpandCanvas {
left: (i32::max(0, x1) * -1) as u32,
top: (i32::max(0, y1) * -1) as u32,
right: i32::min(0, x2 - input.w) as u32,
bottom: i32::min(0, y2 - input.h) as u32,
color: color.clone()
left: i32::max(0, 0 - x1) as u32,
top: i32::max(0, 0 - y1) as u32,
right: i32::max(0, x2 - input.w) as u32,
bottom: i32::max(0, y2 - input.h) as u32,
color: background_color.clone()
};

//First crop, then expand
Expand All @@ -318,11 +377,10 @@ impl NodeDefOneInputExpand for RegionPercentDef {

Ok(())
} else {
Err(nerror!(crate::ErrorKind::NodeParamsMismatch, "Need RegionPercentage, got {:?}", p))
Err(nerror!(crate::ErrorKind::NodeParamsMismatch, "Need Region, got {:?}", p))
}
}
}

#[derive(Debug, Clone)]
pub struct CropMutNodeDef;

Expand Down
1 change: 1 addition & 0 deletions imageflow_core/src/flow/nodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub use self::clone_crop_fill_expand::CROP_WHITESPACE;
pub use self::clone_crop_fill_expand::CROP_MUTATE;
pub use self::clone_crop_fill_expand::EXPAND_CANVAS;
pub use self::clone_crop_fill_expand::REGION_PERCENT;
pub use self::clone_crop_fill_expand::REGION;
pub use self::clone_crop_fill_expand::FILL_RECT;
pub use self::codecs_and_pointer::BITMAP_BGRA_POINTER;
pub use self::codecs_and_pointer::DECODER;
Expand Down
41 changes: 40 additions & 1 deletion imageflow_core/tests/visuals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn test_expand_rect(){

#[test]
fn test_crop(){
for _ in 1..100 {
for _ in 1..100 { //WTF are we looping 100 times for?
let matched = compare(None, 500,
"FillRectAndCrop", POPULATE_CHECKSUMS, DEBUG_GRAPH, vec![
s::Node::CreateCanvas { w: 200, h: 200, format: s::PixelFormat::Bgra32, color: s::Color::Srgb(s::ColorSrgb::Hex("FF5555FF".to_owned())) },
Expand All @@ -86,6 +86,45 @@ fn test_crop(){
}
}

#[test]
fn test_off_surface_region(){

let matched = compare(None, 500,
"TestOffSurfaceRegion", POPULATE_CHECKSUMS, DEBUG_GRAPH, vec![
s::Node::CreateCanvas { w: 200, h: 200, format: s::PixelFormat::Bgra32, color: s::Color::Srgb(s::ColorSrgb::Hex("FF5555FF".to_owned())) },
s::Node::FillRect { x1: 0, y1: 0, x2: 10, y2: 100, color: s::Color::Srgb(s::ColorSrgb::Hex("0000FFFF".to_owned())) },
s::Node::RegionPercent { x1: -100f32, y1: -100f32, x2: -1f32, y2: -1f32, background_color: s::Color::Transparent}
]
);
assert!(matched);

}
#[test]
fn test_partial_region(){

let matched = compare(None, 500,
"TestPartialRegion", POPULATE_CHECKSUMS, DEBUG_GRAPH, vec![
s::Node::CreateCanvas { w: 200, h: 200, format: s::PixelFormat::Bgra32, color: s::Color::Srgb(s::ColorSrgb::Hex("FF5555FF".to_owned())) },
s::Node::FillRect { x1: 0, y1: 0, x2: 10, y2: 100, color: s::Color::Srgb(s::ColorSrgb::Hex("0000FFFF".to_owned())) },
s::Node::RegionPercent { x1: -10f32, y1: -10f32, x2: 40f32, y2: 40f32, background_color: s::Color::Transparent}
]
);
assert!(matched);

}
#[test]
fn test_pixels_region(){

let matched = compare(None, 500,
"TestPixelsRegion", POPULATE_CHECKSUMS, DEBUG_GRAPH, vec![
s::Node::CreateCanvas { w: 200, h: 200, format: s::PixelFormat::Bgra32, color: s::Color::Srgb(s::ColorSrgb::Hex("FF5555FF".to_owned())) },
s::Node::FillRect { x1: 0, y1: 0, x2: 10, y2: 100, color: s::Color::Srgb(s::ColorSrgb::Hex("0000FFFF".to_owned())) },
s::Node::Region { x1: -10, y1: -10, x2: 120, y2: 50, background_color: s::Color::Transparent}
]
);
assert!(matched);

}


// Replaces TEST_CASE("Test scale rings", "")
Expand Down
3 changes: 3 additions & 0 deletions imageflow_core/tests/visuals/checksums.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"ScaleIDCTFastvsSlow": "04549C40B272C69E8_0EED88CCC2F4CD12F",
"ScaleIDCT_approx_gamma": "01DD6D368FDF435EF_0E685FA15F0460A97",
"ScaleTheHouse": "047AE058719BD4B9C_0EED88CCC2F4CD12F",
"TestOffSurfaceRegion": "09FA1A44E855DFBB0_01D9D2C49A4E782F9",
"TestPartialRegion": "0C51C8FBFD7A960E5_0172196390B512E97",
"TestPixelsRegion": "0B42E995F9EF3B17E_0AB6E6EE83BE6CCAF",
"Test_Apply_Orientation_Landscape_1.jpg": "0DD4E589FF3B2583D_0AF9F040B874D83F7",
"Test_Apply_Orientation_Landscape_2.jpg": "0002595D4CEF82803_0AF9F040B874D83F7",
"Test_Apply_Orientation_Landscape_3.jpg": "0BE76E2D685843DBE_0AF9F040B874D83F7",
Expand Down
18 changes: 13 additions & 5 deletions imageflow_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,11 +509,19 @@ pub enum Node {
},
#[serde(rename="region_percent")]
RegionPercent {
left: f32,
top: f32,
right: f32,
bottom: f32,
color: Color,
x1: f32,
y1: f32,
x2: f32,
y2: f32,
background_color: Color,
},
#[serde(rename="region")]
Region {
x1: i32,
y1: i32,
x2: i32,
y2: i32,
background_color: Color,
},
#[serde(rename="transpose")]
Transpose,
Expand Down

0 comments on commit 3b9f0e5

Please sign in to comment.