ใน WebAssembly คืออะไรและมาจากไหน ผมได้อธิบายวิธีที่ WebAssembly ของเราจัดขึ้นในวันนี้ ในบทความนี้ เราจะแสดงวิธีการคอมไพล์โปรแกรม C ที่มีอยู่ mkbitmap
ไปยัง WebAssembly โปรแกรมนี้มีความซับซ้อนกว่าตัวอย่าง hello world เนื่องจากประกอบด้วยการทำงานกับไฟล์ การสื่อสารระหว่าง WebAssembly กับ JavaScript และการวาดบนผืนผ้าใบ แต่ก็ยังสามารถจัดการได้มากพอที่จะไม่ทำให้คุณรู้สึกว่าเป็นภาระ
บทความนี้เขียนขึ้นสำหรับนักพัฒนาเว็บที่ต้องการเรียนรู้ WebAssembly และแสดงวิธีดำเนินการทีละขั้นตอนเมื่อต้องการคอมไพล์บางอย่าง เช่น mkbitmap
ไปยัง WebAssembly ขอเตือนไว้ก่อนว่า การที่ไม่มีแอปหรือไลบรารีเพื่อคอมไพล์เมื่อเรียกใช้ครั้งแรกนั้นเป็นเรื่องปกติ จึงเป็นเหตุผลที่ทำให้บางขั้นตอนที่อธิบายไว้ด้านล่างไม่ทำงาน ฉันจึงต้องย้อนกลับไปใช้วิธีอื่นในภายหลัง บทความนี้ไม่ได้แสดงคำสั่งรวมคลิปขั้นสุดท้ายราวกับว่าร่วงหล่นลงมาจากฟ้า แต่ให้อธิบายความคืบหน้าที่แท้จริงของฉัน รวมถึงความไม่พอใจบางอย่างด้วย
เกี่ยวกับ mkbitmap
โปรแกรม mkbitmap
C จะอ่านรูปภาพและนำการดำเนินการต่อไปนี้อย่างน้อย 1 อย่างไปใช้กับรูปภาพนั้น โดยเรียงตามลำดับดังนี้ การกลับ การกรองไฮพาส การปรับขนาด และการกำหนดเกณฑ์ คุณควบคุมและเปิดหรือปิดการดำเนินการแต่ละรายการแยกกันได้ การใช้งานหลักของ mkbitmap
คือการแปลงรูปภาพสีหรือโทนสีเทาให้อยู่ในรูปแบบที่เหมาะสำหรับการป้อนข้อมูลสำหรับโปรแกรมอื่นๆ โดยเฉพาะโปรแกรมการติดตาม potrace
ที่เป็นพื้นฐานของ SVGcode เนื่องจากเป็นเครื่องมือประมวลผลล่วงหน้า mkbitmap
มีประโยชน์อย่างยิ่งในการแปลงภาพลายเส้นที่สแกนไว้ เช่น การ์ตูนหรือข้อความที่เขียนด้วยลายมือ ให้เป็นภาพ 2 ระดับที่มีความละเอียดสูง
คุณจะใช้ mkbitmap
โดยส่งต่อตัวเลือกจำนวนหนึ่งและชื่อไฟล์อย่างน้อย 1 ชื่อ โปรดดูรายละเอียดทั้งหมดได้ที่หน้าหลักของเครื่องมือ ดังนี้
$ mkbitmap [options] [filename...]
รับโค้ด
ขั้นตอนแรกคือการรับซอร์สโค้ดของ mkbitmap
คุณค้นหาได้ในเว็บไซต์ของโครงการ ในขณะที่เขียนบทความนี้ potrace-1.16.tar.gz เป็นเวอร์ชันล่าสุด
คอมไพล์และติดตั้งภายในเครื่อง
ขั้นตอนถัดไปคือคอมไพล์และติดตั้งเครื่องมือไว้ในเครื่องเพื่อให้ทราบลักษณะการทำงาน ไฟล์ INSTALL
มีวิธีการต่อไปนี้
cd
ไปยังไดเรกทอรีที่มีซอร์สโค้ดของแพ็กเกจและประเภท./configure
เพื่อกำหนดค่าแพ็กเกจสำหรับระบบของคุณการเรียกใช้
configure
อาจใช้เวลาสักครู่ ขณะทำงาน เครื่องจะพิมพ์ ข้อความบางข้อความเพื่อบอกว่าระบบกำลังตรวจสอบคุณลักษณะใดบ้างพิมพ์
make
เพื่อรวบรวมแพ็กเกจ(ไม่บังคับ) พิมพ์
make check
เพื่อเรียกใช้การทดสอบด้วยตนเองที่มาพร้อมกับแพ็กเกจ ซึ่งโดยทั่วไปจะใช้ไบนารีที่ยังไม่ได้ติดตั้งที่สร้างขึ้นมาทั้งหมดพิมพ์
make install
เพื่อติดตั้งโปรแกรม รวมถึงไฟล์ข้อมูลและเอกสารต่างๆ เมื่อติดตั้งลงในคำนำหน้าที่เป็นของรูท เราขอแนะนำให้กำหนดค่าและสร้างแพ็กเกจในฐานะผู้ใช้ทั่วไป และจะดำเนินการเฉพาะเฟสmake install
ด้วยสิทธิ์รูทเท่านั้น
เมื่อทำตามขั้นตอนเหล่านี้ คุณจะได้ไฟล์สั่งการ 2 ไฟล์ ได้แก่ potrace
และ mkbitmap
ซึ่งเป็นเนื้อหาสำคัญของบทความนี้ คุณสามารถยืนยันว่า URL ทำงานได้อย่างถูกต้องโดยเรียกใช้ mkbitmap --version
นี่คือเอาต์พุตของทั้ง 4 ขั้นตอนจากเครื่องของฉัน โดยตัดให้สั้นลงเพื่อความสั้นกระชับ
ขั้นตอนที่ 1 ./configure
:
$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ./install-sh -c -d
checking for gawk... no
checking for mawk... no
checking for nawk... no
checking for awk... awk
checking whether make sets $(MAKE)... yes
[…]
config.status: executing libtool commands
ขั้นตอนที่ 2 make
:
$ make
/Applications/Xcode.app/Contents/Developer/usr/bin/make all-recursive
Making all in src
clang -DHAVE_CONFIG_H -I. -I.. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
[…]
make[2]: Nothing to be done for `all-am'.
ขั้นตอนที่ 3 make check
:
$ make check
Making check in src
make[1]: Nothing to be done for `check'.
Making check in doc
make[1]: Nothing to be done for `check'.
[…]
============================================================================
Testsuite summary for potrace 1.16
============================================================================
# TOTAL: 8
# PASS: 8
# SKIP: 0
# XFAIL: 0
# FAIL: 0
# XPASS: 0
# ERROR: 0
============================================================================
make[1]: Nothing to be done for `check-am'.
ขั้นตอนที่ 4 sudo make install
:
$ sudo make install
Password:
Making install in src
.././install-sh -c -d '/usr/local/bin'
/bin/sh ../libtool --mode=install /usr/bin/install -c potrace mkbitmap '/usr/local/bin'
[…]
make[2]: Nothing to be done for `install-data-am'.
หากต้องการตรวจสอบว่าใช้งานได้หรือไม่ ให้เรียกใช้ mkbitmap --version
:
$ mkbitmap --version
mkbitmap 1.16. Copyright (C) 2001-2019 Peter Selinger.
หากเห็นรายละเอียดเวอร์ชัน แสดงว่าคุณคอมไพล์และติดตั้ง mkbitmap
เรียบร้อยแล้ว ต่อไป ให้ขั้นตอนเหล่านี้เทียบเท่ากับ WebAssembly
คอมไพล์ mkbitmap
ไปยัง WebAssembly
Emscripten เป็นเครื่องมือสำหรับการคอมไพล์โปรแกรม C/C++ ไปยัง WebAssembly เอกสารประกอบโครงการก่อสร้างของ Emscripten ระบุข้อมูลต่อไปนี้
การสร้างโปรเจ็กต์ขนาดใหญ่ด้วย Emscripten นั้นง่ายมาก Emscripten มีสคริปต์ง่ายๆ 2 สคริปต์ที่กำหนดค่า Makefile เพื่อใช้
emcc
แทนgcc
ในกรณีส่วนใหญ่ ระบบบิลด์ปัจจุบันของโปรเจ็กต์ที่เหลือจะไม่มีการเปลี่ยนแปลง
จากนั้นเอกสารก็ดำเนินต่อไป (โดยตัดต่อให้สั้นกระชับ)
ลองพิจารณากรณีที่ปกติแล้วคุณจะสร้างด้วยคำสั่งต่อไปนี้
./configure
make
หากต้องการสร้างด้วย Emscripten คุณจะใช้คำสั่งต่อไปนี้แทน
emconfigure ./configure
emmake make
ดังนั้น ./configure
จึงกลายเป็น emconfigure ./configure
และ make
จะกลายเป็น emmake make
วิดีโอต่อไปนี้แสดงวิธีดําเนินการด้วย mkbitmap
ขั้นตอนที่ 0 make clean
:
$ make clean
Making clean in src
rm -f potrace mkbitmap
test -z "" || rm -f
rm -rf .libs _libs
[…]
rm -f *.lo
ขั้นตอนที่ 1 emconfigure ./configure
:
$ emconfigure ./configure
configure: ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ./install-sh -c -d
checking for gawk... no
checking for mawk... no
checking for nawk... no
checking for awk... awk
[…]
config.status: executing libtool commands
ขั้นตอนที่ 2 emmake make
:
$ emmake make
make: make
/Applications/Xcode.app/Contents/Developer/usr/bin/make all-recursive
Making all in src
/opt/homebrew/Cellar/emscripten/3.1.36/libexec/emcc -DHAVE_CONFIG_H -I. -I.. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
[…]
make[2]: Nothing to be done for `all'.
หากทุกอย่างไม่มีปัญหาแล้ว ก็ควรมี .wasm
ไฟล์ในไดเรกทอรี คุณสามารถค้นหาได้โดยเรียกใช้ find . -name "*.wasm"
:
$ find . -name "*.wasm"
./a.wasm
./src/mkbitmap.wasm
./src/potrace.wasm
2 รายการสุดท้ายดูน่าสนใจดี จึงใส่ cd
ลงในไดเรกทอรี src/
นอกจากนี้ยังมีไฟล์ใหม่ที่เกี่ยวข้องอีก 2 ไฟล์ ได้แก่ mkbitmap
และ potrace
บทความนี้มีเนื้อหาที่เกี่ยวข้องกับ mkbitmap
เท่านั้น ข้อเท็จจริงที่ว่าส่วนขยายไม่มีส่วนขยาย .js
อาจชวนสับสนเล็กน้อย แต่ที่จริงแล้วเป็นไฟล์ JavaScript ซึ่งยืนยันได้ด้วยการเรียก head
สั้นๆ ดังนี้
$ cd src/
$ head -n 20 mkbitmap
// include: shell.js
// The Module object: Our interface to the outside world. We import
// and export values on it. There are various ways Module can be used:
// 1. Not defined. We create it here
// 2. A function parameter, function(Module) { ..generated code.. }
// 3. pre-run appended it, var Module = {}; ..generated code..
// 4. External script tag defines var Module.
// We need to check if Module already exists (e.g. case 3 above).
// Substitution will be replaced with actual code on later stage of the build,
// this way Closure Compiler will not mangle it (e.g. case 4. above).
// Note that if you want to run closure, and also to use Module
// after the generated code, you will need to define var Module = {};
// before the code. Then that object will be used in the code, and you
// can continue to use Module afterwards as well.
var Module = typeof Module != 'undefined' ? Module : {};
// --pre-jses are emitted after the Module integration code, so that they can
// refer to Module (if they choose; they can also define Module)
เปลี่ยนชื่อไฟล์ JavaScript เป็น mkbitmap.js
โดยเรียก mv mkbitmap mkbitmap.js
(และ mv potrace potrace.js
ตามลำดับหากต้องการ)
ตอนนี้ถึงเวลาทดสอบครั้งแรกเพื่อดูว่าทำงานได้หรือไม่โดยการเรียกใช้ไฟล์ด้วย Node.js ในบรรทัดคำสั่งด้วยการเรียกใช้ node mkbitmap.js --version
:
$ node mkbitmap.js --version
mkbitmap 1.16. Copyright (C) 2001-2019 Peter Selinger.
คุณคอมไพล์ mkbitmap
ไปยัง WebAssembly เรียบร้อยแล้ว ขั้นตอนถัดไปคือทำให้ Chrome ใช้งานได้ในเบราว์เซอร์
mkbitmap
ด้วย WebAssembly ในเบราว์เซอร์
คัดลอกไฟล์ mkbitmap.js
และ mkbitmap.wasm
ไปยังไดเรกทอรีใหม่ที่ชื่อว่า mkbitmap
และสร้างไฟล์ต้นแบบ index.html
ของ HTML ที่โหลดไฟล์ JavaScript ของ mkbitmap.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>mkbitmap</title>
</head>
<body>
<script src="mkbitmap.js"></script>
</body>
</html>
เริ่มเซิร์ฟเวอร์ภายในที่ให้บริการไดเรกทอรี mkbitmap
และเปิดในเบราว์เซอร์ คุณควรเห็นข้อความแจ้งที่ขอให้คุณป้อนข้อมูล กรณีนี้เป็นไปตามที่คาดไว้ เนื่องจากอ้างอิงจากหน้าหลักของเครื่องมือ "[i]ไม่มีการให้อาร์กิวเมนต์ชื่อไฟล์ จากนั้น mkbitmap จะทำหน้าที่เป็นตัวกรอง คืออ่านจากอินพุตมาตรฐาน" ซึ่งสำหรับ Emscripten โดยค่าเริ่มต้นจะเป็น prompt()
ป้องกันการดำเนินการอัตโนมัติ
หากต้องการหยุดการทำงานของ mkbitmap
ทันทีและกำหนดให้รอข้อมูลจากผู้ใช้แทน คุณต้องเข้าใจออบเจ็กต์ Module
ของ Emscripten Module
เป็นออบเจ็กต์ JavaScript ส่วนกลางที่มีแอตทริบิวต์ที่โค้ดซึ่งสร้าง Emscripten เรียกใช้ ณ จุดต่างๆ ในการทำงาน
คุณระบุการติดตั้งใช้งาน Module
เพื่อควบคุมการเรียกใช้โค้ดได้
เมื่อแอปพลิเคชัน Emscripten เริ่มทำงาน จะดูค่าในออบเจ็กต์ Module
และนำไปใช้
ในกรณีของ mkbitmap
ให้ตั้งค่า Module.noInitialRun
เป็น true
เพื่อป้องกันการเรียกใช้ครั้งแรกที่ทำให้ข้อความแจ้งปรากฏขึ้น สร้างสคริปต์ชื่อ script.js
ใส่สคริปต์ดังกล่าวก่อน <script src="mkbitmap.js"></script>
ใน index.html
และเพิ่มโค้ดต่อไปนี้ลงใน script.js
เมื่อโหลดแอปซ้ำ ข้อความแจ้งจะหายไป
var Module = {
// Don't run main() at page load
noInitialRun: true,
};
สร้างบิลด์โมดูลด้วยแฟล็กบิลด์เพิ่มเติม
หากต้องการให้อินพุตแก่แอป คุณสามารถใช้การรองรับระบบไฟล์ของ Emscripten ใน Module.FS
ส่วนการรวมการรองรับระบบไฟล์ในเอกสารประกอบจะระบุดังนี้
Emscripten จะตัดสินใจว่าจะรวมการรองรับระบบไฟล์โดยอัตโนมัติหรือไม่ โปรแกรมจำนวนมากไม่จำเป็นต้องใช้ไฟล์ และการรองรับระบบไฟล์นั้นมีขนาดเล็กมาก ดังนั้น Emscripten จะหลีกเลี่ยงการรวมไฟล์เมื่อไม่เห็นเหตุผลที่ต้องการ ซึ่งหมายความว่าหากโค้ด C/C++ ของคุณไม่ได้เข้าถึงไฟล์ ออบเจ็กต์
FS
และ API ระบบไฟล์อื่นๆ จะไม่รวมอยู่ในเอาต์พุต ในทางกลับกัน หากโค้ด C/C++ ใช้ไฟล์ ระบบจะรวมการรองรับระบบไฟล์ไว้โดยอัตโนมัติ
ขออภัย mkbitmap
เป็นหนึ่งในกรณีที่ Emscripten ไม่ได้รวมการรองรับระบบไฟล์โดยอัตโนมัติ คุณจึงต้องแจ้งอย่างชัดเจนให้ดำเนินการดังกล่าว ซึ่งหมายความว่าคุณต้องทำตามขั้นตอน emconfigure
และ emmake
ที่อธิบายไว้ก่อนหน้านี้ และตั้งค่าแฟล็กอีก 2 รายการผ่านอาร์กิวเมนต์ CFLAGS
แฟล็กต่อไปนี้อาจเป็นประโยชน์สำหรับโปรเจ็กต์อื่นๆ ด้วย
- ตั้งค่า
-sFILESYSTEM=1
เพื่อรวมการรองรับระบบไฟล์ - ตั้งค่า
-sEXPORTED_RUNTIME_METHODS=FS,callMain
เพื่อส่งออกModule.FS
และModule.callMain
- ตั้งค่า
-sMODULARIZE=1
และ-sEXPORT_ES6
เพื่อสร้างโมดูล ES6 ที่ทันสมัย - ตั้งค่า
-sINVOKE_RUN=0
เพื่อป้องกันการเรียกใช้ครั้งแรกที่ทำให้ข้อความแจ้งปรากฏขึ้น
นอกจากนี้ ในกรณีดังกล่าว คุณต้องตั้งค่าแฟล็ก --host
เป็น wasm32
เพื่อบอกสคริปต์ configure
ว่าคุณกำลังคอมไพล์สำหรับ WebAssembly
คำสั่ง emconfigure
สุดท้ายจะมีลักษณะดังนี้
$ emconfigure ./configure --host=wasm32 CFLAGS='-sFILESYSTEM=1 -sEXPORTED_RUNTIME_METHODS=FS,callMain -sMODULARIZE=1 -sEXPORT_ES6 -sINVOKE_RUN=0'
อย่าลืมเรียกใช้ emmake make
อีกครั้ง แล้วคัดลอกไฟล์ที่สร้างขึ้นใหม่ไปยังโฟลเดอร์ mkbitmap
แก้ไข index.html
เพื่อให้โหลดเฉพาะโมดูล ES script.js
เท่านั้น จากนั้นจึงนำเข้าโมดูล mkbitmap.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>mkbitmap</title>
</head>
<body>
<!-- No longer load `mkbitmap.js` here -->
<script src="script.js" type="module"></script>
</body>
</html>
// This is `script.js`.
import loadWASM from './mkbitmap.js';
const run = async () => {
const Module = await loadWASM();
console.log(Module);
};
run();
เมื่อเปิดแอปในเบราว์เซอร์ตอนนี้ คุณควรเห็นออบเจ็กต์ Module
บันทึกไปยังคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ และข้อความแจ้งจะหายไป เนื่องจากฟังก์ชัน main()
ของ mkbitmap
จะไม่เรียกใช้ในตอนเริ่มต้นอีกต่อไป
เรียกใช้ฟังก์ชันหลักด้วยตนเอง
ขั้นตอนถัดไปคือการเรียกใช้ฟังก์ชัน main()
ของ mkbitmap
ด้วยตนเองโดยเรียกใช้ Module.callMain()
ฟังก์ชัน callMain()
จะใช้อาร์เรย์ของอาร์กิวเมนต์ ซึ่งตรงกับสิ่งที่คุณจะส่งในบรรทัดคำสั่งทีละรายการ หากเรียกใช้ mkbitmap -v
ในบรรทัดคำสั่ง คุณจะต้องเรียกใช้ Module.callMain(['-v'])
ในเบราว์เซอร์ การดำเนินการนี้จะบันทึกหมายเลขเวอร์ชันของ mkbitmap
ไปยังคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ
// This is `script.js`.
import loadWASM from './mkbitmap.js';
const run = async () => {
const Module = await loadWASM();
Module.callMain(['-v']);
};
run();
เปลี่ยนเส้นทางเอาต์พุตมาตรฐาน
เอาต์พุตมาตรฐาน (stdout
) คือคอนโซลโดยค่าเริ่มต้น แต่จะเปลี่ยนเส้นทางไปยังอย่างอื่นได้ เช่น ฟังก์ชันที่เก็บเอาต์พุตเป็นตัวแปร ซึ่งหมายความว่าคุณจะเพิ่มเอาต์พุตลงใน HTML ได้โดยการตั้งค่าพร็อพเพอร์ตี้ Module.print
// This is `script.js`.
import loadWASM from './mkbitmap.js';
const run = async () => {
let consoleOutput = 'Powered by ';
const Module = await loadWASM({
print: (text) => (consoleOutput += text),
});
Module.callMain(['-v']);
document.body.textContent = consoleOutput;
};
run();
รับไฟล์อินพุตลงในระบบไฟล์หน่วยความจำ
หากต้องการส่งไฟล์อินพุตลงในระบบไฟล์หน่วยความจำ คุณต้องมีไฟล์ที่เทียบเท่า mkbitmap filename
ในบรรทัดคำสั่ง เพื่อให้เข้าใจแนวทางนี้ ก่อนอื่นฉันขอทราบข้อมูลพื้นฐานเกี่ยวกับวิธีที่ mkbitmap
คาดหวังข้อมูลและสร้างผลลัพธ์
รูปแบบอินพุต mkbitmap
ที่รองรับ ได้แก่ PNM (PBM, PGM, PPM) และ BMP รูปแบบเอาต์พุตคือ PBM สำหรับบิตแมป และ PGM สำหรับสีเทา หากกำหนดอาร์กิวเมนต์ filename
ไว้ mkbitmap
จะสร้างไฟล์เอาต์พุตที่ได้ชื่อมาจากชื่อไฟล์อินพุตโดยเปลี่ยนคำต่อท้ายเป็น .pbm
ตัวอย่างเช่น ชื่อไฟล์อินพุต example.bmp
ชื่อไฟล์เอาต์พุตจะเป็น example.pbm
Emscripten มีระบบไฟล์เสมือนที่จำลองระบบไฟล์ในเครื่อง เพื่อให้สามารถคอมไพล์และเรียกใช้โค้ดแบบเนทีฟที่ใช้ API ไฟล์แบบซิงโครนัสได้โดยมีการเปลี่ยนแปลงเพียงเล็กน้อยหรือไม่ต้องเปลี่ยนแปลงเลย
หากต้องการให้ mkbitmap
อ่านไฟล์อินพุตเสมือนว่ามีการส่งผ่านเป็นอาร์กิวเมนต์บรรทัดคำสั่ง filename
คุณต้องใช้ออบเจ็กต์ FS
ที่ Emscripten มีให้
ออบเจ็กต์ FS
รองรับโดยระบบไฟล์แบบในหน่วยความจำ (มักเรียกว่า MEMFS) และมีฟังก์ชัน writeFile()
ที่ใช้เขียนไฟล์ลงในระบบไฟล์เสมือน คุณใช้ writeFile()
ตามที่แสดงในตัวอย่างโค้ดต่อไปนี้
หากต้องการยืนยันว่าการดำเนินการเขียนไฟล์ใช้งานได้ ให้เรียกใช้ฟังก์ชัน readdir()
ของออบเจ็กต์ FS
ที่มีพารามิเตอร์ '/'
คุณจะเห็น example.bmp
และไฟล์เริ่มต้นจำนวนหนึ่งที่สร้างขึ้นโดยอัตโนมัติเสมอ
โปรดทราบว่าการโทรติดต่อ Module.callMain(['-v'])
ก่อนหน้านี้เพื่อพิมพ์หมายเลขเวอร์ชันถูกนำออก กรณีนี้เกิดจากการที่ Module.callMain()
เป็นฟังก์ชันที่โดยทั่วไปแล้วคาดว่าจะทำงานเพียงครั้งเดียว
// This is `script.js`.
import loadWASM from './mkbitmap.js';
const run = async () => {
const Module = await loadWASM();
const buffer = await fetch('https://example.com/example.bmp').then((res) => res.arrayBuffer());
Module.FS.writeFile('example.bmp', new Uint8Array(buffer));
console.log(Module.FS.readdir('/'));
};
run();
การดำเนินการจริงครั้งแรก
เมื่อทุกอย่างเรียบร้อยแล้ว ให้เรียกใช้ mkbitmap
โดยเรียกใช้ Module.callMain(['example.bmp'])
บันทึกเนื้อหาในโฟลเดอร์ '/'
ของ MEMFS คุณจะเห็นไฟล์เอาต์พุต example.pbm
ที่สร้างขึ้นใหม่อยู่ข้างไฟล์อินพุต example.bmp
// This is `script.js`.
import loadWASM from './mkbitmap.js';
const run = async () => {
const Module = await loadWASM();
const buffer = await fetch('https://example.com/example.bmp').then((res) => res.arrayBuffer());
Module.FS.writeFile('example.bmp', new Uint8Array(buffer));
Module.callMain(['example.bmp']);
console.log(Module.FS.readdir('/'));
};
run();
นำไฟล์เอาต์พุตออกจากระบบไฟล์หน่วยความจำ
ฟังก์ชัน readFile()
ของออบเจ็กต์ FS
เปิดใช้การสร้าง example.pbm
ในขั้นตอนสุดท้ายจากระบบไฟล์หน่วยความจำ ฟังก์ชันนี้จะแสดงผล Uint8Array
ที่คุณแปลงเป็นออบเจ็กต์ File
และบันทึกไปยังดิสก์ เนื่องจากเบราว์เซอร์มักไม่รองรับไฟล์ PBM สำหรับการดูในเบราว์เซอร์โดยตรง
(มีวิธีที่สะดวกกว่าในการบันทึกไฟล์ แต่การใช้ <a download>
ที่สร้างขึ้นแบบไดนามิกเป็นวิธีที่รองรับอย่างกว้างขวางที่สุด) เมื่อบันทึกไฟล์แล้ว คุณจะสามารถเปิดไฟล์ในโปรแกรมดูรูปภาพที่คุณชื่นชอบได้
// This is `script.js`.
import loadWASM from './mkbitmap.js';
const run = async () => {
const Module = await loadWASM();
const buffer = await fetch('https://example.com/example.bmp').then((res) => res.arrayBuffer());
Module.FS.writeFile('example.bmp', new Uint8Array(buffer));
Module.callMain(['example.bmp']);
const output = Module.FS.readFile('example.pbm', { encoding: 'binary' });
const file = new File([output], 'example.pbm', {
type: 'image/x-portable-bitmap',
});
const a = document.createElement('a');
a.href = URL.createObjectURL(file);
a.download = file.name;
a.click();
};
run();
เพิ่ม UI เชิงโต้ตอบ
ในจุดนี้ ไฟล์อินพุตได้รับการฮาร์ดโค้ดและ mkbitmap
ทำงานโดยใช้พารามิเตอร์เริ่มต้น ขั้นตอนสุดท้ายคือการให้ผู้ใช้เลือกไฟล์อินพุตแบบไดนามิก ปรับแต่งพารามิเตอร์ mkbitmap
แล้วเรียกใช้เครื่องมือด้วยตัวเลือกที่เลือกไว้
// Corresponds to `mkbitmap -o output.pbm input.bmp -s 8 -3 -f 4 -t 0.45`.
Module.callMain(['-o', 'output.pbm', 'input.bmp', '-s', '8', '-3', '-f', '4', '-t', '0.45']);
รูปแบบรูปภาพ PBM แยกวิเคราะห์ได้ไม่ยากนัก ดังนั้นด้วยโค้ด JavaScript บางโค้ด คุณยังสามารถแสดงตัวอย่างภาพเอาต์พุตได้อีกด้วย โปรดดูซอร์สโค้ดของการสาธิตที่ฝังอยู่ด้านล่างเพื่อดูวิธีหนึ่งในการดำเนินการ
บทสรุป
ขอแสดงความยินดี คุณคอมไพล์ mkbitmap
ไปยัง WebAssembly สำเร็จแล้ว และทำงานในเบราว์เซอร์ได้ บางจุดมีทางตันและคุณต้องคอมไพล์เครื่องมือมากกว่า 1 ครั้งจนกว่าจะได้ผล แต่อย่างที่ผมเขียนไว้ข้างต้น นี่เป็นส่วนหนึ่งของประสบการณ์การใช้งาน อย่าลืมแท็ก webassembly
ของ StackOverflow หากพบปัญหา ขอให้สนุกกับการคอมไพล์
ข้อความแสดงการยอมรับ
บทความนี้ได้รับการตรวจสอบโดย Sam Clegg และ Rachel Andrew