Skip to content

Average Color Algorithm

The Average Color algorithm is the simplest and fastest method for creating pixel art. It calculates the arithmetic mean of all pixels within each grid cell to determine the representative color.

How It Works

Basic Concept

For each cell in the pixel grid:

  1. Collect all pixels within the cell boundaries
  2. Calculate the average red, green, and blue values
  3. Use this average as the cell's representative color

Mathematical Formula

For a cell containing pixels with RGB values (r₁,g₁,b₁), (r₂,g₂,b₂), ..., (rₙ,gₙ,bₙ):

Average Red   = (r₁ + r₂ + ... + rₙ) / n
Average Green = (g₁ + g₂ + ... + gₙ) / n
Average Blue  = (b₁ + b₂ + ... + bₙ) / n

The resulting color is: RGB(Average Red, Average Green, Average Blue)

Visual Example

Consider a 2×2 pixel cell with these colors:

┌─────────┬─────────┐
│ Red     │ Yellow  │
│ #FF0000 │ #FFFF00 │
├─────────┼─────────┤
│ Blue    │ Green   │
│ #0000FF │ #00FF00 │
└─────────┴─────────┘

Calculation:

  • Average Red: (255 + 255 + 0 + 0) / 4 = 127.5 ≈ 128
  • Average Green: (0 + 255 + 0 + 255) / 4 = 127.5 ≈ 128
  • Average Blue: (0 + 0 + 255 + 0) / 4 = 63.75 ≈ 64

Result: RGB(128, 128, 64) - a brownish color

Advantages

Speed

  • Fastest algorithm: Only requires one pass through the pixels
  • Minimal computation: Simple arithmetic operations
  • Low memory usage: No need to store intermediate data structures

Simplicity

  • Easy to understand: Straightforward mathematical concept
  • Predictable results: Deterministic output for given input
  • No parameters: No configuration needed

Efficiency

  • Parallel processing: Each cell can be processed independently
  • Cache friendly: Sequential memory access pattern
  • Scalable: Performance scales linearly with image size

Disadvantages

Color Quality Issues

Muddy Colors: When averaging diverse colors, the result can be unappetizing:

Bright Red + Bright Green = Muddy Brown
#FF0000 + #00FF00 = #808000

Loss of Vibrancy: Saturated colors tend to become desaturated:

Pure Blue + Pure Yellow = Gray
#0000FF + #FFFF00 = #808080

Visual Artifacts

Detail Loss: Fine details disappear when averaged with background:

  • Small bright highlights get averaged away
  • Thin lines may vanish completely
  • Text becomes illegible at low resolutions

Color Bleeding: Adjacent contrasting colors influence each other:

  • Sharp edges become soft
  • Color boundaries shift
  • Original color relationships are lost

Best Use Cases

Quick Previews

Perfect for rapid iteration when adjusting grid sizes:

bash
# Test different grid sizes quickly
pixel-art-rust -w 16 -h 16 -i photo.jpg -o test16.png
pixel-art-rust -w 32 -h 32 -i photo.jpg -o test32.png
pixel-art-rust -w 64 -h 64 -i photo.jpg -o test64.png

Uniform Images

Works well with images that have consistent coloring:

  • Sky gradients
  • Simple logos
  • Screenshots with limited color palettes
  • Abstract art with smooth transitions

Batch Processing

Ideal for processing large numbers of images:

bash
for img in photos/*.jpg; do
    pixel-art-rust -w 32 -h 32 -i "$img" -o "thumbnails/$(basename "$img")"
done

Real-time Applications

Suitable for interactive applications requiring immediate feedback:

  • Live camera filters
  • Gaming applications
  • Interactive art installations

Performance Characteristics

Time Complexity: O(n)

Where n is the number of pixels in the image. Each pixel is processed exactly once.

Space Complexity: O(1)

Only requires storage for running totals - no additional data structures needed.

Benchmarks

Typical processing times on modern hardware:

Image SizeGrid SizeProcessing Time
512×51216×160.005s
1024×102432×320.02s
2048×204864×640.08s
4096×4096128×1280.32s

Implementation Tips

Numerical Precision

When implementing, use appropriate data types to avoid overflow:

rust
// Avoid overflow with large images
let sum_r: u64 = pixels.iter().map(|p| p.r as u64).sum();
let avg_r = (sum_r / pixel_count as u64) as u8;

Floating Point Considerations

For more accurate averaging, consider using floating-point arithmetic:

rust
let avg_r = pixels.iter().map(|p| p.r as f32).sum() / pixel_count as f32;
let result_r = avg_r.round() as u8;

SIMD Optimization

The algorithm is well-suited for SIMD acceleration:

rust
// Pseudo-code for SIMD averaging
fn average_colors_simd(colors: &[RGB]) -> RGB {
    // Process 8 colors at once with AVX2
    // Sum all red, green, blue channels separately
    // Divide by count to get averages
}

Comparison with Other Algorithms

vs. Median Cut

  • Speed: Average is ~10x faster
  • Quality: Median Cut produces better color distribution
  • Use case: Average for speed, Median Cut for quality

vs. K-Means

  • Speed: Average is ~50x faster
  • Quality: K-Means produces significantly better results
  • Use case: Average for prototyping, K-Means for final output

vs. Quadtree

  • Speed: Similar performance for simple images
  • Adaptivity: Quadtree preserves detail better
  • Use case: Average for uniform content, Quadtree for varied detail

When NOT to Use Average Color

Avoid the average algorithm when:

High Quality Requirements

  • Final artwork for publication
  • Professional photography conversion
  • Detailed illustrations

Complex Color Relationships

  • Images with many saturated colors
  • High contrast photography
  • Artwork with careful color palettes

Small Grid Sizes with Detailed Images

  • Detailed photos converted to small grids (< 32×32)
  • Images with important fine details
  • Text or line art

Improving Results

Pre-processing

Consider image adjustments before conversion:

bash
# Increase contrast before averaging
convert input.jpg -contrast-stretch 5%x5% -normalize temp.jpg
pixel-art-rust -w 32 -h 32 -i temp.jpg -o output.png

Post-processing

Enhance results after conversion:

bash
# Increase saturation of pixel art
convert output.png -modulate 100,150,100 final.png

Hybrid Approaches

Use average for speed, then refine with other algorithms:

  1. Quick preview with average algorithm
  2. Adjust grid size based on preview
  3. Final render with median-cut or k-means

Example Workflows

Rapid Prototyping

bash
# Quick test of different aspect ratios
pixel-art-rust -w 32 -h 32 -i photo.jpg -o square.png
pixel-art-rust -w 48 -h 32 -i photo.jpg -o wide.png
pixel-art-rust -w 32 -h 48 -i photo.jpg -o tall.png

Batch Thumbnail Generation

bash
mkdir thumbnails
for img in gallery/*.jpg; do
    name=$(basename "$img" .jpg)
    pixel-art-rust -w 24 -h 24 -i "$img" -o "thumbnails/${name}_thumb.png"
done

Performance Testing

bash
# Test processing speed with different grid sizes
time pixel-art-rust -w 16 -h 16 -i large_image.jpg -o test16.png
time pixel-art-rust -w 64 -h 64 -i large_image.jpg -o test64.png

See Also

Released under the MIT License.