rext-image-editor
Version:
REXT is a client side image editor that uses GPU.
1,033 lines (973 loc) • 103 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["RextEditor"] = factory();
else
root["RextEditor"] = factory();
})(this, function() {
return /******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/raw-loader/dist/cjs.js!./src/shaders/fragment_shader.frag":
/*!********************************************************************************!*\
!*** ./node_modules/raw-loader/dist/cjs.js!./src/shaders/fragment_shader.frag ***!
\********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("/** * David Iglesias. All rights reserved */\nprecision mediump float;\nuniform sampler2D u_image;\nuniform vec2 u_textureSize;\nuniform float u_kernel[25];\nuniform float u_kernelWeight;\nuniform sampler2D u_lut;\nuniform float u_saturation;\nuniform float u_brightness;\nuniform float u_exposure;\nuniform float u_contrast;\nuniform float u_dehaze;\nuniform float u_atmosferic_light;\nuniform float u_masking;\nuniform vec3 u_temptint[3]; // RGB temptint, RGB lightFill, RGB darkFill\nuniform float u_bAndW;\nuniform float u_hdr;\nvarying vec2 v_texCoord;\nvoid main() {\n \n\tvec2 pixel_size = vec2(1.0, 1.0) / u_textureSize;\n \n\tvec3 center = texture2D(u_image, v_texCoord).rgb;\n\n /* 5x5 kernel filter */\n vec4 colorSum = texture2D(u_image, v_texCoord + pixel_size * vec2(-2, -2)) * u_kernel[0]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-1, -2)) * u_kernel[1]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(0, -2)) * u_kernel[2]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(1, -2)) * u_kernel[3]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(2, -2)) * u_kernel[4]\n\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-2, -1)) * u_kernel[5]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-1, -1)) * u_kernel[6]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(0, -1)) * u_kernel[7]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(1, -1)) * u_kernel[8]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(2, -1)) * u_kernel[9]\n\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-2, 0)) * u_kernel[10]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-1, 0)) * u_kernel[11]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(0, 0)) * u_kernel[12]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(1, 0)) * u_kernel[13]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(2, 0)) * u_kernel[14]\n\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-2, 1)) * u_kernel[15]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-1, 1)) * u_kernel[16]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(0, 1)) * u_kernel[17]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(1, 1)) * u_kernel[18]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(2, 1)) * u_kernel[19]\n\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-2, 2)) * u_kernel[20]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(-1, 2)) * u_kernel[21]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(0, 2)) * u_kernel[22]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(1, 2)) * u_kernel[23]\n\t\t + texture2D(u_image, v_texCoord + pixel_size * vec2(2, 2)) * u_kernel[24];\n\n\t/* Kernel filter mask */\n vec3 rgb_pix = mix(center, (colorSum.rgb / u_kernelWeight), u_masking);\n\t\n\t/**\n\t * RGB to saturation/value conversion, in order to keep hue constant \n\t * sv_pixel = (saturation, value)\n\t */\n float _max = max(rgb_pix.r, max(rgb_pix.g, rgb_pix.b));\n float _min = min(rgb_pix.r, min(rgb_pix.g, rgb_pix.b));\n vec2 sv_pixel = vec2(1.0 - _min / _max, _max);\n\n sv_pixel.y = clamp(texture2D(u_lut, vec2(sv_pixel.y, 0.0)).a, 0.0, 1.0);\n\n\t/* Add saturation */\n if (u_saturation != 0.0) {\n sv_pixel.x *= (1.0 + u_saturation);\n }\n\n sv_pixel.x = clamp(sv_pixel.x, 0.0, 1.0);\n\n\t/* Brightness */\n if (u_brightness != 0.0) {\n sv_pixel.y = pow(sv_pixel.y, 1.0 - u_brightness * 0.6);\n }\n\n\t/* HDR 'like' filter */\n if (u_hdr != 0.0) {\n sv_pixel.y = mix(sv_pixel.y, clamp(1.0 - pow(1.0 - pow(sv_pixel.y, 0.3), 0.42), 0.0, 1.0), u_hdr);\n }\n\n sv_pixel = clamp(sv_pixel, 0.0, 1.0);\n\t/* Return to RGB */\n if (sv_pixel.x > 0.0) {\n float k = -sv_pixel.x / (1.0 - _min / _max);\n rgb_pix = (_max - rgb_pix) * k + _max;\n rgb_pix *= sv_pixel.y / _max;\n } else {\n rgb_pix.r = rgb_pix.g = rgb_pix.b = sv_pixel.y;\n }\n\n\t/* Dehaze */\n if (u_dehaze != 0.0) {\n float t = 1.0 / 25.0;\n vec4 center = texture2D(u_image, v_texCoord);\n vec2 pixel_size = vec2(1.0, 1.0) / u_textureSize;\n float dark = 1.0;\n const int radius = 1;\n for (int ii = -radius; ii <= radius; ii++) {\n for (int jj = -radius; jj <= radius; jj++) {\n vec4 pix = texture2D(u_image, v_texCoord + pixel_size * vec2(ii, jj));\n float _min = min(pix.r, min(pix.g, pix.b));\n if (dark > _min) {\n dark = _min;\n }\n }\n }\n float darkPix = min(center.r, min(center.g, center.b));\n float diff = abs(darkPix - dark);\n float mask = pow(diff, 3.0);\n dark = mix(darkPix, dark, mask);\n float mm = max(1.0 - dark, 0.2);\n rgb_pix = mix(rgb_pix, ((rgb_pix - u_atmosferic_light) / mm + u_atmosferic_light), u_dehaze);\n }\n\n\t/* Exposure */\n rgb_pix += u_exposure;\n rgb_pix = clamp(rgb_pix, 0.0, 1.0);\n\n\t/* Contrast */\n float contrast = u_contrast + 1.0;\n rgb_pix = contrast * (rgb_pix - 0.5) + 0.5;\n\t\n\t/* Apply tint filter */\n rgb_pix *= u_temptint[0];\n float mono = dot(rgb_pix, vec3(0.2126, 0.7152, 0.0722));\n rgb_pix += mix(u_temptint[2], u_temptint[1], mono);\n\n\t/* Black&White filter */\n if (u_bAndW != 0.0) {\n rgb_pix = mix(rgb_pix, vec3(mono, mono, mono), u_bAndW);\n }\n\n gl_FragColor = vec4(rgb_pix, 1.0);\n\n}\n");
/***/ }),
/***/ "./node_modules/raw-loader/dist/cjs.js!./src/shaders/vertex_shader.vert":
/*!******************************************************************************!*\
!*** ./node_modules/raw-loader/dist/cjs.js!./src/shaders/vertex_shader.vert ***!
\******************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("attribute vec2 a_position;\nattribute vec2 a_texCoord;\nuniform vec2 u_resolution;\nvarying vec2 v_texCoord;\nuniform vec2 u_rotation;\nuniform vec2 u_rotation_center;\nuniform vec2 u_scale;\nuniform vec2 u_translate; \n\nvoid main() {\n\n vec2 scaled = a_position * vec2(u_scale);\n vec2 pos_r_t = scaled - u_rotation_center;\n vec2 pos_rotated = vec2(\n pos_r_t.x * u_rotation.y + pos_r_t.y * u_rotation.x,\n pos_r_t.y * u_rotation.y - pos_r_t.x * u_rotation.x);\n \n vec2 dist = (pos_rotated + u_rotation_center) / u_resolution;\n\n vec2 pos = vec2((dist + u_translate) * 2.0 - 1.0) * vec2(1, -1);\n gl_Position = vec4(pos, 0, 1);\n v_texCoord = a_texCoord;\n}\n");
/***/ }),
/***/ "./src/editor.ts":
/*!***********************!*\
!*** ./src/editor.ts ***!
\***********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "RextEditor": () => (/* binding */ RextEditor)
/* harmony export */ });
/* harmony import */ var _lib_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lib/color */ "./src/lib/color.ts");
/* harmony import */ var _lib_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./lib/constants */ "./src/lib/constants.ts");
/* harmony import */ var _shaders_index__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/index */ "./src/shaders/index.ts");
/* harmony import */ var _log_LogFacade__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./log/LogFacade */ "./src/log/LogFacade.ts");
/* harmony import */ var _lib_image_transforms__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lib/image-transforms */ "./src/lib/image-transforms.ts");
/* harmony import */ var _shaders__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./shaders */ "./src/shaders.ts");
/* harmony import */ var _lib_context__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./lib/context */ "./src/lib/context.ts");
const clone = (obj) => JSON.parse(JSON.stringify(obj));
const CANVAS_OPTIONS = {
alpha: false,
antialias: false,
};
/* BEGIN WEBGL PART */
class RextEditor {
constructor(canvas) {
this.params = clone(_lib_constants__WEBPACK_IMPORTED_MODULE_1__.defaultParams);
this.program = null;
this.realImage = null;
this.currentImage = null;
this.context = null;
this.config = _lib_constants__WEBPACK_IMPORTED_MODULE_1__.defaultConfig;
this.onParamsChangeCallbacks = [];
this.WIDTH = 0;
this.HEIGHT = 0;
this.log = new _log_LogFacade__WEBPACK_IMPORTED_MODULE_3__.LogFacade();
this.uniforms = {
kernel: [
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
],
temptint: [1, 1, 1]
};
this.LIGHT_MATCH = new Array(256).fill(0).map((v, i) => i);
if (canvas) {
this.setCanvas(canvas);
}
}
setCanvas(canvas) {
this.config.width = canvas.width;
this.config.height = canvas.height;
this.canvas = canvas;
this.gl = canvas.getContext("webgl", CANVAS_OPTIONS) || canvas.getContext("experimental-webgl", CANVAS_OPTIONS);
}
runCallback(callbackName) {
switch (callbackName) {
case "generateLightning":
this.generateLightning();
case "kernel_update":
this.uniforms.kernel = (0,_lib_image_transforms__WEBPACK_IMPORTED_MODULE_4__.computeKernel)(this.params);
case "updateTemptint":
this.updateTemptint();
return;
}
this.log.warn(`No callback ${callbackName} exists`);
}
onParamsChange(callback) {
this.onParamsChangeCallbacks.push(callback);
}
updateParams(params) {
/* Calculate difference */
const updateKeys = Object.keys(this.params).filter(paramKey => {
return this.params[paramKey] !== params[paramKey];
});
updateKeys.forEach(paramKey => {
this._updateParam(paramKey, params[paramKey]);
});
const updates = this.getCallbacks(updateKeys);
/* Update with callbacks */
updates.forEach(callbackName => {
this.runCallback(callbackName);
});
this.update();
this.onParamsChangeCallbacks.forEach(callback => {
if (callback) {
try {
callback(this.params);
}
catch (err) {
// Ignored
}
}
});
}
getCallbacks(updatedParams) {
const callbacks = new Set(updatedParams.filter(key => _lib_constants__WEBPACK_IMPORTED_MODULE_1__.paramsCallbacks[key] !== undefined && _lib_constants__WEBPACK_IMPORTED_MODULE_1__.paramsCallbacks[key] !== null)
.map(key => _lib_constants__WEBPACK_IMPORTED_MODULE_1__.paramsCallbacks[key])
.reduce((acc, v) => acc.concat(v), []));
return Array.from(callbacks);
}
// Do not call this method from any other function than updateParams
_updateParam(param, value) {
const keys = Object.keys(this.params);
if (keys.includes(param)) {
// @ts-ignore
this.params[param] = value;
}
else {
this.log.error(`Param ${param} does not exists`);
}
}
autoZoom() {
const widthX = this.config.width / this.WIDTH;
const heightX = this.config.height / this.HEIGHT;
const maxX = Math.max(widthX, heightX);
this.setZoom(maxX);
}
setZoom(zoom) {
this.updateParams({ ...this.params, zoom: zoom });
this.update();
}
getWidth() {
return this.WIDTH;
}
getHeight() {
return this.HEIGHT;
}
setWidth(width) {
this.WIDTH = width;
}
setHeight(height) {
this.HEIGHT = height;
}
getCanvas() {
return this.gl.canvas;
}
// FIXME: To Math class
get2dRotation() {
return [
Math.sin(this.params.rotation),
Math.cos(this.params.rotation)
];
}
get2dRotationCenter() {
const x = (this.params.rotation_center.x + 1) * this.WIDTH / 2.0;
const y = (this.params.rotation_center.y + 1) * this.HEIGHT / 2.0;
return [x, y];
}
loadImage(url) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
if (this.currentImage == null) {
this.log.warn('Load Image called without image.');
return;
}
this.WIDTH = image.width;
this.HEIGHT = image.height;
this.fitCanvas(image.width, image.height);
this.create(this.currentImage);
resolve();
};
image.onerror = (err) => {
this.log.error("Error while loading the image.");
reject(err);
};
this.currentImage = image;
image.src = url;
this.realImage = image;
});
}
async load(url, config) {
this.log.log("Version 1.4.0");
// Save real image as a copy
if (config !== undefined) {
this.config = config;
}
await this.loadImage(url);
return this;
}
setLog(log) {
this.log = log;
}
// Temp and Tint
updateTemptint() {
this.uniforms.temptint = (0,_lib_image_transforms__WEBPACK_IMPORTED_MODULE_4__.tempTint)(this.params);
}
/**
* Lightning generation:
* Map brightness values depending on Brightness, Contrast... etc
*/
generateLightning() {
this.LIGHT_MATCH = (0,_lib_image_transforms__WEBPACK_IMPORTED_MODULE_4__.lightning)(this.params);
}
blob(type, quality) {
return new Promise((resolve, reject) => {
if (this.realImage === null) {
this.log.warn('Called to blob without loaded image');
return reject();
}
this.create(this.realImage);
this.getCanvas().toBlob((blob) => {
if (blob === null) {
this.log.error('Unable to generate the blob file');
return reject();
}
resolve(blob);
}, type || "image/jpeg", quality || 1);
});
}
/**
* create
* Prepare the environment to edit the image
* image: Image element to edit (Image object)
* context: webgl context. Default: __window.gl
* SET_FULL_RES: no resize the image to edit. Default: false (resize the image)
*/
create(image, preventRenderImage) {
// Load GSLS programs
try {
const VERTEX_SHADER_CODE = (0,_shaders__WEBPACK_IMPORTED_MODULE_5__.createShader)(this.gl, this.gl.VERTEX_SHADER, _shaders_index__WEBPACK_IMPORTED_MODULE_2__.VERTEX_SHADER);
const FRAGMENT_SHADER_CODE = (0,_shaders__WEBPACK_IMPORTED_MODULE_5__.createShader)(this.gl, this.gl.FRAGMENT_SHADER, _shaders_index__WEBPACK_IMPORTED_MODULE_2__.FRAGMENT_SHADER);
this.program = (0,_shaders__WEBPACK_IMPORTED_MODULE_5__.createProgram)(this.gl, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE);
}
catch (err) {
return this.log.error(err);
}
this.context = new _lib_context__WEBPACK_IMPORTED_MODULE_6__.Context(this.gl, this.program);
this.log.log("[IMAGE] width = " + this.WIDTH + ", height = " + this.HEIGHT);
this.log.log("[CANVAS] width = " + this.canvas.width + ", height = " + this.canvas.height);
this.setRectangle(this.context.createBuffer("ARRAY_BUFFER"), 0.0, 0.0, this.WIDTH, this.HEIGHT);
this.setRectangle(this.context.createBuffer("TEXCOORD_BUFFER"), 0, 0, 1.0, 1.0);
this.gl.activeTexture(this.gl.TEXTURE0);
// Upload the image into the texture.
(0,_shaders__WEBPACK_IMPORTED_MODULE_5__.createTexture)(this.gl);
try {
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image);
}
catch (err) {
return this.log.error(err);
}
// Upload the LUT (contrast, brightness...)
this.gl.activeTexture(this.gl.TEXTURE1);
(0,_shaders__WEBPACK_IMPORTED_MODULE_5__.createTexture)(this.gl);
this.gl.viewport(0, 0, this.WIDTH, this.HEIGHT);
this.gl.clearColor(0, 0, 0, 0);
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
if (!preventRenderImage) {
this.update();
}
}
fitCanvas(width, height) {
this.canvas.width = width;
this.canvas.height = height;
}
update() {
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.ALPHA, 256, 1, 0, this.gl.ALPHA, this.gl.UNSIGNED_BYTE, new Uint8Array(this.LIGHT_MATCH));
this.gl.useProgram(this.program);
this.gl.enableVertexAttribArray(this.context.getAttribute("a_position"));
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.context.getBuffer("ARRAY_BUFFER"));
this.gl.vertexAttribPointer(this.context.getAttribute("a_position"), 2, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(this.context.getAttribute("a_texCoord"));
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.context.getBuffer("TEXCOORD_BUFFER"));
this.gl.vertexAttribPointer(this.context.getAttribute("a_texCoord"), 2, this.gl.FLOAT, false, 0, 0);
this.gl.uniform2f(this.context.getUniform("u_resolution"), this.WIDTH, this.HEIGHT);
this.gl.uniform2f(this.context.getUniform("u_textureSize"), this.WIDTH, this.HEIGHT);
this.gl.uniform1f(this.context.getUniform("u_brightness"), this.params.brightness);
this.gl.uniform1f(this.context.getUniform("u_contrast"), this.params.contrast);
this.gl.uniform1f(this.context.getUniform("u_exposure"), this.params.exposure);
this.gl.uniform1f(this.context.getUniform("u_contrast"), this.params.contrast);
this.gl.uniform1f(this.context.getUniform("u_saturation"), this.params.saturation);
this.gl.uniform1f(this.context.getUniform("u_masking"), this.params.masking);
this.gl.uniform1f(this.context.getUniform("u_dehaze"), this.params.dehaze);
this.gl.uniform1f(this.context.getUniform("u_atmosferic_light"), this.params.atmosferic_light);
this.gl.uniform3fv(this.context.getUniform("u_temptint[0]"), this.uniforms.temptint
.concat((0,_lib_color__WEBPACK_IMPORTED_MODULE_0__.asArray)((0,_lib_color__WEBPACK_IMPORTED_MODULE_0__.hsv2rgb)({ x: this.params.lightColor * 360, y: this.params.lightSat, z: this.params.lightFill })))
.concat((0,_lib_color__WEBPACK_IMPORTED_MODULE_0__.asArray)((0,_lib_color__WEBPACK_IMPORTED_MODULE_0__.hsv2rgb)({ x: this.params.darkColor * 360, y: this.params.darkSat, z: this.params.darkFill })))); // vec3 x3
this.gl.uniform1f(this.context.getUniform("u_bAndW"), this.params.bAndW);
this.gl.uniform1f(this.context.getUniform("u_hdr"), this.params.hdr);
this.gl.uniform2fv(this.context.getUniform("u_rotation"), this.get2dRotation());
this.gl.uniform2fv(this.context.getUniform("u_rotation_center"), this.get2dRotationCenter());
this.gl.uniform2f(this.context.getUniform("u_scale"), this.params.scale.x, this.params.scale.y);
this.gl.uniform2f(this.context.getUniform("u_translate"), this.params.translate.x, this.params.translate.y);
// Show image
this.gl.uniform1i(this.context.getUniform("u_lut"), 1); // TEXTURE 1
// set the kernel and it's weight
this.gl.uniform1fv(this.context.getUniform("u_kernel[0]"), this.uniforms.kernel);
this.gl.uniform1f(this.context.getUniform("u_kernelWeight"), (0,_lib_image_transforms__WEBPACK_IMPORTED_MODULE_4__.sumArray)(this.uniforms.kernel));
/* Adjust canvas size: Cropping */
this.applyCrop();
this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
}
applyCrop() {
const x2 = this.WIDTH * this.params.size.x;
const y2 = this.HEIGHT * this.params.size.y;
const cw = (this.params.zoom * x2);
const ch = (this.params.zoom * y2);
this.getCanvas().style.width = cw + "px";
this.getCanvas().style.height = ch + "px";
this.getCanvas().width = x2;
this.getCanvas().height = y2;
}
setRectangle(buffer, x, y, width, height) {
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
var x1 = x;
var x2 = x + width;
var y1 = y;
var y2 = y + height;
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([
x1, y1,
x2, y1,
x1, y2,
x1, y2,
x2, y1,
x2, y2,
]), this.gl.STATIC_DRAW);
}
}
/***/ }),
/***/ "./src/lib/color.ts":
/*!**************************!*\
!*** ./src/lib/color.ts ***!
\**************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "getLuma": () => (/* binding */ getLuma),
/* harmony export */ "hsv2rgb": () => (/* binding */ hsv2rgb),
/* harmony export */ "asArray": () => (/* binding */ asArray)
/* harmony export */ });
/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math */ "./src/lib/math.ts");
/**
* Color space functions
*/
const getLuma = (rgb_pix) => {
return 0.2126 * rgb_pix.x + 0.7152 * rgb_pix.y + 0.0722 * rgb_pix.z;
};
const hsv2rgb = (pixel_hsv) => {
let a, d, c;
let r, g, b;
a = pixel_hsv.z * pixel_hsv.y;
d = a * (1.0 - Math.abs((pixel_hsv.x / 60.0) % 2.0 - 1.0));
c = pixel_hsv.z - a;
if (pixel_hsv.x < 180.0) {
if (pixel_hsv.x < 60.0) {
r = pixel_hsv.z;
g = d + c;
b = c;
}
else if (pixel_hsv.x < 120.0) {
r = d + c;
g = pixel_hsv.z;
b = c;
}
else {
r = c;
g = pixel_hsv.z;
b = d + c;
}
}
else {
if (pixel_hsv.x < 240.0) {
r = c;
g = d + c;
b = pixel_hsv.z;
}
else if (pixel_hsv.x < 300.0) {
r = d + c;
g = c;
b = a + c;
}
else {
r = a + c;
g = c;
b = d + c;
}
}
r = (0,_math__WEBPACK_IMPORTED_MODULE_0__.clamp)(r, 0.0, 1.0);
g = (0,_math__WEBPACK_IMPORTED_MODULE_0__.clamp)(g, 0.0, 1.0);
b = (0,_math__WEBPACK_IMPORTED_MODULE_0__.clamp)(b, 0.0, 1.0);
return { x: r, y: g, z: b };
};
const asArray = (vec) => [vec.x, vec.y, vec.z];
/***/ }),
/***/ "./src/lib/constants.ts":
/*!******************************!*\
!*** ./src/lib/constants.ts ***!
\******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "defaultConfig": () => (/* binding */ defaultConfig),
/* harmony export */ "defaultParams": () => (/* binding */ defaultParams),
/* harmony export */ "paramsCallbacks": () => (/* binding */ paramsCallbacks),
/* harmony export */ "TEMP_DATA": () => (/* binding */ TEMP_DATA)
/* harmony export */ });
const defaultConfig = {
resolutionLimit: -1,
editionResolutionLimit: -1,
};
const defaultParams = {
hdr: 0,
exposure: 0,
temperature: 0,
tint: 0,
brightness: 0,
saturation: 0,
contrast: 0,
sharpen: 0,
masking: 0,
sharpen_radius: 0,
radiance: 0,
highlights: 0,
shadows: 0,
whites: 0,
blacks: 0,
dehaze: 0,
bAndW: 0,
atmosferic_light: 0,
lightFill: 0,
lightColor: 0,
lightSat: 1,
darkFill: 0,
darkColor: 0,
darkSat: 1,
rotation: 0,
rotation_center: {
x: 0,
y: 0,
},
scale: {
x: 1,
y: 1,
},
translate: {
x: 0,
y: 0,
},
size: {
x: 1,
y: 1,
},
zoom: 1,
};
/**
* Callbacks needed to be recalculated when changing parameters
*/
const paramsCallbacks = {
contrast: ["generateLightning"],
whites: ["generateLightning"],
highlights: ["generateLightning"],
shadows: ["generateLightning"],
blacks: ["generateLightning"],
radiance: ["generateLightning", "kernel_update"],
hdr: ["kernel_update"],
temperature: ["updateTemptint"],
tint: ["updateTemptint"],
sharpen: ["kernel_update"],
sharpen_radius: ["kernel_update"],
};
/**
* Temperature map
*/
const TEMP_DATA = [
[0.6167426069865002, 0.017657981710823077],
[0.5838624982041293, 0.06447754787874993],
[0.5666570157784903, 0.1010769359975838],
[0.5600215017846518, 0.13012054359808795],
[0.5603460901328465, 0.15370282338343416],
[0.5651414015638195, 0.1734071109259789],
[0.5727157905223393, 0.19040417876076665],
[0.5819305919306469, 0.20554787970182647],
[0.5920253173976543, 0.219454396860673],
[0.6024964973113273, 0.23256361077001078],
[0.613014923688415, 0.2451851574423344],
[0.6233694681448863, 0.2575325541865392],
[0.633428991849502, 0.2697484189519574],
[0.6431164873163056, 0.2819231700046263],
[0.6523914777767198, 0.29410898225476145],
[0.6612380004437802, 0.30633028466830314],
[0.6696563786680246, 0.31859171532935343],
[0.6776575761390952, 0.330884185957384],
[0.6852593188363603, 0.34318952105568623],
[0.6924834326806721, 0.3554840067292358],
[0.6993540206164168, 0.36774109382812364],
[0.705896221219359, 0.37993343721079975],
[0.712135371070854, 0.3920344089104195],
[0.7180964477199883, 0.4040191918024166],
[0.7238037074478182, 0.41586553788423575],
[0.7292804578150028, 0.42755425869079605],
[0.7345489228275083, 0.43906950280216533],
[0.7396301709912545, 0.4503988656030025],
[0.7445440852278651, 0.4615333686006381],
[0.7493093597375261, 0.47246733915721345],
[0.7539435132044948, 0.4831982160881075],
[0.7584629107855697, 0.4937263019887011],
[0.7628827894765442, 0.5040544792219176],
[0.7672172829757861, 0.5141879031216875],
[0.7756812566990368, 0.5339005596070674],
[0.7756812566990368, 0.5339005596070674],
[0.7798336535847834, 0.5434985836882681],
[0.7839465092903851, 0.552938802301879],
[0.7880286368234596, 0.5622329533372938],
[0.7920877696863722, 0.5713931712543325],
[0.796130534601134, 0.5804317041849897],
[0.8001624136045166, 0.5893606423074715],
[0.8041876951180534, 0.5981916567442426],
[0.8082094136732589, 0.6069357478075997],
[0.8122292780585781, 0.6156030011340633],
[0.8162475877574743, 0.624202350096731],
[0.8202631376804659, 0.6327413428542148],
[0.8242731113661302, 0.6412259124772712],
[0.8282729630469863, 0.6496601487868902],
[0.8322562892583072, 0.6580460708395705],
[0.8362146910181553, 0.6663833994084263],
[0.8401376280395388, 0.6746693293369075],
[0.8440122669563406, 0.6828983022904387],
[0.8478233261635671, 0.691061781205187],
[0.8515529205921868, 0.6991480286361483],
[0.8578515274860328, 0.7143328511178657],
[0.8630349166004683, 0.7236145588845],
[0.8630349166004683, 0.7236145588845],
[0.8678866519883774, 0.7326305266929798],
[0.8724265417351438, 0.7413920824039555],
[0.8766746938112879, 0.7499106260961086],
[0.8806514255414362, 0.7581975699581189],
[0.8843771730729832, 0.7662642858505886],
[0.8878724008449614, 0.7741220599147951],
[0.8911575110568668, 0.7817820536219475],
[0.8942527531374216, 0.7892552706795768],
[0.8971781332133792, 0.7965525292390034],
[0.9025975721615955, 0.8106613818669473],
[0.9051296119968262, 0.8174934982533621],
[0.9051296119968262, 0.8174934982533621],
[0.9075675706910422, 0.8241906743465228],
[0.9099288798932852, 0.8307625342003426],
[0.912230184763394, 0.8372184337382709],
[0.914487253441016, 0.8435674571884941],
[0.9167148865142485, 0.8498184155292972],
[0.9189268264883301, 0.8559798466723794],
[0.9211356672547586, 0.862060017138353],
[0.9233527635598611, 0.8680669250033681],
[0.9278504028585166, 0.8798916280267886],
[0.9301466448383797, 0.8857241176152066],
[0.9324823592671754, 0.8915127453709542],
[0.9348613471976668, 0.8972642431099969],
[0.9348613471976668, 0.8972642431099969],
[0.9372856273504615, 0.9029851088748369],
[0.9397553455825536, 0.9086816143048344],
[0.9422686843563701, 0.9143598121965675],
[0.9448217722084058, 0.9200255441824128],
[0.947408593218177, 0.925684448465339],
[0.9500208964767429, 0.931341967556689],
[0.9552772279767501, 0.9426736878435626],
[0.9578927646784257, 0.9483578644262163],
[0.9604766194871308, 0.954060621455171],
[0.9630080085847714, 0.9597865363484674],
[0.965463369977889, 0.9655400352277332],
[0.965463369977889, 0.9655400352277332],
[0.9678162729662736, 0.9713253997462401],
[0.9700373276119754, 0.9771467737131783],
[0.9720940942080452, 0.9830081695063213],
[0.9739509927471266, 0.9889134742677088],
[0.97556921239073, 0.9948664558790756],
[0.9782396416593983, 1]
];
/***/ }),
/***/ "./src/lib/context.ts":
/*!****************************!*\
!*** ./src/lib/context.ts ***!
\****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "Context": () => (/* binding */ Context)
/* harmony export */ });
class Context {
constructor(gl, program) {
this.gl = gl;
this.program = program;
this.pointers = {};
this.atributes = {};
this.buffers = {};
}
;
getUniform(uniform) {
if (!this.pointers[uniform]) {
this.pointers[uniform] = this.gl.getUniformLocation(this.program, uniform);
}
return this.pointers[uniform];
}
getAttribute(atribute) {
if (!this.atributes[atribute]) {
this.atributes[atribute] = this.gl.getAttribLocation(this.program, atribute);
}
return this.atributes[atribute];
}
createBuffer(bufferName) {
this.buffers[bufferName] = this.gl.createBuffer();
return this.buffers[bufferName];
}
getBuffer(bufferName) {
return this.buffers[bufferName];
}
}
/***/ }),
/***/ "./src/lib/image-transforms.ts":
/*!*************************************!*\
!*** ./src/lib/image-transforms.ts ***!
\*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "computeKernel": () => (/* binding */ computeKernel),
/* harmony export */ "tempTint": () => (/* binding */ tempTint),
/* harmony export */ "lightning": () => (/* binding */ lightning),
/* harmony export */ "sumArray": () => (/* binding */ sumArray)
/* harmony export */ });
/* harmony import */ var _color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./color */ "./src/lib/color.ts");
/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./constants */ "./src/lib/constants.ts");
/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./math */ "./src/lib/math.ts");
/**
* Computes an 3x3 kernel for image processing
*/
const computeKernel = (params) => {
let sharpness = -params.sharpen;
let radius = params.sharpen_radius;
const radiance = params.radiance;
const hdr = params.hdr;
if (radiance != 0) {
sharpness -= 0.5 * radiance;
radius += 0.5 * radiance;
}
if (hdr != 0) {
sharpness -= 0.5 * hdr;
radius += 0.5 * hdr;
}
const A = sharpness * Math.exp(-Math.pow(1 / radius, 2));
const B = sharpness * Math.exp(-Math.pow(1.41 / radius, 2));
const C = sharpness * Math.exp(-Math.pow(2 / radius, 2));
const D = sharpness * Math.exp(-Math.pow(2.24 / radius, 2));
const E = sharpness * Math.exp(-Math.pow(2.83 / radius, 2));
let X = 1;
if (sharpness < 0) {
X += 4 * Math.abs(E) + 8 * Math.abs(D) + 4 * Math.abs(C) + 4 * Math.abs(B) + 4 * Math.abs(A);
}
return [E, D, C, D, E,
D, B, A, B, D,
C, A, X, A, C,
D, B, A, B, D,
E, D, C, D, E];
};
const tempTint = (params) => {
let T = params.temperature;
let tint = params.tint;
let R, G, B;
if (T < 0) {
R = 1;
const i = _constants__WEBPACK_IMPORTED_MODULE_1__.TEMP_DATA[Math.floor((T + 1) * 100)]; // Tab values, algorithm is hard
G = i[0];
B = i[1];
}
else {
R = 0.0438785 / (Math.pow(T + 0.150127, 1.23675)) + 0.543991;
G = 0.0305003 / (Math.pow(T + 0.163976, 1.23965)) + 0.69136;
B = 1;
}
if (tint == -1) { // HACK
tint = -0.99;
}
G += tint;
// Luma correction
var curr_luma = (0,_color__WEBPACK_IMPORTED_MODULE_0__.getLuma)({ x: R, y: G, z: B });
var mult_K = 1 / curr_luma;
return [R * mult_K, G * mult_K, B * mult_K];
};
const lightning = (params) => {
const func = (0,_math__WEBPACK_IMPORTED_MODULE_2__.getCuadraticFunction)(params.blacks, params.shadows + 0.33, params.highlights + 0.66, params.whites + 1, 0, 0.33, 0.66, 1);
let f_radiance = null;
if (params.radiance != 0) {
f_radiance = (0,_math__WEBPACK_IMPORTED_MODULE_2__.getCuadraticFunction)(0, 0.33 - params.radiance * 0.11, 0.66 + params.radiance * 0.11, 1, 0, 0.33, 0.66, 1);
}
const LIGHT_MATCH = [];
for (let i = 0; i <= 255; i++) {
let pixel_value = i / 255;
// Radiance part
if (params.radiance != 0) {
pixel_value = f_radiance(pixel_value);
}
pixel_value = func(pixel_value);
if (pixel_value > 1) {
pixel_value = 1;
}
if (pixel_value < 0) {
pixel_value = 0;
}
LIGHT_MATCH[i] = pixel_value * 255;
}
return LIGHT_MATCH;
};
/**
* kernelNormalization
* Compute the total weight of the kernel in order to normalize it
*/
const sumArray = (kernel) => kernel.reduce((a, b) => a + b);
/***/ }),
/***/ "./src/lib/math.ts":
/*!*************************!*\
!*** ./src/lib/math.ts ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "clamp": () => (/* binding */ clamp),
/* harmony export */ "resTreatment": () => (/* binding */ resTreatment),
/* harmony export */ "getCuadraticFunction": () => (/* binding */ getCuadraticFunction)
/* harmony export */ });
const clamp = (a, b, c) => {
return (a < b) ? b : (a > c) ? c : a;
};
const resTreatment = (arr) => arr.map(v => Math.round(v * 1000) / 1000);
const getCuadraticFunction = (a, b, c, d, aa = 0, bb = 0.33, cc = 0.66, dd = 1) => {
const aaS = Math.pow(aa, 2);
const bbS = Math.pow(bb, 2);
const ccS = Math.pow(cc, 2);
const ddS = Math.pow(dd, 2);
const aaT = aaS * aa;
const bbT = bbS * bb;
const ccT = ccS * cc;
const ddT = ddS * dd;
const res = resTreatment(solve4x4([aaT, bbT, ccT, ddT], [aaS, bbS, ccS, ddS], [aa, bb, cc, dd], [a, b, c, d]));
return function (x) {
let _r = res[3];
let xx = x;
_r += res[2] * xx;
xx *= x;
_r += res[1] * xx;
xx *= x;
_r += res[0] * xx;
return _r;
};
};
function solve4x4(w, x, y, s) {
let S, W, X, Y, Z;
let _S, _W, _X, _Y, _Z;
const Aa = y[2] - y[3];
const Ad = w[2] - w[3];
const Ab = x[2] - x[3];
const Ah = s[2] - s[3];
const Ac = x[2] * y[3] - y[2] * x[3];
const Af = w[2] * y[3] - y[2] * w[3];
const Ag = w[2] * x[3] - x[2] * w[3];
const Ai = s[2] * y[3] - y[2] * s[3];
const Aj = s[2] * x[3] - x[2] * s[3];
const Ak = w[2] * s[3] - s[2] * w[3];
const Al = x[2] * s[3] - s[2] * x[3];
const Am = y[2] * s[3] - s[2] * y[3];
W = x[1] * Aa - y[1] * Ab + Ac;
X = w[1] * Aa - y[1] * Ad + Af;
Y = w[1] * Ab - x[1] * Ad + Ag;
Z = w[1] * Ac - x[1] * Af + y[1] * Ag;
_S = w[0] * W - x[0] * X + y[0] * Y - Z;
S = x[1] * Aa - y[1] * Ab + Ac;
X = s[1] * Aa - y[1] * Ah + Ai;
Y = s[1] * Ab - x[1] * Ah + Aj;
Z = s[1] * Ac - x[1] * Ai + y[1] * Aj;
_W = s[0] * S - x[0] * X + y[0] * Y - Z;
W = s[1] * Aa - y[1] * Ah + Ai;
S = w[1] * Aa - y[1] * Ad + Af;
Y = w[1] * Ah - s[1] * Ad + Ak;
Z = w[1] * Ai - s[1] * Af + y[1] * Ak;
_X = w[0] * W - s[0] * S + y[0] * Y - Z;
W = x[1] * Ah - s[1] * Ab + Al;
X = w[1] * Ah - s[1] * Ad + Ak;
S = w[1] * Ab - x[1] * Ad + Ag;
Z = w[1] * Al - x[1] * Ak + s[1] * Ag;
_Y = w[0] * W - x[0] * X + s[0] * S - Z;
W = x[1] * Am - y[1] * Al + s[1] * Ac;
X = w[1] * Am - y[1] * Ak + s[1] * Af;
Y = w[1] * Al - x[1] * Ak + s[1] * Ag;
S = w[1] * Ac - x[1] * Af + y[1] * Ag;
_Z = w[0] * W - x[0] * X + y[0] * Y - s[0] * S;
return [_W / _S, _X / _S, _Y / _S, _Z / _S];
}
/***/ }),
/***/ "./src/log/LogFacade.ts":
/*!******************************!*\
!*** ./src/log/LogFacade.ts ***!
\******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "LogFacade": () => (/* binding */ LogFacade)
/* harmony export */ });
class LogFacade {
log(msg) {
console.log(msg);
}
warn(msg) {
console.warn(msg);
}
error(msg) {
console.error(msg);
}
}
/***/ }),
/***/ "./src/shaders.ts":
/*!************************!*\
!*** ./src/shaders.ts ***!
\************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "createShader": () => (/* binding */ createShader),
/* harmony export */ "createProgram": () => (/* binding */ createProgram),
/* harmony export */ "createTexture": () => (/* binding */ createTexture)
/* harmony export */ });
const createShader = (gl, type, source) => {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (success) {
return shader;
}
console.warn(gl.getError());
gl.deleteShader(shader);
throw new Error("Unable to create a WebGL shader.");
};
const createProgram = (gl, vertexShader, fragmentShader) => {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
const success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (success) {
return program;
}
console.warn(gl.getError());
gl.deleteProgram(program);
throw new Error("Unable to create a WebGL Program.");
};
const createTexture = (gl) => {
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
return texture;
};
/***/ }),
/***/ "./src/shaders/index.ts":
/*!******************************!*\
!*** ./src/shaders/index.ts ***!
\******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "FRAGMENT_SHADER": () => (/* reexport safe */ _raw_loader_fragment_shader_frag__WEBPACK_IMPORTED_MODULE_0__.default),
/* harmony export */ "VERTEX_SHADER": () => (/* reexport safe */ _raw_loader_vertex_shader_vert__WEBPACK_IMPORTED_MODULE_1__.default)
/* harmony export */ });
/* harmony import */ var _raw_loader_fragment_shader_frag__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !!raw-loader!./fragment_shader.frag */ "./node_modules/raw-loader/dist/cjs.js!./src/shaders/fragment_shader.frag");
/* harmony import */ var _raw_loader_vertex_shader_vert__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !!raw-loader!./vertex_shader.vert */ "./node_modules/raw-loader/dist/cjs.js!./src/shaders/vertex_shader.vert");
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(__webpack_module_cache__[moduleId]) {
/******/ return __webpack_module_cache__[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
/*!**********************!*\
!*** ./src/index.ts ***!
\**********************/
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "RextEditor": () => (/* reexport safe */ _editor__WEBPACK_IMPORTED_MODULE_0__.RextEditor)
/* harmony export */ });
/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./editor */ "./src/editor.ts");
})();
/******/ return __webpack_exports__;
/******/ })()
;
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9SZXh0RWRpdG9yL3dlYnBhY2svdW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbiIsIndlYnBhY2s6Ly9SZXh0RWRpdG9yLy4vc3JjL3NoYWRlcnMvZnJhZ21lbnRfc2hhZGVyLmZyYWciLCJ3ZWJwYWNrOi8vUmV4dEVkaXRvci8uL3NyYy9zaGFkZXJzL3ZlcnRleF9zaGFkZXIudmVydCIsIndlYnBhY2s6Ly9SZXh0RWRpdG9yLy4vc3JjL2VkaXRvci50cyIsIndlYnBhY2s6Ly9SZXh0RWRpdG9yLy4vc3JjL2xpYi9jb2xvci50cyIsIndlYnBhY2s6Ly9SZXh0RWRpdG9yLy4vc3JjL2xpYi9jb25zdGFudHMudHMiLCJ3ZWJwYWNrOi8vUmV4dEVkaXRvci8uL3NyYy9saWIvY29udGV4dC50cyIsIndlYnBhY2s6Ly9SZXh0RWRpdG9yLy4vc3JjL2xpYi9pbWFnZS10cmFuc2Zvcm1zLnRzIiwid2VicGFjazovL1JleHRFZGl0b3IvLi9zcmMvbGliL21hdGgudHMiLCJ3ZWJwYWNrOi8vUmV4dEVkaXRvci8uL3NyYy9sb2cvTG9nRmFjYWRlLnRzIiwid2VicGFjazovL1JleHRFZGl0b3IvLi9zcmMvc2hhZGVycy50cyIsIndlYnBhY2s6Ly9SZXh0RWRpdG9yLy4vc3JjL3NoYWRlcnMvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vUmV4dEVkaXRvci93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9SZXh0RWRpdG9yL3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly9SZXh0RWRpdG9yL3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vUmV4dEVkaXRvci93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL1JleHRFZGl0b3IvLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FB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