Skip to content

Commit 4205656

Browse files
committed
Convert the image to greyscale inside the C++/WASM code
1 parent da92472 commit 4205656

File tree

4 files changed

+51
-24
lines changed

4 files changed

+51
-24
lines changed

CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,14 @@ include_directories(${opencv_include_modules})
2828
add_executable(hello src/hello.cpp)
2929

3030
# Link to opencv.js precompiled libraries
31-
file(GLOB opencv_js "${OPENCV_DIR}/build_wasm/lib/*.a")
32-
target_link_libraries(hello ${opencv_js})
31+
file(GLOB opencv_libs "${OPENCV_DIR}/build_wasm/lib/*.a")
32+
target_link_libraries(hello ${opencv_libs})
33+
34+
# There is an issue regarding the order in which libraries
35+
# are passed to the compiler - pass libopencv_core.a last
36+
# https://answers.opencv.org/question/186124/undefined-reference-to-cvsoftdoubleoperator/
37+
file(GLOB opencv_lib_core "${OPENCV_DIR}/build_wasm/lib/libopencv_core.a")
38+
target_link_libraries(hello ${opencv_lib_core})
3339

3440
# Specify linker arguments
3541
set_target_properties(hello PROPERTIES LINK_FLAGS "-s ENVIRONMENT=web -s EXTRA_EXPORTED_RUNTIME_METHODS=['cwrap']")

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "emscripten-opencv",
3-
"version": "0.0.1",
3+
"version": "0.0.2",
44
"description": "Web app calling into C++ WebAssembly code that uses OpenCV",
55
"scripts": {
66
"build:wasm": "./build-wasm.sh",

src/hello.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
#include <cstring>
22
#include <opencv2/core/mat.hpp>
33
#include <opencv2/imgcodecs.hpp>
4+
#include <opencv2/imgproc.hpp>
45
#include <opencv2/opencv.hpp>
56
#include <emscripten.h>
67

8+
using namespace cv;
9+
710
#ifdef __cplusplus
811
extern "C" {
912
#endif
1013

1114
EMSCRIPTEN_KEEPALIVE
1215
uchar *processImage(uchar *array, int width, int height) {
13-
cv::Mat mat(height, width, CV_8UC4, array);
14-
// EM_ASM_({
15-
// console.log(`[processImage] width: ${$0}; height: ${$1}; array[0]: ${$2}; array[1]: ${$3}; array[2]: ${$4}`)
16-
// }, width, height, array[0], array[1], array[2]);
17-
const int cb = width * height * 4;
16+
Mat mat(height, width, CV_8UC4, array);
17+
cvtColor(mat, mat, COLOR_RGBA2GRAY);
18+
const int cb = width * height * mat.channels();
1819
uchar *array_copy = reinterpret_cast<uchar*>(malloc(cb));
19-
std::memcpy(array_copy, array, cb);
20+
std::memcpy(array_copy, mat.data, cb);
2021
return array_copy;
2122
}
2223

src/index.js

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,57 @@ window.Module = {
55
}
66
}
77

8-
const processImageBtn = document.getElementById('process-image-btn')
9-
const inputImage = document.getElementById('input-image')
10-
const outputImage = document.getElementById('output-image')
11-
128
const getImageData = () => {
139
console.log('[getImageData]')
10+
const img = document.getElementById('input-image')
1411
const canvas = document.createElement('canvas')
15-
canvas.width = inputImage.width
16-
canvas.height = inputImage.height
12+
canvas.width = img.width
13+
canvas.height = img.height
1714
ctx = canvas.getContext('2d')
18-
ctx.drawImage(inputImage, 0, 0, inputImage.width, inputImage.height)
15+
ctx.drawImage(img, 0, 0, img.width, img.height)
1916
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
2017
return imageData
2118
}
2219

23-
const drawOutputImage = (dataOut, width, height) => {
24-
console.log('[drawOutputImage]')
25-
const array = new Uint8ClampedArray(dataOut)
20+
const imageDataFrom1Channel = (data, width, height) => {
21+
console.log('[imageDataFrom1Channel]')
22+
const cb = width * height * 4
23+
const array = new Uint8ClampedArray(cb)
24+
data.forEach((pixelValue, index) => {
25+
const base = index * 4
26+
array[base] = pixelValue // R
27+
array[base + 1] = pixelValue // G
28+
array[base + 2] = pixelValue // B
29+
array[base + 3] = 255 // A
30+
})
31+
const imageData = new ImageData(array, width, height)
32+
return imageData
33+
}
34+
35+
const imageDataFrom4Channels = (data, width, height) => {
36+
console.log('[imageDataFrom4Channels]')
37+
const array = new Uint8ClampedArray(data)
2638
const imageData = new ImageData(array, width, height)
27-
outputImage.width = width
28-
outputImage.height = height
29-
ctx = outputImage.getContext('2d')
39+
return imageData
40+
}
41+
42+
const drawOutputImage = imageData => {
43+
console.log('[drawOutputImage]')
44+
const canvas = document.getElementById('output-image')
45+
canvas.width = imageData.width
46+
canvas.height = imageData.height
47+
ctx = canvas.getContext('2d')
3048
ctx.putImageData(imageData, 0, 0)
3149
}
3250

3351
const onProcessImage = (module, processImage) => () => {
3452
console.log('[onProcessImage]')
3553
const { data, width, height } = getImageData()
3654
const dataOutAddr = processImage(data, width, height)
37-
const dataOutSize = width * height * 4
55+
const dataOutSize = width * height * 1
3856
const dataOut = module.HEAPU8.slice(dataOutAddr, dataOutAddr + dataOutSize)
39-
drawOutputImage(dataOut, width, height)
57+
const imageData = imageDataFrom1Channel(dataOut, width, height)
58+
drawOutputImage(imageData)
4059
module._free(dataOutAddr)
4160
}
4261

@@ -52,5 +71,6 @@ const wrapProcessImage = module => {
5271
const init = module => {
5372
console.log('[init]')
5473
const processImage = wrapProcessImage(module)
74+
const processImageBtn = document.getElementById('process-image-btn')
5575
processImageBtn.addEventListener('click', onProcessImage(module, processImage))
5676
}

0 commit comments

Comments
 (0)