diff options
author | bptato <nincsnevem662@gmail.com> | 2024-06-21 18:37:33 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-06-21 18:37:33 +0200 |
commit | 51ae4cc4ec4402f78bbda6de5207c60b6a1aaf86 (patch) | |
tree | 687e668736dd5c8638df45cc8342773069bcebf0 /adapter/img/stbi.nim | |
parent | b8a21c2407a9898a538852098eca5658de5afd37 (diff) | |
download | chawan-51ae4cc4ec4402f78bbda6de5207c60b6a1aaf86.tar.gz |
stbi: add encoders
Diffstat (limited to 'adapter/img/stbi.nim')
-rw-r--r-- | adapter/img/stbi.nim | 97 |
1 files changed, 80 insertions, 17 deletions
diff --git a/adapter/img/stbi.nim b/adapter/img/stbi.nim index 35ef8f64..c0f44c86 100644 --- a/adapter/img/stbi.nim +++ b/adapter/img/stbi.nim @@ -1,8 +1,13 @@ +import std/options import std/os +import std/strutils import utils/sandbox import utils/twtstr +{.passc: "-fno-strict-aliasing".} +{.passl: "-fno-strict-aliasing".} + {.compile: "stb_image.c".} type stbi_io_callbacks = object @@ -16,6 +21,8 @@ proc stbi_load_from_callbacks(clbk: ptr stbi_io_callbacks; user: pointer; proc stbi_failure_reason(): cstring {.importc.} +proc stbi_image_free(retval_from_stbi_load: pointer) {.importc.} + proc myRead(user: pointer; data: ptr uint8; size: cint): cint {.cdecl.} = return cint(stdin.readBuffer(data, size)) @@ -32,26 +39,82 @@ proc mySkip(user: pointer; n: cint) {.cdecl.} = proc myEof(user: pointer): cint {.cdecl.} = return cint(stdin.endOfFile()) +type stbi_write_func = proc(context, data: pointer; size: cint) {.cdecl.} + +proc stbi_write_png_to_func(fun: stbi_write_func; context: pointer; + w, h, comp: cint; data: pointer; stride_in_bytes: cint) {.importc.} +proc stbi_write_bmp_to_func(fun: stbi_write_func; context: pointer; + w, h, comp: cint; data: pointer) {.importc.} +proc stbi_write_jpg_to_func(fun: stbi_write_func; context: pointer; + w, h, comp: cint; data: pointer; quality: cint) {.importc.} + +proc myWriteFunc(context, data: pointer; size: cint) {.cdecl.} = + discard stdout.writeBuffer(data, size) + proc main() = enterNetworkSandbox() let scheme = getEnv("MAPPED_URI_SCHEME") let f = scheme.after('+') - if f notin ["jpeg", "gif", "bmp", "png"]: - stdout.write("Cha-Control: ConnectionError 1 wrong format " & f) - var x: cint - var y: cint - var channels_in_file: cint - var clbk = stbi_io_callbacks( - read: myRead, - skip: mySkip, - eof: myEof - ) - let p = stbi_load_from_callbacks(addr clbk, nil, x, y, channels_in_file, 4) - if p == nil: - stdout.write("Cha-Control: ConnectionError 1 stbi error " & - $stbi_failure_reason()) - return - stdout.write("Cha-Image-Dimensions: " & $x & "x" & $y & "\n\n") - discard stdout.writeBuffer(p, x * y * 4) + case getEnv("MAPPED_URI_PATH") + of "decode": + if f notin ["jpeg", "gif", "bmp", "png"]: + stdout.write("Cha-Control: ConnectionError 1 unknown format " & f) + var x: cint + var y: cint + var channels_in_file: cint + var clbk = stbi_io_callbacks( + read: myRead, + skip: mySkip, + eof: myEof + ) + let p = stbi_load_from_callbacks(addr clbk, nil, x, y, channels_in_file, 4) + if p == nil: + stdout.write("Cha-Control: ConnectionError 1 stbi error " & + $stbi_failure_reason()) + return + stdout.write("Cha-Image-Dimensions: " & $x & "x" & $y & "\n\n") + discard stdout.writeBuffer(p, x * y * 4) + stbi_image_free(p) + of "encode": + let headers = getEnv("REQUEST_HEADERS") + var quality = cint(50) + var width = cint(0) + var height = cint(0) + for hdr in headers.split('\n'): + case hdr.until(':') + of "Cha-Image-Dimensions": + let s = hdr.after(':').strip().split('x') + #TODO error handling + let w = parseUInt32(s[0], allowSign = false) + let h = parseUInt32(s[1], allowSign = false) + if w.isNone or w.isNone: + stdout.write("Cha-Control: ConnectionError 1 wrong dimensions") + return + width = cint(w.get) + height = cint(h.get) + of "Cha-Image-Quality": + let s = hdr.after(':').strip() + let q = parseUInt32(s, allowSign = false).get(101) + if q < 1 or 100 < q: + stdout.write("Cha-Control: ConnectionError 1 wrong quality") + return + quality = cint(q) + let s = stdin.readAll() + if s.len != width * height * 4: + stdout.write("Cha-Control: ConnectionError 1 wrong size") + return + stdout.write("Cha-Image-Dimensions: " & $width & 'x' & $height & "\n\n") + let p = unsafeAddr s[0] + case f + of "png": + stbi_write_png_to_func(myWriteFunc, nil, cint(width), cint(height), 4, p, + 0) + of "bmp": + stbi_write_bmp_to_func(myWriteFunc, nil, cint(width), cint(height), 4, p) + of "jpeg": + stbi_write_jpg_to_func(myWriteFunc, nil, cint(width), cint(height), 4, p, + quality) + else: + stdout.write("Cha-Control: ConnectionError 1 unknown format " & f) main() |