about summary refs log tree commit diff stats
path: root/adapter/img/resize.nim
blob: 5bd29b633d776ce755383db3d1aef85b5ae8c5d8 (plain) (blame)
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
import std/options
import std/os
import std/posix
import std/strutils

import io/dynstream
import utils/sandbox
import utils/twtstr

{.compile("stb_image_resize.c", "-O3").}

{.push header: "stb_image_resize.h".}
proc stbir_resize_uint8(input_pixels: ptr uint8;
  input_w, input_h, input_stride_in_bytes: cint; output_pixels: ptr uint8;
  output_w, output_h, output_stride_in_bytes, num_channels: cint): cint
  {.importc.}
{.pop.}

proc die(s: string) {.noreturn.} =
  let os = newPosixStream(STDOUT_FILENO)
  os.sendDataLoop(s)
  quit(1)

proc main() =
  var srcWidth = cint(-1)
  var srcHeight = cint(-1)
  var dstWidth = cint(-1)
  var dstHeight = cint(-1)
  for hdr in getEnv("REQUEST_HEADERS").split('\n'):
    let k = hdr.until(':')
    if k == "Cha-Image-Target-Dimensions" or k == "Cha-Image-Dimensions":
      let v = hdr.after(':').strip()
      let s = v.split('x')
      if s.len != 2:
        die("Cha-Control: ConnectionError 1 wrong dimensions\n")
      let w = parseUInt32(s[0], allowSign = false)
      let h = parseUInt32(s[1], allowSign = false)
      if w.isNone or w.isNone:
        die("Cha-Control: ConnectionError 1 wrong dimensions\n")
      if k == "Cha-Image-Target-Dimensions":
        dstWidth = cint(w.get)
        dstHeight = cint(h.get)
      else:
        srcWidth = cint(w.get)
        srcHeight = cint(h.get)
  let ps = newPosixStream(STDIN_FILENO)
  let os = newPosixStream(STDOUT_FILENO)
  let src = ps.recvDataLoopOrMmap(int(srcWidth * srcHeight * 4))
  let dst = os.maybeMmapForSend(int(dstWidth * dstHeight * 4 + 1))
  if src == nil or dst == nil:
    die("Cha-Control: ConnectionError 1 failed to open i/o\n")
  dst.p[0] = uint8('\n') # for CGI
  enterNetworkSandbox()
  doAssert stbir_resize_uint8(addr src.p[0], srcWidth, srcHeight, 0,
    addr dst.p[1], dstWidth, dstHeight, 0, 4) == 1
  os.sendDataLoop(dst)
  dealloc(src)
  dealloc(dst)

main()