fn process_pixel(
        &self,
        pos: Position,
        edges: &GrayImage,
        directions: &Directions,
        swt: &mut Image<Luma<u32>>,
    ) -> Option<Ray> {
        // Keep track of the image dimensions for boundary tests.
        let (width, height) = edges.dimensions();

        // The direction in which we travel the gradient depends on the type of text
        // we want to find. For dark text on light background, follow the opposite
        // direction (into the dark are); for light text on dark background, follow
        // the gradient as is.
        let gradient_direction: f32 = if self.dark_on_bright { -1. } else { 1. };

        // Starting from the current pixel we will shoot a ray into the direction
        // of the pixel's gradient and keep track of all pixels in that direction
        // that still lie on an edge.
        let mut ray = Vec::new();
        ray.push(pos);

        // Obtain the direction to step into.
        // TODO: Obtain arctan of directions initially, then obtain dir_x and dir_y using cos and sin here.
        //       See below for another use of the directions.
        let dir_x = unsafe { directions.x.unsafe_get_pixel(pos.x, pos.y) }[0];
        let dir_y = unsafe { directions.y.unsafe_get_pixel(pos.x, pos.y) }[0];

        // Since some pixels have no gradient, normalization of the gradient
        // is a division by zero for them, resulting in NaN. These values
        // should not bother us since we explicitly tested for an edge before.
        debug_assert!(!dir_x.is_nan());
        debug_assert!(!dir_y.is_nan());

        // Traverse the pixels along the direction.
        let mut prev_pos = Position { x: 0, y: 0 };
        let mut steps_taken: usize = 0;
        loop {
            // Advance to the next pixel on the line.
            steps_taken += 1;
            let cur_x =
                (pos.x as f32 + gradient_direction * dir_x * steps_taken as f32).floor() as i64;
            let cur_y =
                (pos.y as f32 + gradient_direction * dir_y * steps_taken as f32).floor() as i64;

            // If we reach the edge of the image without crossing a stroke edge,
            // we discard the result.
            if (cur_x < 0 || cur_x >= width as _) || (cur_y < 0 || cur_y >= height as _) {
                return None;
            }

            // The cast is safe because we know the position lies within the image range.
            let cur_x = cur_x as u32;
            let cur_y = cur_y as u32;

            // If the step width was too small, continue;
            let cur_pos = Position { x: cur_x, y: cur_y };
            if cur_pos == prev_pos {
                continue;
            }
            prev_pos = cur_pos;

            // The point is either on the line or the end of it, so we register it.
            ray.push(cur_pos);

            // If that pixel is not an edge, we are still on the line and
            // need to continue scanning.
            let edge = unsafe { edges.unsafe_get_pixel(cur_x, cur_y) }[0];
            // TODO: Verify edge value range, should be either 0 or 255.
            if edge < 128 {
                continue;
            }

            // If this edge is pointed in a direction approximately opposite of the
            // one we started in, it is approximately parallel. This means we
            // just found the other side of the stroke.
            // The original paper suggests the gradients need to be opposite +/- PI/6.
            // Since the dot product is the cosine of the enclosed angle and
            // cos(pi/6) = 0.8660254037844387, we can discard all values that exceed
            // this threshold.
            // TODO: arctan + cos and sin.
            let cur_dir_x = unsafe { directions.x.unsafe_get_pixel(cur_x, cur_y) }[0];
            let cur_dir_y = unsafe { directions.y.unsafe_get_pixel(cur_x, cur_y) }[0];
            let dot_product = dir_x * cur_dir_x + dir_y * cur_dir_y;
            if dot_product >= -0.866 {
                return None;
            }

            // Paint each of the pixels on the ray with their determined stroke width.
            let delta_x = (cur_pos.x as i64 - pos.x as i64);
            let delta_y = (cur_pos.y as i64 - pos.y as i64);
            let stroke_width = ((delta_x * delta_x + delta_y * delta_y) as f32)
                .sqrt()
                .floor() as u32;

            for p in ray.iter() {
                unsafe {
                    swt.unsafe_put_pixel(p.x, p.y, [stroke_width].into());
                }
            }

            return Some(ray);
        }
    }
/// Obtains the stroke width starting from the specified position.
Obtains the stroke width starting from the specified position.
Obtains the stroke width starting from the specified position .
fn process_pixel(
        &self,
        pos: Position,
        edges: &GrayImage,
        directions: &Directions,
        swt: &mut Image<Luma<u32>>,
    ) -> Option<Ray> {
        // Keep track of the image dimensions for boundary tests.
        let (width, height) = edges.dimensions();
        // The direction in which we travel the gradient depends on the type of text
        // we want to find. For dark text on light background, follow the opposite
        // direction (into the dark are); for light text on dark background, follow
        // the gradient as is.
        let gradient_direction: f32 = if self.dark_on_bright { -1. } else { 1. };
        // Starting from the current pixel we will shoot a ray into the direction
        // of the pixel's gradient and keep track of all pixels in that direction
        // that still lie on an edge.
        let mut ray = Vec::new();
        ray.push(pos);
        // Obtain the direction to step into.
        // TODO: Obtain arctan of directions initially, then obtain dir_x and dir_y using cos and sin here.
        //       See below for another use of the directions.
        let dir_x = unsafe { directions.x.unsafe_get_pixel(pos.x, pos.y) }[0];
        let dir_y = unsafe { directions.y.unsafe_get_pixel(pos.x, pos.y) }[0];
        // Since some pixels have no gradient, normalization of the gradient
        // is a division by zero for them, resulting in NaN. These values
        // should not bother us since we explicitly tested for an edge before.
        debug_assert!(!dir_x.is_nan());
        debug_assert!(!dir_y.is_nan());
        // Traverse the pixels along the direction.
        let mut prev_pos = Position { x: 0, y: 0 };
        let mut steps_taken: usize = 0;
        loop {
            // Advance to the next pixel on the line.
            steps_taken += 1;
            let cur_x =
                (pos.x as f32 + gradient_direction * dir_x * steps_taken as f32).floor() as i64;
            let cur_y =
                (pos.y as f32 + gradient_direction * dir_y * steps_taken as f32).floor() as i64;
            // If we reach the edge of the image without crossing a stroke edge,
            // we discard the result.
            if (cur_x < 0 || cur_x >= width as _) || (cur_y < 0 || cur_y >= height as _) {
                return None;
            }
            // The cast is safe because we know the position lies within the image range.
            let cur_x = cur_x as u32;
            let cur_y = cur_y as u32;
            // If the step width was too small, continue;
            let cur_pos = Position { x: cur_x, y: cur_y };
            if cur_pos == prev_pos {
                continue;
            }
            prev_pos = cur_pos;
            // The point is either on the line or the end of it, so we register it.
            ray.push(cur_pos);
            // If that pixel is not an edge, we are still on the line and
            // need to continue scanning.
            let edge = unsafe { edges.unsafe_get_pixel(cur_x, cur_y) }[0];
            // TODO: Verify edge value range, should be either 0 or 255.
            if edge < 128 {
                continue;
            }
            // If this edge is pointed in a direction approximately opposite of the
            // one we started in, it is approximately parallel. This means we
            // just found the other side of the stroke.
            // The original paper suggests the gradients need to be opposite +/- PI/6.
            // Since the dot product is the cosine of the enclosed angle and
            // cos(pi/6) = 0.8660254037844387, we can discard all values that exceed
            // this threshold.
            // TODO: arctan + cos and sin.
            let cur_dir_x = unsafe { directions.x.unsafe_get_pixel(cur_x, cur_y) }[0];
            let cur_dir_y = unsafe { directions.y.unsafe_get_pixel(cur_x, cur_y) }[0];
            let dot_product = dir_x * cur_dir_x + dir_y * cur_dir_y;
            if dot_product >= -0.866 {
                return None;
            }
            // Paint each of the pixels on the ray with their determined stroke width.
            let delta_x = (cur_pos.x as i64 - pos.x as i64);
            let delta_y = (cur_pos.y as i64 - pos.y as i64);
            let stroke_width = ((delta_x * delta_x + delta_y * delta_y) as f32)
                .sqrt()
                .floor() as u32;
            for p in ray.iter() {
                unsafe {
                    swt.unsafe_put_pixel(p.x, p.y, [stroke_width].into());
                }
            }
            return Some(ray);
        }
    }
fn process_pixel ( & self , pos : Position , edges : & GrayImage , directions : & Directions , swt : & mut Image < Luma < u32 > > , ) -> Option < Ray > { // Keep track of the image dimensions for boundary tests. let ( width , height ) = edges . dimensions ( ) ; // The direction in which we travel the gradient depends on the type of text // we want to find. For dark text on light background, follow the opposite // direction (into the dark are); for light text on dark background, follow // the gradient as is. let gradient_direction : f32 = if self . dark_on_bright { - 1. } else { 1. } ; // Starting from the current pixel we will shoot a ray into the direction // of the pixel's gradient and keep track of all pixels in that direction // that still lie on an edge. let mut ray = Vec :: new ( ) ; ray . push ( pos ) ; // Obtain the direction to step into. // TODO: Obtain arctan of directions initially, then obtain dir_x and dir_y using cos and sin here. //       See below for another use of the directions. let dir_x = unsafe { directions . x . unsafe_get_pixel ( pos . x , pos . y ) } [ 0 ] ; let dir_y = unsafe { directions . y . unsafe_get_pixel ( pos . x , pos . y ) } [ 0 ] ; // Since some pixels have no gradient, normalization of the gradient // is a division by zero for them, resulting in NaN. These values // should not bother us since we explicitly tested for an edge before. debug_assert ! ( dir_x is_nan ( ) ) ; debug_assert ! ( dir_y is_nan ( ) ) ; // Traverse the pixels along the direction. let mut prev_pos = Position { x : 0 , y : 0 } ; let mut steps_taken : usize = 0 ; loop { // Advance to the next pixel on the line. steps_taken += 1 ; let cur_x = ( pos . x as f32 + gradient_direction * dir_x * steps_taken as f32 ) . floor ( ) as i64 ; let cur_y = ( pos . y as f32 + gradient_direction * dir_y * steps_taken as f32 ) . floor ( ) as i64 ; // If we reach the edge of the image without crossing a stroke edge, // we discard the result. if ( cur_x < 0 || cur_x >= width as _ ) || ( cur_y < 0 || cur_y >= height as _ ) { return None ; } // The cast is safe because we know the position lies within the image range. let cur_x = cur_x as u32 ; let cur_y = cur_y as u32 ; // If the step width was too small, continue; let cur_pos = Position { x : cur_x , y : cur_y } ; if cur_pos == prev_pos { continue ; } prev_pos = cur_pos ; // The point is either on the line or the end of it, so we register it. ray . push ( cur_pos ) ; // If that pixel is not an edge, we are still on the line and // need to continue scanning. let edge = unsafe { edges . unsafe_get_pixel ( cur_x , cur_y ) } [ 0 ] ; // TODO: Verify edge value range, should be either 0 or 255. if edge < 128 { continue ; } // If this edge is pointed in a direction approximately opposite of the // one we started in, it is approximately parallel. This means we // just found the other side of the stroke. // The original paper suggests the gradients need to be opposite +/- PI/6. // Since the dot product is the cosine of the enclosed angle and // cos(pi/6) = 0.8660254037844387, we can discard all values that exceed // this threshold. // TODO: arctan + cos and sin. let cur_dir_x = unsafe { directions . x . unsafe_get_pixel ( cur_x , cur_y ) } [ 0 ] ; let cur_dir_y = unsafe { directions . y . unsafe_get_pixel ( cur_x , cur_y ) } [ 0 ] ; let dot_product = dir_x * cur_dir_x + dir_y * cur_dir_y ; if dot_product >= - 0.866 { return None ; } // Paint each of the pixels on the ray with their determined stroke width. let delta_x = ( cur_pos . x as i64 - pos . x as i64 ) ; let delta_y = ( cur_pos . y as i64 - pos . y as i64 ) ; let stroke_width = ( ( delta_x * delta_x + delta_y * delta_y ) as f32 ) . sqrt ( ) . floor ( ) as u32 ; for p in ray . iter ( ) { unsafe { swt . unsafe_put_pixel ( p . x , p . y , [ stroke_width ] . into ( ) ) ; } } return Some ( ray ) ; } }
Obtains the stroke width starting from the specified position.
Obtains the stroke width starting from the specified position .
&self
pos
Position
edges
&GrayImage
directions
&Directions
swt
&mut Image<Luma<u32>>
&self
pos
Position
edges
&GrayImage
directions
&Directions
swt
&mut Image<Luma<u32>>