///|
pub fn downsample_half(image : GrayImage) -> GrayImage {
  let width = (image.width / 2).max(1)
  let height = (image.height / 2).max(1)
  let result = GrayImage(width~, height~)
  for y in 0.. GrayImage {
  let result = GrayImage(width=width.max(0), height=height.max(0))
  for y in 0.. GrayImage {
  let result = GrayImage(width=width.max(0), height=height.max(0))
  for y in 0.. Array[PyramidLevel] {
  let result : Array[PyramidLevel] = []
  let mut current = image
  let mut scale = 1.0
  for _ in 0.. GrayImage {
  if pyramid.is_empty() {
    GrayImage(width=0, height=0)
  } else {
    pyramid[index.clamp(min=0, max=pyramid.length() - 1)].image
  }
}

///|
pub fn pyramid_scales(pyramid : Array[PyramidLevel]) -> Array[Double] {
  pyramid.map(fn(level) { level.scale })
}

///|
pub fn blur_downsample(
  image : GrayImage,
  levels : Int,
  radius : Int,
) -> Array[PyramidLevel] {
  let result : Array[PyramidLevel] = []
  let mut current = image
  let mut scale = 1.0
  for _ in 0.. Array[PyramidLevel] {
  pyramid.map(fn(level) { { ..level, image: gradient_magnitude(level.image) } })
}

///|
pub fn pyramid_checksum(pyramid : Array[PyramidLevel]) -> Double {
  let mut result = 0.0
  for level in pyramid {
    result += level.scale * image_checksum(level.image)
  }
  result
}