Skip to main content

Overview

Mslicer includes several post-processing operations that run after the initial slicing process to improve print quality. These operations are applied to the sliced layers before the file is saved.

Anti-Aliasing

Anti-aliasing smooths the edges of sliced layers using a Gaussian blur, reducing the appearance of layer lines and improving surface quality.

How It Works

The anti-aliasing algorithm uses a fast Gaussian blur implementation from the libblur library:
  1. Processes each layer in parallel for performance
  2. Applies an anisotropic Gaussian blur with configurable radius
  3. Uses clamp edge mode to prevent artifacts at boundaries
  4. Operates on grayscale image data
// From anti_alias.rs:32-38
let mut image = BlurImageMut::borrow(
    layer.inner_mut(), 
    width, 
    height, 
    FastBlurChannels::Plane
);
libblur::fast_gaussian_next(
    &mut image,
    AnisotropicRadius::new(self.radius as u32),
    ThreadingPolicy::Single,
    EdgeMode2D::new(EdgeMode::Clamp),
)

Configuration

Enabled: Boolean flag to enable/disable anti-aliasing
Radius: Blur radius in pixels (default: 1.0)

When to Use

Enable For

  • Models with visible layer lines
  • Detailed miniatures
  • Smooth curved surfaces
  • Display pieces

Disable For

  • Mechanical parts needing sharp edges
  • Models with fine text
  • When maximum detail is critical
  • Very small features

Performance

Anti-aliasing uses parallel processing with Rayon:
// From anti_alias.rs:25-26
SliceLayerIterator::new(file)
    .par_bridge()
    .for_each(|mut layer| {
        // Process layer
    });
Progress is tracked with a progress bar showing the number of layers processed.
Anti-aliasing typically adds 10-30 seconds to the slicing process depending on the number of layers and blur radius.

Elephant Foot Compensation

Elephant foot is a common 3D printing issue where the first few layers are wider than intended due to the weight of the model compressing the uncured resin. The elephant foot fixer compensates for this by reducing the intensity of pixels near the edges of bottom layers.

How It Works

The algorithm uses morphological erosion to detect and fix elephant foot:
  1. Calculates erosion radius based on physical dimensions:
    // From elephant_foot_fixer.rs:32-35
    let (x_radius, y_radius) = (
        (self.inset_distance * (width as f32 / info.size.x).get::<Milimeter>()) as usize,
        (self.inset_distance * (height as f32 / info.size.y).get::<Milimeter>()) as usize,
    );
    
  2. Generates elliptical mask for erosion
  3. Applies grayscale erosion to detect edge pixels
  4. Darkens edge pixels by the intensity multiplier
// From elephant_foot_fixer.rs:53-59
layer.gray_image(|layer| {
    let erode = imageproc::morphology::grayscale_erode(layer, &mask);
    for (x, y, pixel) in layer.enumerate_pixels_mut() {
        if erode.get_pixel(x, y)[0] == 0 && pixel[0] != 0 {
            *pixel = Luma([darken(pixel[0])]);
        }
    }
})

Configuration

Enabled: Boolean flag to enable/disable elephant foot compensation Inset Distance: Physical distance to inset from edges in millimeters (default: 0.5)
This controls how far from the edge the compensation extends.
Intensity Multiplier: Percentage of original brightness to maintain (default: 30.0)
For example, 30.0 means edge pixels are reduced to 30% of their original intensity.

Example Configuration

ElephantFootFixer {
    enabled: true,
    inset_distance: 0.5,        // 0.5mm inset
    intensity_multiplier: 30.0, // Reduce to 30% brightness
}

Visual Explanation

1

Original Layer

The bottom layer has full intensity pixels all the way to the edge.
2

Erosion Detection

Morphological erosion identifies pixels near the edge that will be affected.
3

Intensity Reduction

Edge pixels are darkened to 30% (or configured value) of original brightness.
4

Result

The reduced exposure at edges prevents over-curing and elephant foot.

Processing Details

Only the first few layers are processed:
// From elephant_foot_fixer.rs:48-50
SliceLayerIterator::new(file)
    .take(info.bottom_layers as usize)
    .par_bridge()
The number of layers processed is determined by the bottom_layers configuration in the slice settings.
Start with the default settings (0.5mm inset, 30% intensity) and adjust based on your results. If you still see elephant foot, try:
  • Increasing the inset distance to 0.7-1.0mm
  • Decreasing the intensity multiplier to 20-25%

Performance Logging

The operation logs timing information:
Eroding 5 bottom layers with radius (26, 26)
Eroded bottom layers in 1.23s

Mask Generation

Both operations use specialized mask generation:

Elliptical Mask

The elephant foot fixer generates an elliptical mask for anisotropic erosion:
// From elephant_foot_fixer.rs:68-76
fn generate_mask(width: usize, height: usize) -> Mask {
    let (width, height) = ((width / 2) as i16, (height / 2) as i16);
    
    let points = (-width..=width)
        .cartesian_product(-height..=height)
        .map(|(x, y)| Point::new(x, y))
        .collect::<Vec<_>>();
    
    new_mask_unsafe(points)
}
This creates an elliptical region centered at (0, 0) that accounts for non-square pixels.

Serialization

Both post-processing operations can be serialized and deserialized:

Anti-Aliasing Format

// Serialized as:
// - bool: enabled
// - f32: radius

Elephant Foot Fixer Format

// Serialized as:
// - bool: enabled
// - f32: inset_distance
// - f32: intensity_multiplier

Best Practices

Anti-aliasing and elephant foot compensation can be used together:
  1. Elephant foot fixer runs first (modifies bottom layers)
  2. Anti-aliasing runs second (smooths all layers)
This provides both edge compensation and surface smoothing.
Always test post-processing settings with small test prints:
  1. Slice a small calibration piece with default settings
  2. Adjust one parameter at a time
  3. Compare results and note improvements
  4. Save successful configurations for future use
Post-processing adds time to the slicing process:
  • Anti-aliasing: ~10-30 seconds for typical models
  • Elephant foot: ~1-3 seconds for bottom layers
For batch processing, factor this into your workflow.

Implementation Details

Parallel Processing

Both operations use Rayon for parallel layer processing:
use rayon::iter::{ParallelBridge, ParallelIterator};

SliceLayerIterator::new(file)
    .par_bridge()
    .for_each(|mut layer| {
        // Process each layer in parallel
    });
This provides significant performance improvements on multi-core systems.

Progress Tracking

let progress = Progress::new();
progress.set_total(file.info().layers as u64);

// During processing
progress.add_complete(1);

// When done
progress.set_finished();
The progress system provides real-time feedback during post-processing operations.
Post-processing operations modify the slice data permanently. Always save your slice configuration if you want to re-slice without post-processing later.

Build docs developers (and LLMs) love