मेरी हस्तलिपि को कोड करने की तकनीक
(amygoodchild.com)ब्लॉक स्क्रिप्ट
- पिछला लेख block print version के alphabet के बारे में था.
- संक्षेप में, इसे इस प्रक्रिया से बनाया गया था:
- हर अक्षर के path के मुख्य points को define करने वाला code लिखना (~प्रति अक्षर 10 points).
- Chaikin के curve algorithm का इस्तेमाल करके path को smooth बनाना.
- path को variable thickness वाले shape में बदलना.
- p5js का उपयोग करके shape path को draw करना.
- यह कुछ ऐसा दिखता था:
- इस system से वाक्य generate करने के तरीके पर एक लेख जल्द आएगा. अपडेट पाने के लिए newsletter subscribe करें.
- मूल अक्षर path को define करना बहुत manual काम था, जिसमें code में positions लिखनी पड़ती थीं और points को adjust करना पड़ता था ताकि अक्षर सही दिखें.
- cursive को code करते समय इस process को सरल बनाया गया.
अक्षर डिज़ाइन
- p5js editor में आसानी से इस्तेमाल करने के लिए path के मुख्य points को define और output करने वाला एक tool बनाया गया.
- यह sample अक्षर दिखाता है और नए अक्षर डिज़ाइन करने के लिए एक area देता है.
- आगे की प्रक्रिया:
- path के मुख्य points पर click करके उन्हें place करें - resulting Chaikin curve path दिखाया जाता है.
- edit mode में जाने के लिए 'p' दबाएँ.
- point चुनें और उसे position तक drag करें.
- path को console में output करने के लिए 'enter' दबाएँ.
- हर अक्षर के लिए 2-3 options बनाए गए.
- result path इस तरह दिखता है:
[{x:0.7,y:22.5},{x:8.2,y:18.1},{x:8.9,y:11.2},{x:3.7,y:11.4},{x:1.7,y:18.9},{x:8.4,y:22.4},{x:17.7,y:22.0}] - अपनी ही handwriting को guide की तरह इस्तेमाल करना चाहता था, इसलिए lowercase और uppercase के examples लिखे, image को सीधे tool में load किया, और उसे trace किया.
- image को सही जगह पर रखने के लिए w/a/s/d keys और zoom in/out के लिए r/e keys का उपयोग किया.
- numbers, अक्षर generation window में उस area को रखने के लिए x y coordinates हैं.
- सभी paths बनाने, curves draw करने और उन्हें variable width shapes में बदलने के बाद, हर अक्षर अलग-अलग कुछ ऐसा दिखता था.
cursive बनाना
- कभी-कभी अक्षरों को जोड़ना आसान होता है. मुख्य point path से सीधे अगले path तक जाएँ और फिर पूरे path पर एक साथ Chaikin curve apply करें.
- लेकिन कुछ अक्षर जोड़े अच्छी तरह fit नहीं होते.
- उदाहरण के लिए, na जोड़ी में n का आख़िरी point नीचे होता है और a का पहला point ऊपर, इसलिए एक path a को diagonal में काटता है और वह e जैसा दिखता है.
- ti जोड़ी में t baseline के ऊपर समाप्त होता है और i baseline से शुरू होता है, जिससे एक अस्वाभाविक ridge बनती है.
- इस समस्या को हल करने के लिए a की शुरुआत में extra point जोड़े जा सकते हैं और t के आख़िरी दो points हटाए जा सकते हैं.
- लेकिन हर scenario में अक्षरों को इस तरह बदला नहीं जा सकता.
- उदाहरण के लिए, अगर a किसी शब्द की शुरुआत में हो तो extra point गलत जगह पर होता है, और अगर वह w जैसे अक्षर के बाद आए तो a को अलग तरीके से काटती हुई line बनती है.
- जब t की जोड़ी k के साथ बनती है, तो वह भी बदल जाता है.
- अक्षर path के start और end points दूसरे अक्षरों के साथ उसकी position के अनुसार बदलने चाहिए.
- शुरुआत में सोचा था कि खास "problem" pairs को identify करके उनके लिए rules लिखे जाएँ, लेकिन अंत में हर path के start और end पर numbers जोड़ दिए गए, जो यह दिखाते हैं:
- किसी दूसरे अक्षर से जुड़ा नहीं है (0)
- baseline के आसपास किसी दूसरे अक्षर से जुड़ता है (1)
- baseline के ठीक ऊपर किसी दूसरे अक्षर से जुड़ता है (2)
- x-height के आसपास किसी दूसरे अक्षर से जुड़ता है (3)
- उदाहरण:
- अब हर अक्षर path कुछ ऐसा दिखता है. start और end के एक-अंकीय numbers पर ध्यान दें:
[0,{x:12.2,y:13.2},{x:13.5,y:11.0},{x:6.2,y:8.4},{x:1.1,y:13.0},{x:1.8,y:19.0},{x:7.0,y:23.4},{x:15.2,y:23.6},{x:18.4,y:22.1},1] - सभी अक्षर जोड़ों को test किया गया:
- यहाँ आप देख सकते हैं कि हर अक्षर के लिए कई path options हैं, और पड़ोसी अक्षरों के अनुसार edit होने पर क्या बदलाव आते हैं.
- आदर्श रूप से हर अक्षर के लिए कम से कम 5-6 path options होने चाहिए, लेकिन file size के साथ संतुलन बनाना पड़ता है.
शब्द निर्माण
- जब कोई शब्द generate होता है:
- हर अक्षर के लिए 2-3 अलग options में से base path चुना जाता है.
- path के end की जानकारी पड़ोसी अक्षरों तक भेजी जाती है (क्योंकि एक ही अक्षर के अलग path options के endpoints अलग हो सकते हैं, इसलिए पहले सभी अक्षर paths चुने जाने चाहिए).
- base path पड़ोसी अक्षरों के हिसाब से adjust होता है. उदाहरण के लिए, अगर पिछले अक्षर की end height 2 है तो इस path की शुरुआत से 1 point हटा दिया जाता है, या अगर अगले अक्षर की start height 1 है तो किसी खास जगह extra point जोड़ दिया जाता है.
- adjustment function थोड़ा complex हो सकता है. उदाहरण के लिए, अक्षर q के लिए function इस तरह है:
// ip = path // pc = पिछले अक्षर की end info // nc = अगले अक्षर की start info // n = इस अक्षर के लिए चुने गए path का index adjust: (ip, pc, nc, n) => { // इस अक्षर के अंत में 70% chance से break जोड़ें if (rand() < 0.7 ) ip.splice(-1, 1, 0); // अगर 4 options में से [2] इस path के लिए चुना गया हो if (n < 2) { // अगर पिछला अक्षर 3 पर खत्म होता है, तो पहले दो points को दूसरे point से replace करें if (pc == 3) ip.splice(1, 2, {x:10,y:12}); // नहीं तो अगर वह 0 नहीं है, तो शुरुआत में point जोड़ें else if (pc > 0) ip.splice(1, 0, {x:10,y:20}); } // अगर इस अक्षर और अगले अक्षर के बीच कोई break नहीं है (0) if (nc > 0 && ip[ip.length-1] != 0){ // आख़िरी दो points को दूसरे point से replace करें ip.splice(-3, 2, {x:16,y:34}); } } - लेकिन कई बार यह छोटा भी होता है. उदाहरण के लिए, अक्षर n के लिए function इस तरह है:
adjust: (ip, pc, nc) => { // अगर अगला अक्षर 3 से शुरू होता है, तो random break बनाएँ या आख़िरी point को move करें if (nc == 3) rand() < 0.3 ? ip.splice(-1, 1, 0) : ip.splice(-2, 1, {x:17,y:23.8}); } - इसके बाद सभी अक्षरों के base paths को एक साथ जोड़ा जाता है. इस process में path के 1, 2, 3 को ignore किया जाता है, लेकिन जहाँ भी 0 होता है वहाँ एक नया path शुरू किया जाता है ताकि break बन सके.
- फिर path को curve में बदला जाता है, variable width shape में convert किया जाता है, और Perlin noise का उपयोग करके हल्की कंपकंपी जोड़ी जाती है. इसके बाद cursive writing कुछ ऐसी दिखती है.
- इस वाक्य को generate करने के तरीके पर एक लेख जल्द आएगा. अपडेट पाने के लिए newsletter subscribe करें.
- मज़े के लिए, plotter से निकली coded handwriting और असली handwriting की side-by-side तुलना भी की गई.
इसका वज़न कितना है?
- block print के लिए letter class 9.7kb थी.
- cursive letter class अभी 26.1kb है (compression के बाद).
- यह class बड़ी है क्योंकि इसमें हर अक्षर के लिए कई paths और points को adjust करने वाले functions शामिल हैं. लेकिन कुछ और बचत के तरीके भी हैं.
- लगता है और भी optimization संभव है. मैं code golf का जादूगर नहीं हूँ, लेकिन कुछ ideas हैं.
- उदाहरण के लिए, अभी अक्षर base font size 20 पर design किए गए हैं और बाद में scale होते हैं. इसका मतलब है कि कई points को x: 14.5 की तरह define किया जाता है, लेकिन अगर base size को 200 कर दिया जाए तो points को 145 की तरह define किया जा सकता है और decimal हटाए जा सकते हैं. यह बदलाव सावधानी से करना होगा, इसलिए इसे बाद की to-do list में रखा गया है.
कैसे उपयोग करें
- इस handwriting का मुख्य उद्देश्य उन diagrams में title, label, और doodle notes के लिए है जिन पर मैं काम कर रहा हूँ.
- लेकिन text के साथ खुद खेलना भी बहुत मज़ेदार है.
- paths को encode करने की वजह से, font इस्तेमाल करने के बजाय paths के साथ खेला जा सकता है. जैसे अक्षरों की position बदलना, अलग-अलग अक्षरों की thickness बदलना, आदि.
- अगला कदम इस handwriting को diagrams में integrate करना है, लेकिन text पर केंद्रित कुछ बनाने की भी योजना है. यह बहुत सुंदर है और इसमें बहुत संभावनाएँ हैं.
GN⁺ की राय
- यह लेख JavaScript और p5.js का उपयोग करके handwriting को digital बनाने की प्रक्रिया का एक दिलचस्प उदाहरण देता है. यह software engineers के लिए creative projects के ज़रिए coding skills का अभ्यास करने का अच्छा अवसर हो सकता है.
- इसमें यह सीखा जा सकता है कि Chaikin के curve algorithm जैसे mathematical algorithms को real projects में कैसे लागू किया जाए. इससे graphics programming की समझ बेहतर होती है.
- path adjustment function जैसी complex logic को handle करना भी सीखा जा सकता है. यह code की flexibility और scalability बढ़ाने के लिए महत्वपूर्ण skill है.
- यह project file size optimization जैसी practical problems को भी संभालता है. यह real-world software development में एक महत्वपूर्ण consideration है.
- इस तकनीक को अपनाते समय path definitions और adjustment functions लिखने में काफी समय लग सकता है. लेकिन नतीजा बहुत personal और unique text expression देता है.
अभी कोई टिप्पणी नहीं है.