LiveScript ImageData双三次插值(Bicubic interpolation)图像缩放算法

浅析 HTML5 Canvas 的几种中文字体缩小方案》中用到的双三次插值算法的LiveScript实现.

代码是从《图像处理之三种常见双立方插值算法》的Java实现中翻译得来.

require! 'prelude-ls': {map, floor}

bicubic-interpolation-put = (zoom, src-image)->  
  color = (image, x, y) ->
    i = (y * image.width + x) * 4
    map (|| 0), image.data[i to i + 3]
  triangle-interpolation = f ->
    f = f / 2
    if f < 0
      f + 1
    else
      1 - f
  clamp = value ->
    return 255 if value > 255
    return 0 if value < 0
    value
  canvas = document.create-element \canvas
  canvas.width = src-image.width * zoom
  canvas.height = src-image.height * zoom
  ctx = canvas.get-context \2d
  dst-image = ctx.create-image-data canvas.width, canvas.height
  for dst-y from 0 til dst-image.height
    src-y = dst-y * zoom
    j = floor src-y
    t = src-y - j
    for dst-x from 0 til dst-image.width
      src-x = dst-x * zoom
      k = floor src-x
      u = src-x - k
      rgba = [0, 0, 0, 0]
      s = 0
      for m from -1 til 3
        for n from -1 til 3
          rgb = color src-image, j + m, k + n
          f1  = triangle-interpolation m - t
          f2 = triangle-interpolation -(n - u)
          s += f2 * f1
          rgba[0] += rgb[0] * f2 * f1
          rgba[1] += rgb[1] * f2 * f1
          rgba[2] += rgb[2] * f2 * f1
          rgba[3] += rgb[3] * f2 * f1
      dst-i = (dst-y * canvas.width + dst-x) * 4
      dst-image.data[dst-i + 0] = clamp parseInt rgba[0] / s
      dst-image.data[dst-i + 1] = clamp parseInt rgba[1] / s
      dst-image.data[dst-i + 2] = clamp parseInt rgba[2] / s
      dst-image.data[dst-i + 3] = clamp parseInt rgba[3] / s
  ctx.put-image-data dst-image, 0, 0
  canvas