ExrWriter.hx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Based on miniexr.cpp - public domain - 2013 Aras Pranckevicius / Unity Technologies
  2. // https://github.com/aras-p/miniexr
  3. // https://www.openexr.com/documentation/openexrfilelayout.pdf
  4. package arm.format;
  5. class ExrWriter {
  6. public function new(out: haxe.io.BytesOutput, width: Int, height: Int, src: haxe.io.Bytes, bits = 16, type = 1, off = 0) {
  7. out.writeByte(0x76); // magic
  8. out.writeByte(0x2f);
  9. out.writeByte(0x31);
  10. out.writeByte(0x01);
  11. out.writeByte(2); // version, scanline
  12. out.writeByte(0);
  13. out.writeByte(0);
  14. out.writeByte(0);
  15. out.writeString("channels");
  16. out.writeByte(0);
  17. out.writeString("chlist");
  18. out.writeByte(0);
  19. out.writeByte(55);
  20. out.writeByte(0);
  21. out.writeByte(0);
  22. out.writeByte(0);
  23. var attrib = bits == 16 ? 1 : 2; // half, float
  24. out.writeByte("B".code); // B
  25. out.writeByte(0);
  26. out.writeByte(attrib);
  27. out.writeByte(0);
  28. out.writeByte(0);
  29. out.writeByte(0);
  30. out.writeByte(0);
  31. out.writeByte(0);
  32. out.writeByte(0);
  33. out.writeByte(0);
  34. out.writeByte(1);
  35. out.writeByte(0);
  36. out.writeByte(0);
  37. out.writeByte(0);
  38. out.writeByte(1);
  39. out.writeByte(0);
  40. out.writeByte(0);
  41. out.writeByte(0);
  42. out.writeByte("G".code); // G
  43. out.writeByte(0);
  44. out.writeByte(attrib);
  45. out.writeByte(0);
  46. out.writeByte(0);
  47. out.writeByte(0);
  48. out.writeByte(0);
  49. out.writeByte(0);
  50. out.writeByte(0);
  51. out.writeByte(0);
  52. out.writeByte(1);
  53. out.writeByte(0);
  54. out.writeByte(0);
  55. out.writeByte(0);
  56. out.writeByte(1);
  57. out.writeByte(0);
  58. out.writeByte(0);
  59. out.writeByte(0);
  60. out.writeByte("R".code); // R
  61. out.writeByte(0);
  62. out.writeByte(attrib);
  63. out.writeByte(0);
  64. out.writeByte(0);
  65. out.writeByte(0);
  66. out.writeByte(0);
  67. out.writeByte(0);
  68. out.writeByte(0);
  69. out.writeByte(0);
  70. out.writeByte(1);
  71. out.writeByte(0);
  72. out.writeByte(0);
  73. out.writeByte(0);
  74. out.writeByte(1);
  75. out.writeByte(0);
  76. out.writeByte(0);
  77. out.writeByte(0);
  78. out.writeByte(0);
  79. out.writeString("compression");
  80. out.writeByte(0);
  81. out.writeString("compression");
  82. out.writeByte(0);
  83. out.writeByte(1);
  84. out.writeByte(0);
  85. out.writeByte(0);
  86. out.writeByte(0);
  87. out.writeByte(0); // no compression
  88. out.writeString("dataWindow");
  89. out.writeByte(0);
  90. out.writeString("box2i");
  91. out.writeByte(0);
  92. out.writeByte(16);
  93. out.writeByte(0);
  94. out.writeByte(0);
  95. out.writeByte(0);
  96. out.writeByte(0);
  97. out.writeByte(0);
  98. out.writeByte(0);
  99. out.writeByte(0);
  100. out.writeByte(0);
  101. out.writeByte(0);
  102. out.writeByte(0);
  103. out.writeByte(0);
  104. var ww = width - 1;
  105. var hh = height - 1;
  106. out.writeByte(ww & 0xff);
  107. out.writeByte((ww >> 8) & 0xff);
  108. out.writeByte((ww >> 16) & 0xff);
  109. out.writeByte((ww >> 24) & 0xff);
  110. out.writeByte(hh & 0xff);
  111. out.writeByte((hh >> 8) & 0xff);
  112. out.writeByte((hh >> 16) & 0xff);
  113. out.writeByte((hh >> 24) & 0xff);
  114. out.writeString("displayWindow");
  115. out.writeByte(0);
  116. out.writeString("box2i");
  117. out.writeByte(0);
  118. out.writeByte(16);
  119. out.writeByte(0);
  120. out.writeByte(0);
  121. out.writeByte(0);
  122. out.writeByte(0);
  123. out.writeByte(0);
  124. out.writeByte(0);
  125. out.writeByte(0);
  126. out.writeByte(0);
  127. out.writeByte(0);
  128. out.writeByte(0);
  129. out.writeByte(0);
  130. out.writeByte(ww & 0xff);
  131. out.writeByte((ww >> 8) & 0xff);
  132. out.writeByte((ww >> 16) & 0xff);
  133. out.writeByte((ww >> 24) & 0xff);
  134. out.writeByte(hh & 0xff);
  135. out.writeByte((hh >> 8) & 0xff);
  136. out.writeByte((hh >> 16) & 0xff);
  137. out.writeByte((hh >> 24) & 0xff);
  138. out.writeString("lineOrder");
  139. out.writeByte(0);
  140. out.writeString("lineOrder");
  141. out.writeByte(0);
  142. out.writeByte(1);
  143. out.writeByte(0);
  144. out.writeByte(0);
  145. out.writeByte(0);
  146. out.writeByte(0); // increasing Y
  147. out.writeString("pixelAspectRatio");
  148. out.writeByte(0);
  149. out.writeString("float");
  150. out.writeByte(0);
  151. out.writeByte(4);
  152. out.writeByte(0);
  153. out.writeByte(0);
  154. out.writeByte(0);
  155. out.writeByte(0); // 1.0f
  156. out.writeByte(0);
  157. out.writeByte(0x80);
  158. out.writeByte(0x3f);
  159. out.writeString("screenWindowCenter");
  160. out.writeByte(0);
  161. out.writeString("v2f");
  162. out.writeByte(0);
  163. out.writeByte(8);
  164. out.writeByte(0);
  165. out.writeByte(0);
  166. out.writeByte(0);
  167. out.writeByte(0);
  168. out.writeByte(0);
  169. out.writeByte(0);
  170. out.writeByte(0);
  171. out.writeByte(0);
  172. out.writeByte(0);
  173. out.writeByte(0);
  174. out.writeByte(0);
  175. out.writeString("screenWindowWidth");
  176. out.writeByte(0);
  177. out.writeString("float");
  178. out.writeByte(0);
  179. out.writeByte(4);
  180. out.writeByte(0);
  181. out.writeByte(0);
  182. out.writeByte(0);
  183. out.writeByte(0); // 1.0f
  184. out.writeByte(0);
  185. out.writeByte(0x80);
  186. out.writeByte(0x3f);
  187. out.writeByte(0); // end of header
  188. var channels = 4;
  189. var byteSize = bits == 16 ? 2 : 4;
  190. var kHeaderSize = out.length;
  191. var kScanlineTableSize = 8 * height;
  192. var pixelRowSize = width * 3 * byteSize;
  193. var fullRowSize = pixelRowSize + 8;
  194. // line offset table
  195. var ofs = kHeaderSize + kScanlineTableSize;
  196. for (y in 0...height) {
  197. out.writeByte(ofs & 0xff);
  198. out.writeByte((ofs >> 8) & 0xff);
  199. out.writeByte((ofs >> 16) & 0xff);
  200. out.writeByte((ofs >> 24) & 0xff);
  201. out.writeByte(0);
  202. out.writeByte(0);
  203. out.writeByte(0);
  204. out.writeByte(0);
  205. ofs += fullRowSize;
  206. }
  207. // scanline data
  208. var stride = channels * byteSize;
  209. var pos = 0;
  210. function writeLine16(bytePos: Int) {
  211. for (x in 0...width) {
  212. out.writeByte(src.get(bytePos ));
  213. out.writeByte(src.get(bytePos + 1));
  214. bytePos += stride;
  215. }
  216. }
  217. function writeLine32(bytePos: Int) {
  218. for (x in 0...width) {
  219. out.writeByte(src.get(bytePos ));
  220. out.writeByte(src.get(bytePos + 1));
  221. out.writeByte(src.get(bytePos + 2));
  222. out.writeByte(src.get(bytePos + 3));
  223. bytePos += stride;
  224. }
  225. }
  226. var writeLine = bits == 16 ? writeLine16 : writeLine32;
  227. function writeBGR(off: Int) {
  228. writeLine(pos + byteSize * 2);
  229. writeLine(pos + byteSize);
  230. writeLine(pos);
  231. }
  232. function writeSingle(off: Int) {
  233. writeLine(pos + off * byteSize);
  234. writeLine(pos + off * byteSize);
  235. writeLine(pos + off * byteSize);
  236. }
  237. var writeData = type == 1 ? writeBGR : writeSingle;
  238. for (y in 0...height) {
  239. // coordinate
  240. out.writeByte(y & 0xff);
  241. out.writeByte((y >> 8) & 0xff);
  242. out.writeByte((y >> 16) & 0xff);
  243. out.writeByte((y >> 24) & 0xff);
  244. // data size
  245. out.writeByte(pixelRowSize & 0xff);
  246. out.writeByte((pixelRowSize >> 8) & 0xff);
  247. out.writeByte((pixelRowSize >> 16) & 0xff);
  248. out.writeByte((pixelRowSize >> 24) & 0xff);
  249. // data
  250. writeData(off);
  251. pos += width * stride;
  252. }
  253. }
  254. }