আমি সাথে খেলা করছি <canvas>
এলিমেন্ট, অঙ্কন লাইন এবং এই জাতীয় ।
আমি লক্ষ্য করেছি যে আমার তির্যক রেখাগুলি অ্যান্টিয়ালাইজড। আমি যা করছি তার জন্য আমি জগি চেহারা পছন্দ করব - এই বৈশিষ্ট্যটি বন্ধ করার কোনও উপায় আছে কি?
আমি সাথে খেলা করছি <canvas>
এলিমেন্ট, অঙ্কন লাইন এবং এই জাতীয় ।
আমি লক্ষ্য করেছি যে আমার তির্যক রেখাগুলি অ্যান্টিয়ালাইজড। আমি যা করছি তার জন্য আমি জগি চেহারা পছন্দ করব - এই বৈশিষ্ট্যটি বন্ধ করার কোনও উপায় আছে কি?
উত্তর:
চিত্রের জন্য এখন আছে ।context.imageSmoothingEnabled
= false
তবে, লাইন অঙ্কনকে স্পষ্টভাবে নিয়ন্ত্রণ করে এমন কিছুই নেই। আপনার নিজের লাইনগুলি ( শক্ত উপায় ) ব্যবহার করে getImageData
এবং আঁকার দরকার হতে পারে putImageData
।
putImageData
তবে এটি এখনও নিকটবর্তী পিক্সেল শঙ্কার আলিয়াসিং করে।
আপনার 1-pixel
লাইনের স্থানাঙ্কগুলিতে পছন্দ করুন ctx.lineTo(10.5, 10.5)
। বিন্দুকে কেন্দ্র করে একটি এক-পিক্সেল রেখা আঁকা (10, 10)
মানে, যে এই 1
থেকে যে অবস্থানে পৌছানোর এ পিক্সেল 9.5
থেকে 10.5
যা দুই লাইন যে পটে আকাঁ পেতে ফলাফল।
শুরুতে আপনার পুরো ক্যানভাসটিতে 0.5
যদি আপনি প্রচুর এক-পিক্সেল লাইন পেয়ে থাকেন তবে যে অঙ্কনটি আপনি আঁকতে চান তা সর্বদা যুক্ত করতে হবে না এমন একটি দুর্দান্ত কৌশল alwaysctx.translate(0.5, 0.5)
ctx.translate(0.5,0.5)
তা করেনি। এফএফ 39.0
এটি মজিলা ফায়ারফক্সে করা যেতে পারে। এটি আপনার কোডে যুক্ত করুন:
contextXYZ.mozImageSmoothingEnabled = false;
অপেরাতে এটি বর্তমানে বৈশিষ্ট্যের অনুরোধ, তবে আশা করি এটি শীঘ্রই যুক্ত হয়ে যাবে।
আন্তঃসংখ্যক স্থানাঙ্ক (0.4, 0.4) জড়িত ভেক্টর গ্রাফিক্সের সঠিক প্লট করার জন্য অ্যান্টিয়ালাইজিং প্রয়োজন , যা খুব কম ক্লায়েন্টই করেন।
যখন অ-পূর্ণসংখ্যা স্থানাঙ্ক দেওয়া হয়, ক্যানভাসের দুটি বিকল্প থাকে:
পরবর্তী কৌশলটি স্থির গ্রাফিক্সের জন্য কাজ করবে, যদিও ছোট গ্রাফিক্সের জন্য (2 এর ব্যাসার্ধের একটি বৃত্ত) বক্ররেখা একটি মসৃণ বক্রতার পরিবর্তে পরিষ্কার পদক্ষেপগুলি প্রদর্শন করবে।
আসল সমস্যাটি হ'ল যখন গ্রাফিকগুলি অনুবাদ করা হয় (সরানো) - এক পিক্সেল এবং অন্যটির মধ্যে জাম্প হয় (১.6 => ২, ১.৪ => ১), এর অর্থ এই যে আকারের উত্স পিতামাতার ধারকের সাথে ঝাঁপিয়ে পড়তে পারে (ক্রমাগত স্থানান্তরিত হয়) 1 পিক্সেল উপরে / নীচে এবং বাম / ডান)।
টিপ # 1 : আপনি ক্যানভাসকে স্কেল করে (বা শক্ত করে) অ্যান্টিয়ালাইজিংকে নরম করতে পারেন (এক্স দ্বারা বলুন) তারপরে নিজের জ্যামিতিতে রেকিপ্রোকাল স্কেল (1 / এক্স) প্রয়োগ করুন (ক্যানভাসটি ব্যবহার করছেন না)।
তুলনা (কোন স্কেলিং):
(ক্যানভাস স্কেল: 0.75; ম্যানুয়াল স্কেল: 1.33) সহ:
এবং (ক্যানভাস স্কেল: 1.33; ম্যানুয়াল স্কেল: 0.75):
টিপ # 2 : যদি আপনার জাগতিক চেহারাটি আপনার পরে যা হয় তবে তা প্রতিটি আকৃতি কয়েকবার আঁকতে চেষ্টা করুন (মোছা না করে)। প্রতিটি অঙ্কনের সাথে সাথে অ্যান্টিঅ্যালাসিং পিক্সেল আরও গা .় হয়।
তুলনা করা. একবার আঁকার পরে:
তিনবার আঁকার পরে:
আমি কাস্টম লাইন অ্যালগরিদম যেমন ব্রেনহ্যামের লাইন অ্যালগরিদম ব্যবহার করে সমস্ত কিছু আঁকতাম। এই জাভাস্ক্রিপ্ট প্রয়োগ বাস্তবায়ন দেখুন: http://mebers.chello.at/easyfilter/canvas.html
আমি মনে করি এটি অবশ্যই আপনার সমস্যার সমাধান করবে।
setPixel(x, y)
; আমি স্বীকৃত উত্তরটি এখানে ব্যবহার করেছি: stackoverflow.com/questions/4899799/…
আমি যুক্ত করতে চাই যে কোনও চিত্রকে ক্ষুদ্রতর করার সময় এবং ক্যানভাসে আঁকতে আমার সমস্যা হয়েছিল, এটি এখনও স্মুথিং ব্যবহার করছিল, যদিও এটি উপরে উঠে যাওয়ার সময় ব্যবহার করা হয়নি।
আমি এটি ব্যবহার করে সমাধান করেছি:
function setpixelated(context){
context['imageSmoothingEnabled'] = false; /* standard */
context['mozImageSmoothingEnabled'] = false; /* Firefox */
context['oImageSmoothingEnabled'] = false; /* Opera */
context['webkitImageSmoothingEnabled'] = false; /* Safari */
context['msImageSmoothingEnabled'] = false; /* IE */
}
আপনি এই ফাংশনটি এভাবে ব্যবহার করতে পারেন:
var canvas = document.getElementById('mycanvas')
setpixelated(canvas.getContext('2d'))
এটি কারও পক্ষে কার্যকর is
ctx.translate(0.5, 0.5);
ctx.lineWidth = .5;
এই কম্বো দিয়ে আমি সুন্দর 1px পাতলা রেখা আঁকতে পারি।
একটি খুব সীমিত কৌশল লক্ষ্য করুন। আপনি যদি 2 টি রঙের চিত্র তৈরি করতে চান তবে আপনি # 010101 # 000000 রঙের পটভূমিতে রঙের সাথে আপনার পছন্দ মতো কোনও আকার আঁকতে পারেন। এটি হয়ে গেলে, আপনি প্রতিটি পিক্সেলটি চিত্র.ডেটা.ডেটায় [] পরীক্ষা করতে পারেন এবং মান 0x00 নয় যা 0xFF এ সেট করতে পারেন:
imageData = context2d.getImageData (0, 0, g.width, g.height);
for (i = 0; i != imageData.data.length; i ++) {
if (imageData.data[i] != 0x00)
imageData.data[i] = 0xFF;
}
context2d.putImageData (imageData, 0, 0);
ফলাফলটি অ-অ্যান্টিএলিয়েসড কালো ও সাদা ছবি হবে। এটি নিখুঁত হবে না, যেহেতু কিছু antialiasing সংঘটিত হবে, তবে এই antialiasing খুব সীমাবদ্ধ হবে, আকৃতির রঙটি অনেকটা ব্যাকগ্রাউন্ডের বর্ণের মতো।
যারা এখনও উত্তর খুঁজছেন তাদের জন্য। এখানে আমার সমাধান।
ধরে নিচ্ছি চিত্রটি 1 চ্যানেল ধূসর। আমি স্রেফ ctx.stroke () এর পরে থ্রেশহোল্ড করেছি।
ctx.beginPath();
ctx.moveTo(some_x, some_y);
ctx.lineTo(some_x, some_y);
...
ctx.closePath();
ctx.fill();
ctx.stroke();
let image = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height)
for(let x=0; x < ctx.canvas.width; x++) {
for(let y=0; y < ctx.canvas.height; y++) {
if(image.data[x*image.height + y] < 128) {
image.data[x*image.height + y] = 0;
} else {
image.data[x*image.height + y] = 255;
}
}
}
যদি আপনার চিত্র চ্যানেলটি 3 বা 4 হয় তবে আপনাকে অ্যারে সূচিটি পছন্দ করতে হবে
x*image.height*number_channel + y*number_channel + channel
স্ট্যাশঅফকোডের উত্তরে মাত্র দুটি নোট:
পরিবর্তে এটি করা ভাল:
স্ট্রোক করুন এবং পূরণ করুন #FFFFFF
, তারপরে এটি করুন:
imageData.data[i] = (imageData.data[i] >> 7) * 0xFF
এটি এটি 1px প্রস্থ সহ লাইনের জন্য সমাধান করে।
এগুলি ছাড়াও স্ট্যাশঅফকোডের সমাধানটি সঠিক কারণ এটি আপনার নিজের রাস্টারাইজেশন ফাংশনগুলি লেখার প্রয়োজন নেই (কেবল লাইনগুলিই নয়, বেজিয়ারগুলি, বৃত্তাকার আর্কসগুলি, গর্তগুলিতে ভরাট বহুভুজ ইত্যাদি বিবেচনা করুন ...)
এখানে জাভাস্ক্রিপ্টে ব্রেসেনহ্যামের অ্যালগরিদমের একটি প্রাথমিক বাস্তবায়ন। এটি এই উইকিপিডিয়া নিবন্ধে বর্ণিত পূর্ণসংখ্যা-গাণিতিক সংস্করণের উপর ভিত্তি করে: https://en.wikedia.org/wiki/Bresenham%27s_line_algorithm
function range(f=0, l) {
var list = [];
const lower = Math.min(f, l);
const higher = Math.max(f, l);
for (var i = lower; i <= higher; i++) {
list.push(i);
}
return list;
}
//Don't ask me.
//https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
function bresenhamLinePoints(start, end) {
let points = [];
if(start.x === end.x) {
return range(f=start.y, l=end.y)
.map(yIdx => {
return {x: start.x, y: yIdx};
});
} else if (start.y === end.y) {
return range(f=start.x, l=end.x)
.map(xIdx => {
return {x: xIdx, y: start.y};
});
}
let dx = Math.abs(end.x - start.x);
let sx = start.x < end.x ? 1 : -1;
let dy = -1*Math.abs(end.y - start.y);
let sy = start.y < end.y ? 1 : - 1;
let err = dx + dy;
let currX = start.x;
let currY = start.y;
while(true) {
points.push({x: currX, y: currY});
if(currX === end.x && currY === end.y) break;
let e2 = 2*err;
if (e2 >= dy) {
err += dy;
currX += sx;
}
if(e2 <= dx) {
err += dx;
currY += sy;
}
}
return points;
}
এরকম কিছু চেষ্টা করুন canvas { image-rendering: pixelated; }
।
আপনি যদি কেবল একটি লাইন অ্যান্টিএলাইজড না করে তৈরি করার চেষ্টা করছেন তবে এটি কাজ করবে না।
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.fillRect(4, 4, 2, 2);
canvas {
image-rendering: pixelated;
width: 100px;
height: 100px; /* Scale 10x */
}
<html>
<head></head>
<body>
<canvas width="10" height="10">Canvas unsupported</canvas>
</body>
</html>
যদিও আমি অনেক ব্রাউজারে এটি পরীক্ষা করিনি।