File size: 1,958 Bytes
31c7d49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { SHARP_INTERNAL_RESOLUTION } from './sharpConstants'

export interface DecodedImageInfo {
  width: number
  height: number
}

export async function decodeImageBitmap(file: File): Promise<ImageBitmap> {
  try {
    return await createImageBitmap(file, {
      // `imageOrientation` is not fully typed in all TS DOM libs.
      imageOrientation: 'from-image' as never,
    })
  } catch {
    return createImageBitmap(file)
  }
}

export async function readImageInfo(file: File): Promise<DecodedImageInfo> {
  const bitmap = await decodeImageBitmap(file)
  try {
    return { width: bitmap.width, height: bitmap.height }
  } finally {
    bitmap.close()
  }
}

export async function imageFileToSharpTensor(file: File): Promise<{
  tensor: Float32Array
  width: number
  height: number
}> {
  const bitmap = await decodeImageBitmap(file)
  try {
    const tensor = imageBitmapToSharpTensor(bitmap, SHARP_INTERNAL_RESOLUTION)
    return {
      tensor,
      width: bitmap.width,
      height: bitmap.height,
    }
  } finally {
    bitmap.close()
  }
}

export function imageBitmapToSharpTensor(bitmap: ImageBitmap, size: number): Float32Array {
  const canvas = document.createElement('canvas')
  canvas.width = size
  canvas.height = size
  const context = canvas.getContext('2d', { willReadFrequently: true })
  if (!context) {
    throw new Error('Could not create a 2D canvas context for image preprocessing.')
  }

  context.clearRect(0, 0, size, size)
  context.drawImage(bitmap, 0, 0, size, size)
  const imageData = context.getImageData(0, 0, size, size)
  const pixels = imageData.data
  const pixelCount = size * size

  const tensor = new Float32Array(3 * pixelCount)
  let pixelOffset = 0
  for (let i = 0; i < pixelCount; i += 1) {
    tensor[i] = pixels[pixelOffset] / 255
    tensor[pixelCount + i] = pixels[pixelOffset + 1] / 255
    tensor[pixelCount * 2 + i] = pixels[pixelOffset + 2] / 255
    pixelOffset += 4
  }

  return tensor
}