- Skia Canvas Node.js में HTML Canvas ड्रॉइंग API को on-screen और off-screen rendering के लिए इस्तेमाल करने देता है, और Google Skia पर आधारित होने के कारण Chrome `<canvas>`` जैसा बहुत मिलता-जुलता output देता है
- आउटपुट को PDF·SVG जैसे vector formats और JPEG·PNG·WEBP जैसे bitmap formats में export किया जा सकता है, और इसे file·dataURL·Buffer·Sharp object से जोड़ा जा सकता है
- यह browser Canvas के दायरे से बाहर की क्षमताएँ भी संभालता है, जैसे GUI Window rendering, event framework, multi-page Canvas, path operations, 3D perspective transforms, CSS filter, और advanced typography control
- asynchronous rendering और file I/O यूज़र द्वारा configure किए गए worker pool के native threads पर प्रोसेस होते हैं, इसलिए यह server-side image generation और serverless environments के लिए उपयुक्त है
- benchmarks को serial और async modes में अलग-अलग मापा गया है, और async में कई repeated tasks को एक साथ शुरू करके multithreading प्रभाव की तुलना की जाती है
Node.js में इस्तेमाल होने वाला Canvas implementation
- Skia Canvas Node.js के लिए HTML Canvas ड्रॉइंग API का implementation है, जो on-screen और off-screen rendering दोनों को support करता है
- यह Google Skia graphics engine का उपयोग करता है, जिससे Chrome
<canvas>element जैसा बहुत मिलता-जुलता परिणाम मिलता है - इसमें browser Canvas में अभी उपलब्ध न होने वाली सुविधाएँ भी शामिल हैं
आउटपुट formats और export के तरीके
- image output में vector formats और bitmap formats दोनों supported हैं
- vector: PDF, SVG
- bitmap: JPEG, PNG, WEBP
- Canvas output को कई destinations पर भेजा जा सकता है
- interactive GUI Window पर सीधे draw किया जा सकता है, और browser-जैसा event framework भी दिया गया है
asynchronous rendering और multi-page support
- rendering और file I/O native threads का उपयोग करने वाले worker pool में asynchronous तरीके से चलाए जाते हैं
- worker pool को user configuration के अनुसार सेट किया जा सकता है
- एक ही Canvas में multiple pages बनाई जा सकती हैं
- एक single multi-page PDF के रूप में export किया जा सकता है
- या अलग-अलग files में बँटी image sequence के रूप में save किया जा सकता है
browser Canvas से आगे की graphics capabilities
- Bézier paths boolean operations और point-level interpolation को support करते हैं
- transform features basic Canvas scale·rotation·translation के अलावा 3D perspective transform भी देती हैं
- shape fill के लिए bitmap-based Pattern के साथ vector-based Texture भी इस्तेमाल किया जा सकता है
- line drawing में custom marker जोड़ा जा सकता है
- image processing पूरी CSS filter operator set को support करती है
typography control
- text rendering multiple lines और automatic line wrapping को handle करता है
- line-level text metrics देता है
- small-caps, ligature जैसी OpenType features को standard font-variant syntax से इस्तेमाल किया जा सकता है
- character spacing, word spacing, और leading को proportionally control किया जा सकता है
- variable fonts को support करता है और weight values को transparently map करता है
- local files से load किए गए non-system fonts भी इस्तेमाल किए जा सकते हैं
उपयोग के उदाहरण
- image file generation के उदाहरण में
Canvasबनाया जाता है औरgetContext("2d")से 2D context लेकर conic gradient को stroke style के रूप में इस्तेमाल करते हुए rectangle draw किया जाता हैsaveAs("rainbox.png", {density:2})से high-density image save की जाती हैcanvas.png,canvas.toBuffer("png")का shorthand हैtoDataURL("png")के result को HTML string के अंदर डाला जा सकता हैsaveAsSync("rainbox.pdf")से main thread पर synchronous save भी संभव है
- multi-page sequence के उदाहरण में
canvas.newPage()से अलग-अलग रंगों वाले pages बनाए और save किए जाते हैंall-pages.pdfके रूप में multi-page PDF save होती हैpage-{2}.pngpattern सेpage-01.png,page-02.pngजैसी कई files बनती हैं
- Window rendering के उदाहरण में
Window(300, 300)बनाया जाता है औरdrawevent में frame value के अनुसार line thickness बदलने वाला circle draw किया जाता है - Sharp.js integration के उदाहरण में Canvas output को Sharp object में बदलकर post-processing की जाती है, या Sharp से बनी image को
loadImageसे Canvas पर draw करने का flow दिखाया गया है
benchmark method और results
- benchmark में Skia Canvas को दो modes में test किया गया है
- serial: हर rendering task का इंतज़ार करने के बाद अगली repetition पर बढ़ा जाता है
- async: सभी test repetitions एक साथ शुरू की जाती हैं और multithreading support के साथ parallel execution होता है
- पूरा result canvas-benchmarks result page पर देखा जा सकता है
- startup latency test में 100 repetitions के आधार पर skia-canvas ने प्रति run 1ms से कम, कुल 33ms दर्ज किया
- canvaskit-wasm: प्रति run 25ms, कुल 2.47 सेकंड
- canvas: प्रति run 88ms, कुल 8.77 सेकंड
- @napi-rs/canvas: प्रति run 69ms, कुल 6.87 सेकंड
- Bézier curves test में 20 repetitions के आधार पर async mode की parallel processing का अंतर साफ दिखता है
- skia-canvas serial: प्रति run 137ms, कुल 2.74 सेकंड
- skia-canvas async: प्रति run 28ms, कुल 558ms
- comparison targets थे canvaskit-wasm 790ms, canvas 486ms, @napi-rs/canvas 230ms
- SVG to PNG test में 100 repetitions के आधार पर canvaskit-wasm supported नहीं था, जबकि skia-canvas ने serial में प्रति run 58ms और async में प्रति run 11ms दर्ज किया
- skia-canvas serial: कुल 5.83 सेकंड
- skia-canvas async: कुल 1.08 सेकंड
- image scale·rotation test के 50 repetitions के result
- skia-canvas serial: प्रति run 100ms, कुल 5.00 सेकंड
- skia-canvas async: प्रति run 19ms, कुल 935ms
- basic text test के 200 repetitions के result
- skia-canvas serial: प्रति run 21ms, कुल 4.26 सेकंड
- skia-canvas async: प्रति run 4ms, कुल 819ms
1 टिप्पणियां
Hacker News की राय
https://windowjs.org भी काफी मिलता-जुलता concept है
यह Skia को wrap करके Canvas API के रूप में expose करता है, लेकिन Node के बजाय v8 को embed कर बहुत छोटे runtime के तौर पर चलता है
यह लगभग 3 साल पहले public किया गया मेरा पहला open-source project था, और WebGL, audio वगैरह expose करके इसे desktop के लिए JavaScript game platform बनाने की योजना भी थी, लेकिन दूसरे काम और projects की वजह से development रुक गया
browser के बाहर भी Canvas इस्तेमाल करने देने वाले ऐसे project को देखकर अच्छा लगा
कभी-कभी बस network request करना भी होता है
Node.js के बजाय सिर्फ V8 embed करने से binary size कितना कम होता है, यह जानने की उत्सुकता है
Node.js भी V8 इस्तेमाल करता है, इसलिए यह भी जानना चाहूँगा कि Node binary size का बड़ा हिस्सा V8 से नहीं बल्कि runtime से आता है या नहीं
website और GitHub repository देखी, लेकिन Window.js binary आम तौर पर कितने kB या MB की होती है, यह नहीं मिला
जिज्ञासा है कि ऐसी library का इस्तेमाल कहाँ होता है
desktop पर shapes draw करने के लिए इससे बेहतर native libraries नहीं होतीं क्या, ऐसा लगता है
server side पर भी vector PDF generate करने होते हैं, इसलिए HTML Canvas API इस्तेमाल करके PDF बना सकने वाली Node library इस्तेमाल करते हैं
इससे अच्छा यह होता है कि web browser में render हुई sheet music और output बिल्कुल समान रहते हैं
कुल मिलाकर ऐसी library browser के अलावा environments में भी code reuse संभव बनाती है
Skia का बड़ा फायदा native graphics का असरदार उपयोग करने में है, और browser engines में इसके इस्तेमाल होने की मूल वजह भी यही है
ऊपर से target API एक ही होना भी फायदा है
एक ओर यह ज्यादा low-level है, लेकिन दूसरी ओर मैंने Puppeteer को 2D graphics library की तरह भी इस्तेमाल किया है
Canvas 2D, WebGL, WebGPU और पूरा HTML/CSS मिल जाता है, और text effects, background images, CSS transforms भी इस्तेमाल कर सकते हैं
images और videos load कर सकते हैं, और screenshot feature से compose किए गए result को image बना सकते हैं
यह जरूरत से ज्यादा है, लेकिन मेरे use case में इससे फर्क नहीं पड़ा; यह चलता है, cross-platform है और समस्या हल कर देता है
Skia Direct2D से थोड़ा तेज और Cairo से काफी तेज है
यह बहुत optimize किया गया है और इसमें GPU-accelerated backend भी है
Canvas बहुत आम 2D drawing API भी है
iOS में भी इसका native version है और Android में भी native version है, और drawing operations भी कुल मिलाकर मिलते-जुलते हैं
इसका फायदा उठाने से काफी लाभ मिलता है
Skia में CanvasKit शामिल है, जो Node को support करने वाला WASM build है: https://www.npmjs.com/package/canvaskit-wasm, और यह module शायद Rust bindings है
दोनों approaches के pros और cons जानने की उत्सुकता है
बस internally यह Rust/C++ mixed codebase से generate हुआ है
इसलिए मुख्य अंतर यह है कि WASM को अलग runtime चाहिए, जबकि Node binary को नहीं
क्या यह किसी Rust crate को wrap करने वाला wrapper जैसा है?
https://rust-skia.github.io/doc/skia_safe/canvas/struct.Canvas.html
Node में कुछ खास अलग बात बहुत नहीं दिखती
इसका लंबे समय से इंतजार था
पहले इसी तरह की चीज करने की कोशिशों में Node-Gyp installation चाहिए होता था, जो सचमुच nightmare था
यह simple rendering API से ज्यादा है: इसमें लिखा है कि “OS native graphics pipeline से window में render कर सकता है और browser जैसा UI event framework देता है”
WebGPU support के लिए wgpu और WebGL support के लिए ANGLE भी जोड़ा जा सकता है
यह WebGPU और ANGLE सहित कई rendering targets support करता है
QPainter raw images और windows को संभालता है, और event support वाले ज्यादा refined widgets भी हैं
और एक feature जिसे मैं काफी समय से ढूँढ रहा था: Qt में graphicsview है, जो window से बड़े graphics plane पर लाखों objects को resolution-independent तरीके से render कर सकता है और events भी handle कर सकता है
अगर Node-compatible Canvas implementations में interest है तो कुछ options हैं
Skia project का canvaskit-wasm शायद GPU-accelerated नहीं है: https://github.com/google/skia/tree/main/modules/canvaskit/npm_build
@napi-rs/canvas सबसे तेज binding है: https://github.com/Brooooooklyn/canvas?tab=readme-ov-file#performance
node-canvas Skia के बजाय Cairo इस्तेमाल करता है: https://github.com/Automattic/node-canvas
Advent of Code में जब simple graphics window चाहिए होती है, तब मैं इसे अभी Deno के साथ इस्तेमाल कर रहा हूँ
window-example भी है: https://skia-canvas.org/#rendering-to-a-window
deno add npm:skia-canvasसे add करें,deno.jsonमें"nodeModulesDir": "auto"डालें और फिरdeno install --allow-scriptsचलाएँइसे देखकर सच में excitement हो रही है
लगता है यह standalone चल सकने वाली और web-compatible graphics लिखना कहीं ज्यादा आसान बना देगा
पहली scripting language के लिए library compile करने के लिए दूसरी scripting language से source से build और code generate करने की जरूरत भी नहीं रहेगी
VS Code जैसी जगहों पर Canvas code को real-time render करने या web Canvas पर चलाने के लिए transformation layer वाले code को run करने में यह कितना fit बैठेगा, यह भी दिलचस्प होगा