Files
armorpaint/Sources/arm/format/ExrWriter.hx
T
luboslenco 15a2501906 Format
2019-10-06 19:03:59 +02:00

315 lines
6.3 KiB
Haxe

// Based on miniexr.cpp - public domain - 2013 Aras Pranckevicius / Unity Technologies
// https://github.com/aras-p/miniexr
// https://www.openexr.com/documentation/openexrfilelayout.pdf
package arm.format;
class ExrWriter {
public function new(out:haxe.io.BytesOutput, width:Int, height:Int, src:haxe.io.Bytes, bits = 16, type = 1, off = 0) {
out.writeByte(0x76); // magic
out.writeByte(0x2f);
out.writeByte(0x31);
out.writeByte(0x01);
out.writeByte(2); // version, scanline
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeString('channels');
out.writeByte(0);
out.writeString('chlist');
out.writeByte(0);
out.writeByte(55);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
var attrib = bits == 16 ? 1 : 2; // half, float
out.writeByte('B'.code); // B
out.writeByte(0);
out.writeByte(attrib);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(1);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(1);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte('G'.code); // G
out.writeByte(0);
out.writeByte(attrib);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(1);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(1);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte('R'.code); // R
out.writeByte(0);
out.writeByte(attrib);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(1);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(1);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeString('compression');
out.writeByte(0);
out.writeString('compression');
out.writeByte(0);
out.writeByte(1);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0); // no compression
out.writeString('dataWindow');
out.writeByte(0);
out.writeString('box2i');
out.writeByte(0);
out.writeByte(16);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
var ww = width - 1;
var hh = height - 1;
out.writeByte(ww&0xFF);
out.writeByte((ww>>8)&0xFF);
out.writeByte((ww>>16)&0xFF);
out.writeByte((ww>>24)&0xFF);
out.writeByte(hh&0xFF);
out.writeByte((hh>>8)&0xFF);
out.writeByte((hh>>16)&0xFF);
out.writeByte((hh>>24)&0xFF);
out.writeString('displayWindow');
out.writeByte(0);
out.writeString('box2i');
out.writeByte(0);
out.writeByte(16);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(ww&0xFF);
out.writeByte((ww>>8)&0xFF);
out.writeByte((ww>>16)&0xFF);
out.writeByte((ww>>24)&0xFF);
out.writeByte(hh&0xFF);
out.writeByte((hh>>8)&0xFF);
out.writeByte((hh>>16)&0xFF);
out.writeByte((hh>>24)&0xFF);
out.writeString('lineOrder');
out.writeByte(0);
out.writeString('lineOrder');
out.writeByte(0);
out.writeByte(1);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0); // increasing Y
out.writeString('pixelAspectRatio');
out.writeByte(0);
out.writeString('float');
out.writeByte(0);
out.writeByte(4);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0); // 1.0f
out.writeByte(0);
out.writeByte(0x80);
out.writeByte(0x3f);
out.writeString('screenWindowCenter');
out.writeByte(0);
out.writeString('v2f');
out.writeByte(0);
out.writeByte(8);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeString('screenWindowWidth');
out.writeByte(0);
out.writeString('float');
out.writeByte(0);
out.writeByte(4);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0); // 1.0f
out.writeByte(0);
out.writeByte(0x80);
out.writeByte(0x3f);
out.writeByte(0); // end of header
var channels = 4;
var byteSize = bits == 16 ? 2 : 4;
var kHeaderSize = out.length;
var kScanlineTableSize = 8 * height;
var pixelRowSize = width * 3 * byteSize;
var fullRowSize = pixelRowSize + 8;
// line offset table
var ofs = kHeaderSize + kScanlineTableSize;
for (y in 0...height) {
out.writeByte(ofs & 0xFF);
out.writeByte((ofs >> 8) & 0xFF);
out.writeByte((ofs >> 16) & 0xFF);
out.writeByte((ofs >> 24) & 0xFF);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
out.writeByte(0);
ofs += fullRowSize;
}
// scanline data
var stride = channels * byteSize;
var pos = 0;
function writeLine16(bytePos:Int) {
for (x in 0...width) {
out.writeByte(src.get(bytePos ));
out.writeByte(src.get(bytePos + 1));
bytePos += stride;
}
}
function writeLine32(bytePos:Int) {
for (x in 0...width) {
out.writeByte(src.get(bytePos ));
out.writeByte(src.get(bytePos + 1));
out.writeByte(src.get(bytePos + 2));
out.writeByte(src.get(bytePos + 3));
bytePos += stride;
}
}
var writeLine = bits == 16 ? writeLine16 : writeLine32;
function writeBGR(off:Int) {
writeLine(pos + byteSize * 2);
writeLine(pos + byteSize);
writeLine(pos );
}
function writeSingle(off:Int) {
writeLine(pos + off * byteSize);
writeLine(pos + off * byteSize);
writeLine(pos + off * byteSize);
}
var writeData = type == 1 ? writeBGR : writeSingle;
for (y in 0...height) {
// coordinate
out.writeByte(y & 0xFF);
out.writeByte((y >> 8) & 0xFF);
out.writeByte((y >> 16) & 0xFF);
out.writeByte((y >> 24) & 0xFF);
// data size
out.writeByte(pixelRowSize & 0xFF);
out.writeByte((pixelRowSize >> 8) & 0xFF);
out.writeByte((pixelRowSize >> 16) & 0xFF);
out.writeByte((pixelRowSize >> 24) & 0xFF);
// data
writeData(off);
pos += width * stride;
}
}
}