| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- // Based on miniexr.cpp - public domain - 2013 Aras Pranckevicius / Unity Technologies
- // https://github.com/aras-p/miniexr
- // https://www.openexr.com/documentation/openexrfilelayout.pdf
- function parser_exr_write_string(out: i32[], str: string) {
- for (let i: i32 = 0; i < str.length; ++i) {
- array_push(out, char_code_at(str, i));
- }
- }
- let _parser_exr_width: i32;
- let _parser_exr_stride: i32;
- let _parser_exr_out: u8[];
- let _parser_exr_src_view: buffer_view_t;
- let _parser_exr_write_line: (byte_pos: i32)=> void;
- function parser_exr_write_line16(byte_pos: i32) {
- for (let x: i32 = 0; x < _parser_exr_width; ++x) {
- array_push(_parser_exr_out, buffer_view_get_u8(_parser_exr_src_view, byte_pos ));
- array_push(_parser_exr_out, buffer_view_get_u8(_parser_exr_src_view, byte_pos + 1));
- byte_pos += _parser_exr_stride;
- }
- }
- function parser_exr_write_line32(byte_pos: i32) {
- for (let x: i32 = 0; x < _parser_exr_width; ++x) {
- array_push(_parser_exr_out, buffer_view_get_u8(_parser_exr_src_view, byte_pos ));
- array_push(_parser_exr_out, buffer_view_get_u8(_parser_exr_src_view, byte_pos + 1));
- array_push(_parser_exr_out, buffer_view_get_u8(_parser_exr_src_view, byte_pos + 2));
- array_push(_parser_exr_out, buffer_view_get_u8(_parser_exr_src_view, byte_pos + 3));
- byte_pos += _parser_exr_stride;
- }
- }
- function parser_exr_write_bgr(off: i32, pos: i32, byte_size: i32) {
- _parser_exr_write_line(pos + byte_size * 2);
- _parser_exr_write_line(pos + byte_size);
- _parser_exr_write_line(pos);
- }
- function parser_exr_write_single(off: i32, pos: i32, byte_size: i32) {
- _parser_exr_write_line(pos + off * byte_size);
- _parser_exr_write_line(pos + off * byte_size);
- _parser_exr_write_line(pos + off * byte_size);
- }
- function parser_exr_run(width: i32, height: i32, src: buffer_t, bits: i32 = 16, type: i32 = 1, off: i32 = 0): buffer_t {
- let out: u8[] = [];
- array_push(out, 0x76); // magic
- array_push(out, 0x2f);
- array_push(out, 0x31);
- array_push(out, 0x01);
- array_push(out, 2); // version, scanline
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- parser_exr_write_string(out, "channels");
- array_push(out, 0);
- parser_exr_write_string(out, "chlist");
- array_push(out, 0);
- array_push(out, 55);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- let attrib: i32 = bits == 16 ? 1 : 2; // half, float
- array_push(out, char_code_at("B", 0)); // B
- array_push(out, 0);
- array_push(out, attrib);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 1);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 1);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, char_code_at("G", 0)); // G
- array_push(out, 0);
- array_push(out, attrib);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 1);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 1);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, char_code_at("R", 0)); // R
- array_push(out, 0);
- array_push(out, attrib);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 1);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 1);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- parser_exr_write_string(out, "compression");
- array_push(out, 0);
- parser_exr_write_string(out, "compression");
- array_push(out, 0);
- array_push(out, 1);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0); // no compression
- parser_exr_write_string(out, "dataWindow");
- array_push(out, 0);
- parser_exr_write_string(out, "box2i");
- array_push(out, 0);
- array_push(out, 16);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- let ww: i32 = width - 1;
- let hh: i32 = height - 1;
- array_push(out, ww & 0xff);
- array_push(out, (ww >> 8) & 0xff);
- array_push(out, (ww >> 16) & 0xff);
- array_push(out, (ww >> 24) & 0xff);
- array_push(out, hh & 0xff);
- array_push(out, (hh >> 8) & 0xff);
- array_push(out, (hh >> 16) & 0xff);
- array_push(out, (hh >> 24) & 0xff);
- parser_exr_write_string(out, "displayWindow");
- array_push(out, 0);
- parser_exr_write_string(out, "box2i");
- array_push(out, 0);
- array_push(out, 16);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, ww & 0xff);
- array_push(out, (ww >> 8) & 0xff);
- array_push(out, (ww >> 16) & 0xff);
- array_push(out, (ww >> 24) & 0xff);
- array_push(out, hh & 0xff);
- array_push(out, (hh >> 8) & 0xff);
- array_push(out, (hh >> 16) & 0xff);
- array_push(out, (hh >> 24) & 0xff);
- parser_exr_write_string(out, "lineOrder");
- array_push(out, 0);
- parser_exr_write_string(out, "lineOrder");
- array_push(out, 0);
- array_push(out, 1);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0); // increasing Y
- parser_exr_write_string(out, "pixelAspectRatio");
- array_push(out, 0);
- parser_exr_write_string(out, "float");
- array_push(out, 0);
- array_push(out, 4);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0); // 1.0f
- array_push(out, 0);
- array_push(out, 0x80);
- array_push(out, 0x3f);
- parser_exr_write_string(out, "screenWindowCenter");
- array_push(out, 0);
- parser_exr_write_string(out, "v2f");
- array_push(out, 0);
- array_push(out, 8);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- parser_exr_write_string(out, "screenWindowWidth");
- array_push(out, 0);
- parser_exr_write_string(out, "float");
- array_push(out, 0);
- array_push(out, 4);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0); // 1.0f
- array_push(out, 0);
- array_push(out, 0x80);
- array_push(out, 0x3f);
- array_push(out, 0); // end of header
- let channels: i32 = 4;
- let byte_size: i32 = bits == 16 ? 2 : 4;
- let k_header_size: i32 = out.length;
- let k_scanline_table_size: i32 = 8 * height;
- let pixel_row_size: i32 = width * 3 * byte_size;
- let full_row_size: i32 = pixel_row_size + 8;
- // line offset table
- let ofs: i32 = k_header_size + k_scanline_table_size;
- for (let y: i32 = 0; y < height; ++y) {
- array_push(out, ofs & 0xff);
- array_push(out, (ofs >> 8) & 0xff);
- array_push(out, (ofs >> 16) & 0xff);
- array_push(out, (ofs >> 24) & 0xff);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- array_push(out, 0);
- ofs += full_row_size;
- }
- // scanline data
- let stride: i32 = channels * byte_size;
- let pos: i32 = 0;
- let src_view: buffer_view_t = buffer_view_create(src);
- _parser_exr_width = width;
- _parser_exr_stride = stride;
- _parser_exr_out = out;
- _parser_exr_src_view = src_view;
- _parser_exr_write_line = bits == 16 ? parser_exr_write_line16 : parser_exr_write_line32;
- let write_data: (off: i32, pos: i32, byte_size: i32)=>void = type == 1 ? parser_exr_write_bgr : parser_exr_write_single;
- for (let y: i32 = 0; y < height; ++y) {
- // coordinate
- array_push(out, y & 0xff);
- array_push(out, (y >> 8) & 0xff);
- array_push(out, (y >> 16) & 0xff);
- array_push(out, (y >> 24) & 0xff);
- // data size
- array_push(out, pixel_row_size & 0xff);
- array_push(out, (pixel_row_size >> 8) & 0xff);
- array_push(out, (pixel_row_size >> 16) & 0xff);
- array_push(out, (pixel_row_size >> 24) & 0xff);
- // data
- write_data(off, pos, byte_size);
- pos += width * stride;
- }
- return u8_array_create_from_array(out).buffer;
- }
|