summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app/utils/image.utils.js
blob: dced2d87feeac7cfdadd106f4c17b24034cd153d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
const preloadedImages = {}

export const preloadImages = urls => batchPromise(urls, 4, preloadImage)

export const batchPromise = (list, count, fn) => {
  // console.log(list, count, fn)
  return new Promise((resolve, reject) => {
    let index = 0
    let len = list.length
    const worker = j => (
      new Promise(resolveWorker => {
        const next = () => {
          const i = index++
          if (i >= len) {
            return resolveWorker()
          }
          const item = list[i]
          // console.log(['worker', j, '=>', i, item].join(' '))
          fn(item)
          .then(next)
          .catch(err => {
            console.error(err, item)
            next()
          })
        }
        next()
      })
    )
    const workers = []
    for (let j = 0; j < count; j++) {
      workers.push(worker(j))
    }
    Promise.all(workers)
    .then(resolve)
    .catch(reject)
  })
}

export const preloadImage = (url, anonymous=false) => (
  new Promise((resolve, reject) => {
    if (preloadedImages[url] || typeof url === 'object' && url instanceof Image) {
      return resolve(url)
    }
    preloadedImages[url] = true
    const image = new Image()
    let loaded = false
    image.onload = () => {
      if (loaded) return
      loaded = true
      image.onload = null
      image.onerror = null
      resolve(image)
    }
    image.onerror = () => {
      if (loaded) return
      image.onload = null
      image.onerror = null
      reject(image)
    }
    // console.log(img.src)
    if (anonymous) {
      image.crossOrigin = 'anonymous'
    }
    image.src = url
    if (image.complete) {
      image.onload()
    }
  })
)

export const cropImage = (url, crop, maxSide) => {
  return new Promise((resolve, reject) => {
    preloadImage(url, true)
    .then(image => {
      let { x, y, w, h } = crop
      x = parseFloat(x)
      y = parseFloat(y)
      w = parseFloat(w)
      h = parseFloat(h)
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      const { naturalWidth, naturalHeight } = image
      
      let width, height
      let cropWidth = naturalWidth * w
      let cropHeight = naturalHeight * h

      if (maxSide > 0) {
        if (cropWidth > cropHeight) {
          width = Math.min(maxSide, cropWidth)
          height = cropHeight * width / cropWidth
        } else {
          height = Math.min(maxSide, cropHeight)
          width = cropWidth * height / cropHeight
        }
      } else {
        width = cropWidth
        height = cropHeight
      }

      canvas.width = width
      canvas.height = height

      ctx.drawImage(
        image,
        Math.round(x * naturalWidth),
        Math.round(y * naturalHeight),
        Math.round(w * naturalWidth),
        Math.round(h * naturalHeight),
        0, 0, canvas.width, canvas.height
      )
      // console.log(x, y, w, h)
      // console.log(naturalWidth, naturalHeight)
      // console.log(width, height)
      resolve(canvas)
    })
  })
}