圖片轉字元畫
阿新 • • 發佈:2021-06-13
一個有趣的程式。
主要技術包含圖片拖拽、貼上、雙擊上傳,然後通過canvas獲得圖片每一畫素的rgb顏色值,然後按顏色值總體大小使用相應的字元代替形成字元畫。
原圖:
轉換後:
程式碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>image2char</title> <style> .imageUploader {} .imageUploader .eventContainerDiv {width:100%;height:100px;min-width:300px;min-height:100px;border:3px dashed silver;padding:4px;cursor:default;} .imageUploader .eventContainerDiv img {display:none;overflow-x:auto;} .imageUploader .imageContainerDiv .imageBox {width:200px;height:150px;float:left;margin:4px;border:1px solid #eee;} .imageUploader .imageContainerDiv .imageBox img {max-width:100%;max-height:100%;object-fit: cover;} .imageUploader .imageContainerDiv .imageBox button {height:28px;margin-top:-28px;position: absolute;} .pixel-container {margin:0;padding:0;} .pixel-row {display:flex;} .pixel {width:12px;height:12px;margin:0;padding:0;font-size:12px;font-family:宋體;} </style> </head> <body> <input type="hidden" id="article_link_image" name="article_link_image" value=""/> <div id="imageUploader" class="imageUploader" upload="" maxWidth="400" maxHeight="600" limitCount="1"></div> <div id="imageShow"></div> </body> <script> // 拖拽上傳,相容IE、FireFox、Chrome function dragEventProcess(eventContainerDiv,upload){ document.addEventListener("dragenter", function(e){ eventContainerDiv.style.borderColor = 'gray'; }, false); document.addEventListener("dragleave", function(e){ eventContainerDiv.style.borderColor = 'silver'; }, false); eventContainerDiv.addEventListener("dragenter", function(e){ eventContainerDiv.style.borderColor = 'gray'; eventContainerDiv.style.backgroundColor = 'white'; }, false); eventContainerDiv.addEventListener("dragleave", function(e){ eventContainerDiv.style.backgroundColor = 'transparent'; }, false); eventContainerDiv.addEventListener("dragenter", function(e){ e.stopPropagation(); e.preventDefault(); }, false); eventContainerDiv.addEventListener("dragover", function(e){ e.stopPropagation(); e.preventDefault(); }, false); eventContainerDiv.addEventListener("drop", function(e){ e.stopPropagation(); e.preventDefault(); var imageFile = e.dataTransfer.files[0]; loadImage(imageFile); //submit.disabled = false; }, false); } // 貼上上傳,相容IE、FireFox、Chrome function pasteEventProcess(eventContainerDiv,upload){ eventContainerDiv.addEventListener("paste", function(event){ // console.log(event); // console.log(clipboardData); // chrome、edge、firefox,不管貼上截圖還是網路圖片都能從clipboardData中得到圖片二進位制資料。 if ( event.clipboardData || event.originalEvent ) { var clipboardData = (event.clipboardData || event.originalEvent.clipboardData); if ( clipboardData.items ) { var items = clipboardData.items; for (var i = 0; i < items.length; i++) { // console.log(items[i].type); if (items[i].type.indexOf("image") !== -1) { var imageFile = items[i].getAsFile(); loadImage(imageFile); } } } }else { alert('the browser is not support.'); } }, false); } // 雙擊上傳 function dblclickEventProcess(eventContainerDiv,upload){ eventContainerDiv.addEventListener("dblclick", function(event){ // 觸發上一個元素(input file)的點選事件 eventContainerDiv.previousElementSibling.click(); }); } function clearEventContainerDivImages(eventContainerDiv){ eventContainerDiv.setAttribute("count", "0"); var images = eventContainerDiv.querySelectorAll("img"); for(var i=0;i<images.length;i++){ eventContainerDiv.removeChild(images[i]); } } // 初始化函式 function initialize(){ var imageUploaders = document.querySelectorAll(".imageUploader"); if(imageUploaders && imageUploaders.length > 0){ for(var i=0;i<imageUploaders.length;i++){ var uploader = imageUploaders[i]; // 如果已經初始化過則跳過。 if(uploader.getAttribute("initialized") == "true") continue; var upload = uploader.getAttribute("upload"); var eventContainerDiv = document.createElement("div"); // 往div裡建立一個input file標籤,用於雙擊選擇檔案上傳 var input = document.createElement("input"); input.type = "file"; input.style.display = "none"; input.onchange = function(event){ var evt = window.event || event; var evtsrc = evt.srcElement || evt.target; //console.log(evtsrc.parentNode.id); var imageFile = evtsrc.files[0]; loadImage(imageFile); }; uploader.appendChild(input); // 往div裡建立兩個div,分別作為拖放貼上雙擊容器和圖片上傳後的呈現容器 eventContainerDiv.className = "eventContainerDiv"; eventContainerDiv.contentEditable = true; eventContainerDiv.innerHTML = "請將圖片貼上或拖拽到此區域,或雙擊此區域選擇圖片進行上傳."; // 繫結拖拽事件及處理 dragEventProcess(eventContainerDiv,upload); // 繫結貼上事件及處理 pasteEventProcess(eventContainerDiv,upload); // 繫結雙擊事件及處理 dblclickEventProcess(eventContainerDiv,upload); // 新增到容器裡 uploader.appendChild(eventContainerDiv); var imageContainerDiv = document.createElement("div"); imageContainerDiv.className = "imageContainerDiv"; // 新增到容器裡 uploader.appendChild(imageContainerDiv); uploader.setAttribute("initialized", "true"); } } } window.addEventListener("load",function(){ // 在window下設定一個初始化函式,用於可動態地初始化元件(用js動態建立的元件,需要動態初始化)。 window.powerfulImageUploadInitialize = initialize; powerfulImageUploadInitialize(); },false); function group(array, subGroupLength) { let index = 0; let newArray = []; while(index < array.length) { newArray.push(array.slice(index, index += subGroupLength)); } return newArray; } function loadImage(imageFile) { var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var reader = new FileReader(); reader.readAsDataURL(imageFile); reader.onload = function(e){ // reader onload start var image = new Image(); image.src = e.target.result; image.onload = function(){ // image onload start var img_width = this.width; var img_height = this.height; // 設定畫布尺寸 canvas.width = img_width; canvas.height = img_height; // 將圖片按畫素寫入畫布 context.drawImage(this, 0, 0, img_width, img_height); // 讀取圖片畫素資訊 var imageData = context.getImageData(0, 0, img_width, img_height); var colorRows = group(imageData.data, img_width * 4); // 每4個元素表示一個畫素的rgba。 imageRGB2Char(colorRows); } } } function imageRGB2Char(colorRows) { var html = ''; console.log('colorRows.length:', colorRows.length); for (var x=0; x<colorRows.length; x++) { html += '<div class="pixel-row">'; var cells = colorRows[x]; console.log('cells.length', cells.length); for (var y=0; y<cells.length; y++) { if(y%4 === 0){ // 每四個元素為一個畫素資料 r,g,b,alpha // 這裡只取rgb,不取a var rgb = cells[y] + ',' + cells[y+1] + ',' + cells[y+2]; // html += '<div class="pixel" style="background-color: rgb('+ rgb2char(rgb) +');"></div>'; html += '<div class="pixel" style="color: rgb('+ rgb +');">' + rgb2char(rgb) + '</div>'; } } html += '</div>'; } document.getElementById('imageShow').innerHTML = html; } function rgb2char(rgb) { rgb = eval(rgb.replaceAll(',', '+')); var charr = ''; if (rgb >= 722) { charr = " "; } else if (rgb >= 684 && rgb < 722) { charr = ";;"; } else if (rgb >= 646 && rgb < 684) { charr = "\'\'"; } else if (rgb >= 608 && rgb < 646) { charr = ".."; } else if (rgb >= 570 && rgb < 608) { charr = ",,"; } else if (rgb >= 532 && rgb < 570) { charr = "::"; } else if (rgb >= 494 && rgb < 532) { charr = "tt"; } else if (rgb >= 456 && rgb < 494) { charr = "rr"; } else if (rgb >= 418 && rgb < 456) { charr = "ff"; } else if (rgb >= 380 && rgb < 418) { charr = "kk"; } else if (rgb >= 342 && rgb < 380) { charr = "ZZ"; } else if (rgb >= 304 && rgb < 342) { charr = "FF"; } else if (rgb >= 266 && rgb < 304) { charr = "XX"; } else if (rgb >= 228 && rgb < 266) { charr = "##"; } else if (rgb >= 190 && rgb < 228) { charr = "BB"; } else if (rgb >= 152 && rgb < 190) { charr = "HH"; } else if (rgb >= 114 && rgb < 152) { charr = "WW"; } else if (rgb >= 76 && rgb < 114) { charr = "NN"; } else if (rgb >= 38 && rgb < 76) { charr = "@@"; } else if (rgb >= 0 && rgb < 38) { charr = "MM"; } return charr; } </script> </html>