تغییر پیکسل ها با استفاده از Canvas

مرورگرهای مدرن از طریق عنصر <video> از عمل پخش ویدیو پشتیبانی می‌کنند. بیشتر مرورگرها با استفاده از یک API به نام ()MediaDevices.getUserMedia به وب کم دسترسی دارند اما با ترکیب این دو نمی‌توان به طور مستقیم به آن پیکسل‌ها دسترسی داشته یا آن‌ها را دستکاری کرد.


خوشبختانه، مرورگرها دارای یک Canvas API هستند که به ما امکان رسم طرح‌های گرافیکی با استفاده از جاوا اسکریپت را می‌دهد. در واقع، ما می‌توانیم تصاویر را از ویدیو به <canvas> بکشیم که این کار به ما توانایی تغییر با بازی کردن با آن پیکسل‌ها را می‌دهد. هر آنچه که در این مقاله از لیداوب در مورد چگونگی تغییر پیکسل‌ها می‌آموزید که به شما دانشی برای کار با تصاویر و ویدیوها از هر نوعی و از هر منبعی را می‌دهد.

افزودن یک تصویر به Canvas

پیش از آنکه کار با ویدیو را شروع کنیم بیایید افزودن تصویر به canvas را بررسی کنیم:

<img id="SourceImage" src="image.jpg">
<div class="video-container">
  <canvas id="Canvas" class="video"></canvas>
</div>

ما تصویری را ایجاد کردیم که نماینده تصویری است که می‌خواهیم روی canvas رسم کنیم. می‌توانستیم به جای این روش از شئ image در جاوا اسکریپت استفاده کنیم:

var canvas;
var context;

function init() {
  var image = document.getElementById('SourceImage');
  canvas = document.getElementById('Canvas');
  context = canvas.getContext('2d');

  drawImage(image);
  // Or
  // var image = new Image();
  // image.onload = function () {
  //    drawImage(image);
  // }
  // image.src = 'image.jpg';
}

function drawImage(image) {
  // Set the canvas the same width and height of the image
  canvas.width = image.width;
  canvas.height = image.height;

  context.drawImage(image, 0, 0);
}

window.addEventListener('load', init);

کد بالا تصویر را به طور کامل بر روی canvas ترسیم می‌کند:

تغییر پیکسل ها با استفاده از canvas

حالا می‌توانیم بازی با آن پیکسل‌ها را آغاز کنیم.

به روز رسانی اطلاعات تصویر

اطلاعات تصویر بر روی canvas به ما امکان دستکاری و تغییر پیکسل‌ها را می‌دهد. ویژگی داده یک شئ ImageData با سه ویژگی width، height و data/ است که تمامی آن‌ها نشان‌دهنده مقادیر مشابه در تصویر اصلی هستند. تمام آن ویژگی‌ها readonly هستند. آنچه برای ما اهمیت دارد data است، n آرایه یک بعدی که با یک شئ Uint8ClampedArray نشان داده شده و حاوی داده‌های مربوط به هر پیکسل با فرمت RGBA است.

گرچه ویژگی data به صورت readonly می‌باشد اما به این معنا نیست که ما می‌توانیم مقدار آن را تغییر دهیم، بلکه یعنی ما نمی‌توانیم آرایه دیگری را به این ویژگی نسبت دهیم:

// Get the canvas image data
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);

image.data = new Uint8ClampedArray(); // WRONG
image.data[1] = 0; // CORRECT

ممکن است بپرسید شئ Uint8ClampedArray نشان‌دهنده چه مقادیری است؟ به طور خلاصه، این آرایه مقادیری از صفر تا ۲۵۵ را در هر جایگاه ذخیره می‌کند که آن را به راه‌ حلی فوق‌العاده برای فرمت RGBA تبدیل کند.

یادگیری بیشتر در لیداوب:

رنگ های RGBA

رنگ‌ها می‌توانند با فرمت RGBA نمایش داده شوند که ترکیبی از قرمز، سبز و آبی است. حرف A نشان‌دهنده مقدار آلفا است که تاری رنگ می‌باشد. هر جایگاه در یک آرایه نشان‌دهنده یک مقدار از کانال رنگ (پیکسل) است.

- جایگاه اول مربوط به مقدار قرمز است

- جایگاه دوم مربوط به مقدار سبز است

- جایگاه سوم مربوط به مقدار آبی است

- جایگاه چهارم مربوط به مقدار آلفا است

- جایگاه پنجم مربوط به مقدار قرمز پیکسل بعدی است

- جایگاه ششم مربوط به مقدار سبز پیکسل بعدی است

- جایگاه هفتم مربوط به مقدار آبی پیکسل بعدی است

- جایگاه هشتم مربوط به مقدار آلفای پیکسل بعدی است

و به همین ترتیب ادامه دارد...

اگر شما یک تصویر 2X2 داشته باشید، در این صورت ما یک آرایه ۱۶ جایگاهی خواهیم داشت (۲*۲ پیکسل *۴ مقدار برای هر کدام).

تغییر پیکسل ها با استفاده از canvas

این آرایه به صورت زیر نمایش داده می‌شود:

// RED                 GREEN                BLUE                 WHITE
[ 255, 0, 0, 255,      0, 255, 0, 255,      0, 0, 255, 255,      255, 255, 255, 255]

تغییر داده های پیکسل

یکی از سریع‌ترین کارهایی که می‌توانیم انجام دهیم این است که با تغییر تمام مقادیر RGBA به ۲۵۵، رنگ تمام پیکسل‌ها را سفید کنیم:

// Use a button to trigger the "effect"
var button = document.getElementById('Button');

button.addEventListener('click', onClick);

function changeToWhite(data) {
  for (var i = 0; i < data.length; i++) {
    data[i] = 255;
  }
}

function onClick() {
  var imageData = context.getImageData(0, 0, canvas.width, canvas.height);

  changeToWhite(imageData.data);

  // Update the canvas with the new data
  context.putImageData(imageData, 0, 0);
}

ویژگی data به عنوان مرجع در نظر گرفته خواهد شد که یعنی هر تغییری که در آن ایجاد کنیم، مقدار آرگومان را تغییر خواهد داد:

معکوس کردن رنگ ها

یک افکت زیبا که نیاز به محاسبات زیادی هم ندارد معکوس کردن رنگ‌های یک تصویر است. معکوس کردن مقدار یک رنگ را می‌توان با استفاده از اپراتور XOR (^) یا فرمول 255 – value (value باید بین صفر تا ۲۵۵ باشد) انجام داد:

function invertColors(data) {
  for (var i = 0; i < data.length; i+= 4) {
    data[i] = data[i] ^ 255; // Invert Red
    data[i+1] = data[i+1] ^ 255; // Invert Green
    data[i+2] = data[i+2] ^ 255; // Invert Blue
  }
}

function onClick() {
  var imageData = context.getImageData(0, 0, canvas.width, canvas.height);

  invertColors(imageData.data);

  // Update the canvas with the new data
  context.putImageData(imageData, 0, 0);
}

ما حلقه را به جای یک برابر، چهار برابر می‌کنیم بنابراین، هر پیکسل در یک آرایه را می‌توانیم با ۴ عنصر پر کنیم. مقدار آلفا بر معکوس کردن رنگ‌ها تاثیری ندارد بنابراین از آن عبور می‌کنیم.

روشنایی و کنتراست

 تنظیم روشنایی یک تصویر می‌تواند با استفاده از فرمول بعدی انجام شود:

newValue = currentValue + 255 * (brightness / 100)

- brightness باید بین ۱۰۰- تا ۱۰۰ باشد

- currentValue مقدار فعلی نور قرمز، سبز یا آبی است

- newValue نتیجه نور فعلی رنگ به علاوه brightness است

تعیین کنتراست تصویر می‌تواند با این فرمول انجام شود:

factor = (259 * (contrast + 255)) / (255 * (259 - contrast))
color = GetPixelColor(x, y)
newRed   = Truncate(factor * (Red(color)   - 128) + 128)
newGreen = Truncate(factor * (Green(color) - 128) + 128)
newBlue  = Truncate(factor * (Blue(color)  - 128) + 128)

محاسبات اصلی شامل به دست آوردن فاکتور کنتراست است که برای هر یک از مقادیر رنگ‌ها اعمال خواهد شد. Truncate تابعی است که بررسی می‌کند مقدار بین صفر تا ۲۵۵ باشد. حالا می‌خواهیم این تابع را به زبان جاوا اسکریپت بنویسیم:

function applyBrightness(data, brightness) {
  for (var i = 0; i < data.length; i+= 4) {
    data[i] += 255 * (brightness / 100);
    data[i+1] += 255 * (brightness / 100);
    data[i+2] += 255 * (brightness / 100);
  }
}

function truncateColor(value) {
  if (value < 0) {
    value = 0;
  } else if (value > 255) {
    value = 255;
  }

  return value;
}

function applyContrast(data, contrast) {
  var factor = (259.0 * (contrast + 255.0)) / (255.0 * (259.0 - contrast));

  for (var i = 0; i < data.length; i+= 4) {
    data[i] = truncateColor(factor * (data[i] - 128.0) + 128.0);
    data[i+1] = truncateColor(factor * (data[i+1] - 128.0) + 128.0);
    data[i+2] = truncateColor(factor * (data[i+2] - 128.0) + 128.0);
  }
}

یک نکته که باید به خاطر بسپارید این است که اگر روشنایی و کنتراست را اعمال کنید، هیچ راه برگشتی به حالت قبلی وجود ندارد چون داده‌های جدید تصویر جایگزین داده‌های قبلی می‌شود. اگر می‌خواهید بعد از اعمال تغییرات دوباره به حالت قبلی برگردید، داده‌های اولیه تصویر باید به صورت جداگانه به عنوان مرجع ذخیره شوند. قابل دسترس قرار دادن متغیرهای تصویر برای توابع دیگر بسیار مفید است چون می‌توانید به جای رسم دوباره canvas با تصویر اولیه از همان تصویر استفاده کنید:

var image = document.getElementById('SourceImage');

function redrawImage() {
  context.drawImage(image, 0, 0);
}

دوره‌های آموزشی در لیداوب:

آموزش پایه لاراول ۵,۵

آموزش CSS

آموزش HTML مقدماتی

 مقالات تخصصی لیداوب در زمینه CSS ،HTML و برنامه نویسی با PHP راهنمای شما در طراحی یک سایت حرفه‌ای است. می‌توانید نظرات و سوالات خودتان را در بخش دیدگاه‌های سایت با ما در میان بگذارید.