91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解使用JS如何制作簡單的ASCII圖與單極圖

發布時間:2020-08-23 06:36:59 來源:腳本之家 閱讀:153 作者:daisy 欄目:web開發

ASCII圖

在終端執行各種命令的時候經常會看到一些終端里顯示出來的"圖片",遠看仿佛一張圖,近看則是一個個的 ASCII碼,它們 大致長這樣子

詳解使用JS如何制作簡單的ASCII圖與單極圖

而今天我們要做的則是用JS把一張給定的圖片轉換成這種用ASCII字符組成的“ASCII圖” 先看看最終效果,假設我們給定的圖片是這樣子的,

詳解使用JS如何制作簡單的ASCII圖與單極圖

這是代碼處理后的結果,用了 I'mYasic 這8個字符來表示,還是可以分辨出大致的輪廓的。

詳解使用JS如何制作簡單的ASCII圖與單極圖

單級圖

而另一種圖則是單極圖,也就是黑白圖片,還是剛剛那張圖片,輸出如下

詳解使用JS如何制作簡單的ASCII圖與單極圖

基礎知識

這兩種圖都是比較簡單的,只需要以下知識即可

  • HTML5中的Canvas
  • 像素的RGB值
  • JS中的Canvas相關API

制作ASCII圖

一般來說,在計算機當中,我們看到的大多數圖片都是由一個個像素點構成的,每一個像素點則由 RGBA 構成,在 css 中我們時常用的 rgba(255, 255, 255, 255, 0)就是一組RGBA值, 也即是RGB三原色和Alpha透明度。當然一張圖片不是僅僅包含所有像素點數據的,還包括一些描述信息,也稱為圖片的 profile,這一部分小則幾KB,多則幾百KB,是圖片壓縮中經常被處理的部分。

那么對于圖片中每一個像素點來說,只要我們改變了其相應的RGBA的值,最終的圖片也就變了樣子。而修改哪些像素點、修改成什么樣的RGBA,則決定著最終的圖片風格,這也是許多濾鏡采用的機制。

基于以上的理論知識,我們的ASCII圖制作思路也就有了。ASCII圖其實就是將一張圖中的一個像素點,通過計算其RGBA的值,劃分成給定的幾個量化值,在這里由于我們用的 I'mYasic 這8個字符來表示,所以要分成8組值,每一組用一個ASCII字符來表示,最終就能組成一幅完整的ASCII圖片。

接下來就是具體的代碼實現。

獲取圖片的像素信息

通過 Canvas API 中的 getImageData() 方法我們可以獲得一個對象,這個對象的屬性里包含一個一維數組 data,這個一維數組每4個元素為一組,代表了一個 canvas 中指定范圍的全部像素信息,并且依次是 RED,GREEN,BLUE,ALPHA。因此我們可以先把圖片放進 canvas 中,再調用這個方法拿到像素。

不過我很疑惑為什么 data 是一個一維數組,通常處理的圖片都是二維圖片,如果用二維數組來表示像素信息,代碼讀取和處理會方便很多,也更容易理解。甚至可以用一個三維數組,專門用一個維度來放置RGBA信息。

獲取圖片像素信息的代碼如下所示

var canvasContext = canvas.getContext("2d");
canvasContext.drawImage(sourceImg, 0, 0);
var imgData = canvasContext.getImageData(0 , 0, sourceImg.width, sourceImg.height);
var imgDataArray = imgData.data;

那么對于某一個像素點的RGBA值就可以這樣獲取

var r = imgDataArray[lineIndex];
var g = imgDataArray[lineIndex + 1];
var b = imgDataArray[lineIndex + 2];
var a = imgDataArray[lineIndex + 3];

其中 lineIndex 是遍歷每一個像素點的基準變量。

圖片灰度化

灰度化,也就是獲取像素點的灰度值。由于每一個像素點包含著RGBA四種信息,而我們需要將所有像素點的RGBA值分成8組,因此需要統一一下RGBA的值,最終得到一個值Y,而相應的像素點的RGBA值滿足 Y = R = G = B ,在這里我們不考慮透明度 Alpha。由于RGB的值相等像素點顏色是介于白色與黑色之間的灰色,所以這一過程也稱為灰度化。

灰度化算法有很多種,我們在這里采取最簡單的方式,即

Y = (R + G + B) * 1/3

相應代碼如下

function rgb2gray(r, g, b) {
 return r * 0.333 + g * 0.333 + b * 0.333;
}

灰度圖量化

灰度化以后的圖片大致長這樣子,可以看到色彩已經都變成灰色了。

詳解使用JS如何制作簡單的ASCII圖與單極圖

那么接下來就是關鍵的“量化”過程。也就是說,我們要讓把這些不同灰度的值分成8組,并且每一組都賦予一個ASCII字符作為標示,當然選取的ASCII字符也要有一定規律,簡單來說就是顏色由深到淺相應的字符由繁到簡。而量化過程就是將0-255范圍等分成8個區間,依次判斷灰度值在哪一個區間內,代碼如下。

由于圖像像素數目巨大,為了效率,判決時可以采取“二分判決”法提高判決速度。

function gray2asc(gray) {
 /*ASCII--I'mYasic*/
 /*32 64 96 128 160 192 224 256*/
 gray = 255 - gray;
 if (gray < 128){
  if (gray < 64){
   if (gray < 32){
    return '\''
   }
   else {
    return 'c'
   }
  }
  else {
   if (gray < 96){
    return 'i'
   }
   else {
    return 's'
   }
  }
 }
 else {
  if (gray < 192){
   if (gray < 160){
    return 'I'
   }
   else {
    return 'm'
   }
  }
  else {
   if (gray < 224){
    return 'a'
   }
   else {
    return 'Y'
   }
  }
 }
}

遍歷與顯示

上面大概講解完了對于一個像素點變換為ASCII碼的過程,接下來就是遍歷和顯示了。

遍歷

遍歷全部像素點并變換為ASCII碼基本是不可能的,因為圖片稍微大一些計算量就增長很多,所以我們折中一下,對于像素陣列的行與列都進行等間隔采樣,最終展示出來的圖片分辨率會隨著采樣間隔減小而增強。另外要注意 data 數組是一維數組,并且每4個元素為一組RGBA數據。相應代碼如下

 var result = "";
 var lineIndex = 0;
 for (var lineHeight = 0; lineHeight < sourceImg.height; lineHeight += 12){
  var lineASC = "";
  for (var lineFlag = 0; lineFlag < sourceImg.width; lineFlag += 5){
   lineIndex = (lineHeight * sourceImg.width + lineFlag) * 4;
   var r = imgDataArray[lineIndex];
   var g = imgDataArray[lineIndex + 1];
   var b = imgDataArray[lineIndex + 2];
   lineASC += gray2asc(rgb2gray(r, g, b));
  }
  lineASC += '\n';
  result += lineASC;
 }

顯示

最終獲得的 result 字符串就是需要展示的ASCII碼。但是必須注意,如果直接展示到頁面上會因為每一個字符的字符寬度不一樣而導致ASCII圖“失真”,這里我們可以采用 Monospace 字體來確保字符寬度一致。

制作單極圖

其實看完上面部分,就應該知道單極圖非常好實現,同樣需要獲取像素信息并灰度化,只是量化時直接量化為 rgb(0, 0, 0) 和 rgb(255, 255, 255) 兩種顏色就可以。

 var canvasContext = targetCanvas.getContext("2d");
 canvasContext.drawImage(sourceImg, 0, 0);
 var imgData = canvasContext.getImageData(0 , 0, sourceImg.width, sourceImg.height);
 var imgDataArray = imgData.data;
 for (var index = 0; index <= sourceImg.width * sourceImg.height * 4; index += 4){
  var red = imgDataArray[index];
  var green = imgDataArray[index + 1];
  var blue = imgDataArray[index + 2];
  var gray = rgb2gray(red, green, blue);
  if (gray < 128){
   imgData.data[index] = 0;
   imgData.data[index + 1] = 0;
   imgData.data[index + 2] = 0;
  }
  else {
   imgData.data[index] = 255;
   imgData.data[index + 1] = 255;
   imgData.data[index + 2] = 255;
  }
 }
 canvasContext.putImageData(imgData, 0, 0);

別忘了最后要用 putImageData 方法將修改后的像素信息放回 canvas 中進行顯示。

ASCII圖完整代碼

function rgb2gray(r, g, b) {
 return r * 0.333 + g * 0.333 + b * 0.333;
}

function gray2asc(gray) {
 /*ASCII--I'mYasic*/
 /*32 64 96 128 160 192 224 256*/
 gray = 255 - gray;
 if (gray < 128){
  if (gray < 64){
   if (gray < 32){
    return '\''
   }
   else {
    return 'c'
   }
  }
  else {
   if (gray < 96){
    return 'i'
   }
   else {
    return 's'
   }
  }
 }
 else {
  if (gray < 192){
   if (gray < 160){
    return 'I'
   }
   else {
    return 'm'
   }
  }
  else {
   if (gray < 224){
    return 'a'
   }
   else {
    return 'Y'
   }
  }
 }
}

var img2ASC = function (canvas, sourceImg) {
 console.log(sourceImg.width + " " + sourceImg.height);

 var canvasContext = canvas.getContext("2d");
 canvasContext.drawImage(sourceImg, 0, 0);
 var imgData = canvasContext.getImageData(0 , 0, sourceImg.width, sourceImg.height);
 var imgDataArray = imgData.data;
 var result = "";
 var lineIndex = 0;
 for (var lineHeight = 0; lineHeight < sourceImg.height; lineHeight += 12){
  var lineASC = "";
  for (var lineFlag = 0; lineFlag < sourceImg.width; lineFlag += 5){
   lineIndex = (lineHeight * sourceImg.width + lineFlag) * 4;
   var r = imgDataArray[lineIndex];
   var g = imgDataArray[lineIndex + 1];
   var b = imgDataArray[lineIndex + 2];
   lineASC += gray2asc(rgb2gray(r, g, b));
  }
  lineASC += '\n';
  result += lineASC;
 }
 document.getElementById("result").innerHTML = result;
};

單極圖完整代碼

function rgb2gray(r, g, b) {
 return r * 0.333 + g * 0.333 + b * 0.333;
}

function gray2asc(gray) {
 /*ASCII--I'mYasic*/
 /*32 64 96 128 160 192 224 256*/
 if (gray < 128){
  if (gray < 64){
   if (gray < 32){
    return '\''
   }
   else {
    return 'c'
   }
  }
  else {
   if (gray < 96){
    return 'i'
   }
   else {
    return 's'
   }
  }
 }
 else {
  if (gray < 192){
   if (gray < 160){
    return 'I'
   }
   else {
    return 'm'
   }
  }
  else {
   if (gray < 224){
    return 'a'
   }
   else {
    return 'Y'
   }
  }
 }
}

var monoImg = function (targetCanvas, sourceImg) {
 targetCanvas.width = sourceImg.width;
 targetCanvas.height = sourceImg.height;
 var canvasContext = targetCanvas.getContext("2d");
 canvasContext.drawImage(sourceImg, 0, 0);
 var imgData = canvasContext.getImageData(0 , 0, sourceImg.width, sourceImg.height);
 var imgDataArray = imgData.data;
 for (var index = 0; index <= sourceImg.width * sourceImg.height * 4; index += 4){
  var red = imgDataArray[index];
  var green = imgDataArray[index + 1];
  var blue = imgDataArray[index + 2];
  var gray = rgb2gray(red, green, blue);
  if (gray < 128){
   imgData.data[index] = 0;
   imgData.data[index + 1] = 0;
   imgData.data[index + 2] = 0;
  }
  else {
   imgData.data[index] = 255;
   imgData.data[index + 1] = 255;
   imgData.data[index + 2] = 255;
  }
 }
 canvasContext.putImageData(imgData, 0, 0);
};

總結

這一篇博客主要講了利用JS中的 Canvas API 進行一些簡單的像素化操作,但其實還有很多地方可以繼續改進。比如一般單極圖出來后很多地方會有噪點,也就是一些礙眼的白點和黑點,可以通過一些方式“去掉噪點”,就留在以后寫吧!以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武鸣县| 浙江省| 惠安县| 昭通市| 定结县| 赤水市| 永胜县| 长寿区| 新安县| 金平| 南部县| 土默特右旗| 息烽县| 临安市| 仲巴县| 赤城县| 福清市| 安多县| 于田县| 军事| 宁河县| 沽源县| 盐山县| 苏尼特右旗| 临湘市| 许昌市| 云梦县| 贵溪市| 科技| 垫江县| 鄄城县| 西城区| 陇西县| 江永县| 临泉县| 沽源县| 武城县| 固原市| 丰顺县| 教育| 阿拉善盟|