import Texture from '../Texture'; import Texture2D from '../Texture2D'; var toChar = String.fromCharCode; var MINELEN = 8; var MAXELEN = 0x7fff; function rgbe2float(rgbe, buffer, offset, exposure) { if (rgbe[3] > 0) { var f = Math.pow(2.0, rgbe[3] - 128 - 8 + exposure); buffer[offset + 0] = rgbe[0] * f; buffer[offset + 1] = rgbe[1] * f; buffer[offset + 2] = rgbe[2] * f; } else { buffer[offset + 0] = 0; buffer[offset + 1] = 0; buffer[offset + 2] = 0; } buffer[offset + 3] = 1.0; return buffer; } function uint82string(array, offset, size) { var str = ''; for (var i = offset; i < size; i++) { str += toChar(array[i]); } return str; } function copyrgbe(s, t) { t[0] = s[0]; t[1] = s[1]; t[2] = s[2]; t[3] = s[3]; } // TODO : check function oldReadColors(scan, buffer, offset, xmax) { var rshift = 0, x = 0, len = xmax; while (len > 0) { scan[x][0] = buffer[offset++]; scan[x][1] = buffer[offset++]; scan[x][2] = buffer[offset++]; scan[x][3] = buffer[offset++]; if (scan[x][0] === 1 && scan[x][1] === 1 && scan[x][2] === 1) { // exp is count of repeated pixels for (var i = (scan[x][3] << rshift) >>> 0; i > 0; i--) { copyrgbe(scan[x-1], scan[x]); x++; len--; } rshift += 8; } else { x++; len--; rshift = 0; } } return offset; } function readColors(scan, buffer, offset, xmax) { if ((xmax < MINELEN) | (xmax > MAXELEN)) { return oldReadColors(scan, buffer, offset, xmax); } var i = buffer[offset++]; if (i != 2) { return oldReadColors(scan, buffer, offset - 1, xmax); } scan[0][1] = buffer[offset++]; scan[0][2] = buffer[offset++]; i = buffer[offset++]; if ((((scan[0][2] << 8) >>> 0) | i) >>> 0 !== xmax) { return null; } for (var i = 0; i < 4; i++) { for (var x = 0; x < xmax;) { var code = buffer[offset++]; if (code > 128) { code = (code & 127) >>> 0; var val = buffer[offset++]; while (code--) { scan[x++][i] = val; } } else { while (code--) { scan[x++][i] = buffer[offset++]; } } } } return offset; } var ret = { // http://www.graphics.cornell.edu/~bjw/rgbe.html // Blender source // http://radsite.lbl.gov/radiance/refer/Notes/picture_format.html parseRGBE: function(arrayBuffer, texture, exposure) { if (exposure == null) { exposure = 0; } var data = new Uint8Array(arrayBuffer); var size = data.length; if (uint82string(data, 0, 2) !== '#?') { return; } // find empty line, next line is resolution info for (var i = 2; i < size; i++) { if (toChar(data[i]) === '\n' && toChar(data[i+1]) === '\n') { break; } } if (i >= size) { // not found return; } // find resolution info line i += 2; var str = ''; for (; i < size; i++) { var _char = toChar(data[i]); if (_char === '\n') { break; } str += _char; } // -Y M +X N var tmp = str.split(' '); var height = parseInt(tmp[1]); var width = parseInt(tmp[3]); if (!width || !height) { return; } // read and decode actual data var offset = i+1; var scanline = []; // memzero for (var x = 0; x < width; x++) { scanline[x] = []; for (var j = 0; j < 4; j++) { scanline[x][j] = 0; } } var pixels = new Float32Array(width * height * 4); var offset2 = 0; for (var y = 0; y < height; y++) { var offset = readColors(scanline, data, offset, width); if (!offset) { return null; } for (var x = 0; x < width; x++) { rgbe2float(scanline[x], pixels, offset2, exposure); offset2 += 4; } } if (!texture) { texture = new Texture2D(); } texture.width = width; texture.height = height; texture.pixels = pixels; // HALF_FLOAT can't use Float32Array texture.type = Texture.FLOAT; return texture; }, parseRGBEFromPNG: function(png) { } }; export default ret;