Commit 28b9d317 authored by Romain Courteaud's avatar Romain Courteaud

erp5_document_scanner: add glfx support

Use the GPU to speed up the image manipulation process.
parent 9e8adf0f
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
<script type="text/javascript" src="cropper.min.js"></script> <script type="text/javascript" src="cropper.min.js"></script>
<script type="text/javascript" src="domsugar.js"></script> <script type="text/javascript" src="domsugar.js"></script>
<script type="text/javascript" src="caman.full.min.js"></script> <script type="text/javascript" src="caman.full.min.js"></script>
<script type="text/javascript" src="glfx.js"></script>
<script type="text/javascript" src="gadget_document_scanner.js"></script> <script type="text/javascript" src="gadget_document_scanner.js"></script>
<title>Gadget Document Scanner</title> <title>Gadget Document Scanner</title>
</head> </head>
......
...@@ -242,7 +242,7 @@ ...@@ -242,7 +242,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>982.7390.34742.27767</string> </value> <value> <string>982.46775.50354.51694</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1582765422.37</float> <float>1585665387.68</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*jslint indent: 2, unparam: true, bitwise: true */ /*jslint indent: 2, unparam: true, bitwise: true */
/*global rJS, RSVP, window, document, navigator, Cropper, Promise, JSON, jIO, /*global rJS, RSVP, window, document, navigator, Cropper, Promise, JSON, jIO,
promiseEventListener, domsugar, createImageBitmap, FormData, Caman, promiseEventListener, domsugar, createImageBitmap, FormData, Caman,
FileReader, DataView, URL*/ FileReader, DataView, URL, fx*/
(function (rJS, RSVP, window, document, navigator, Cropper, Promise, JSON, jIO, (function (rJS, RSVP, window, document, navigator, Cropper, Promise, JSON, jIO,
promiseEventListener, domsugar, createImageBitmap, FormData, caman, promiseEventListener, domsugar, createImageBitmap, FormData, caman,
FileReader, DataView, URL) { FileReader, DataView, URL, fx) {
"use strict"; "use strict";
////////////////////////////////////////////////// //////////////////////////////////////////////////
...@@ -109,6 +109,29 @@ ...@@ -109,6 +109,29 @@
return new RSVP.Promise(waitForStream, canceller); return new RSVP.Promise(waitForStream, canceller);
} }
function handleGfx(canvas, settings) {
  • @romain

    Did you run "Test memory exhausted issue on mobile" on mobile?

    If I run, it crashes and mobile becomes unsable.

  • So, testing a bit more. The issue is here:

    https://lab.nexedi.com/nexedi/erp5/blob/master/bt5/erp5_document_scanner/PathTemplateItem/web_page_module/scanner_gadget_document_scanner_js.js#L71

    canvas.toBlob(resolve, 'image/jpeg', compression);

    But, I can not find how to compare canvas from caman and canvas from gfx.

  • Yes, I add this issue.

    The only workaround I found was to decrease the size of the image (a max of 3000px for example) in the preference.

    Please also note that the size is also limited automatically by the webgl MAX_TEXTURE_SIZE

Please register or sign in to reply
var webgl_canvas = fx.canvas(),
texture = webgl_canvas.texture(canvas),
tmp;
// apply the ink filter
tmp = webgl_canvas.draw(texture);
if ((settings.brightness && settings.brightness !== 0) ||
(settings.contrast && settings.contrast !== 0)) {
tmp.brightnessContrast(
(settings.brightness || 0) / 100,
(settings.contrast || 0) / 100
);
}
if (settings.enable_greyscale) {
tmp.hueSaturation(0, -1);
}
tmp.update();
return webgl_canvas;
}
function handleCaman(canvas, settings) { function handleCaman(canvas, settings) {
var local_caman; var local_caman;
...@@ -142,7 +165,7 @@ ...@@ -142,7 +165,7 @@
this.render(function () { this.render(function () {
// XXX canceller should be called automatically ? // XXX canceller should be called automatically ?
canceller(); canceller();
resolve(); resolve(canvas);
}); });
} catch (error) { } catch (error) {
canceller(); canceller();
...@@ -427,30 +450,57 @@ ...@@ -427,30 +450,57 @@
orientation = result; orientation = result;
var expected_width = settings.maximum_width, var expected_width = settings.maximum_width,
bitmap_options, bitmap_options;
div;
// If orientation is correct, return the original blob // If orientation is correct, return the original blob
// and size is small // and size is small
// no color correction is expected // and no color correction is expected
if (((orientation < 2) || (8 < orientation)) && if (((orientation < 2) || (8 < orientation)) &&
((!expected_width) || (original_width < expected_width)) && ((!expected_width) ||
((original_width < expected_width) && (original_height < expected_width))) &&
(!(settings.brightness || settings.contrast || settings.enable_greyscale))) { (!(settings.brightness || settings.contrast || settings.enable_greyscale))) {
return blob; return blob;
} }
if ((!!expected_width) && (expected_width < original_width)) {
bitmap_options = {
resizeWidth: expected_width,
// resizeHeight: expected_height,
resizeQuality: 'high'
};
}
// Else, transform the image // Else, transform the image
return new RSVP.Queue(createImageBitmap(blob, bitmap_options)) return new RSVP.Queue(createImageBitmap(blob))
.push(function (bitmap) { .push(function (bitmap) {
// Check if image dimension must be changed
// It is mandatory to check the bitmap info,
// as the image could be rotated
var canvas,
webgl_context,
higher_dimension_key,
higher_dimension_value;
if (bitmap.width < bitmap.height) {
higher_dimension_key = 'resizeHeight';
higher_dimension_value = bitmap.height;
} else {
higher_dimension_key = 'resizeWidth';
higher_dimension_value = bitmap.width;
}
canvas = document.createElement('canvas');
webgl_context = canvas.getContext('webgl');
expected_width = Math.min(
expected_width || webgl_context.getParameter(webgl_context.MAX_TEXTURE_SIZE),
webgl_context.getParameter(webgl_context.MAX_TEXTURE_SIZE) - 1
);
if ((!!expected_width) && (expected_width < higher_dimension_value)) {
bitmap_options = {
resizeQuality: 'high'
};
bitmap_options[higher_dimension_key] = expected_width;
return createImageBitmap(blob, bitmap_options);
}
return bitmap;
})
.push(function (bitmap) {
var height = bitmap.height, var height = bitmap.height,
width = bitmap.width, width = bitmap.width,
canvas = domsugar('canvas'), canvas = domsugar('canvas'),
...@@ -458,9 +508,9 @@ ...@@ -458,9 +508,9 @@
// Caman expect the canvas to be in a container // Caman expect the canvas to be in a container
// in order to replace it when resizing // in order to replace it when resizing
div = domsugar('div', [canvas]); domsugar('div', [canvas]);
if (4 < orientation && orientation < 9) { if ((4 < orientation) && (orientation < 9)) {
canvas.width = height; canvas.width = height;
canvas.height = width; canvas.height = width;
} else { } else {
...@@ -499,11 +549,13 @@ ...@@ -499,11 +549,13 @@
ctx.drawImage(bitmap, 0, 0); ctx.drawImage(bitmap, 0, 0);
if (settings.brightness || settings.contrast || settings.enable_greyscale) { if (settings.brightness || settings.contrast || settings.enable_greyscale) {
return handleCaman(canvas, settings); return handleGfx(canvas, settings);
// return handleCaman(canvas, settings);
} }
return canvas;
}) })
.push(function () { .push(function (final_canvas) {
return promiseCanvasToBlob(div.firstElementChild); return promiseCanvasToBlob(final_canvas);
}); });
}); });
} }
...@@ -951,4 +1003,4 @@ ...@@ -951,4 +1003,4 @@
}(rJS, RSVP, window, document, navigator, Cropper, Promise, JSON, jIO, }(rJS, RSVP, window, document, navigator, Cropper, Promise, JSON, jIO,
promiseEventListener, domsugar, createImageBitmap, FormData, Caman, promiseEventListener, domsugar, createImageBitmap, FormData, Caman,
FileReader, DataView, URL)); FileReader, DataView, URL, fx));
\ No newline at end of file \ No newline at end of file
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>982.58526.37480.14609</string> </value> <value> <string>982.59651.45192.29798</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -262,7 +262,7 @@ ...@@ -262,7 +262,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1585660747.23</float> <float>1585728228.5</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -7,6 +7,8 @@ url_list = [ ...@@ -7,6 +7,8 @@ url_list = [
"cropper.min.css", "cropper.min.css",
"cropper.min.js", "cropper.min.js",
"caman.full.min.js" "caman.full.min.js"
"caman.full.min.js",
"glfx.js"
] ]
return url_list return url_list
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>glfx.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>glfx.js</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment