Image Test
<html> <head> <link href="https://1119s.wdfiles.com/local--code/image-test/2" rel="stylesheet"> </head> <body> <div class="form"> <input type="file" id="select_file" accept=".png,.jpg,.jpeg"> <div> 不透明度の低い画素を完全に透明にする <select name="min_opacity" id="min_opacity"> <option value="0" selected>なし</option> <option value="8">8未満 (超弱)</option> <option value="16">16未満 (弱)</option> <option value="32">32未満 (中)</option> <option value="48">48未満 (強)</option> <!--<option value="-1">カスタム</option>--> </select> </div> </div> <div class="viewer"> <div class="canvas-wrapper"> <canvas id="canvas_in" width="400"></canvas> <canvas id="canvas_out" width="400"></canvas> </div> <div class="buttons"> <div class="btn-container"> <button id="convert" disabled>変換</button> </div> <div class="btn-container"> <button id="download" disabled>保存</button> </div> </div> </div> <script type="text/javascript" src="https://1119s.wdfiles.com/local--code/image-test/3"></script> </body> </html>
body { background: #f4f4f4; margin: 1em; } .viewer { background: #fff; border: solid 1px #ccc; border-radius: 12px; margin: 1em 1em; padding: 1em 1em; container: viewer / inline-size; } .canvas-wrapper { display: flex; flex-wrap: wrap; justify-content: space-evenly; gap: 1em 1em; canvas { background: white; } } .buttons { display: flex; justify-content: space-evenly; gap: 1em; margin: 2em 0 1em; .btn-container { width: 400px; text-align: center; @container viewer (width < calc(800px + 1em)) { display: contents; } } button { display: inline-block; border: none; border-radius: 5px; background: #4090ff; color: #f8f8f8; font-size: 1.2em; width: 4em; padding: 0.25em; cursor: pointer; &:hover { color: #ccccff; } &[disabled] { background: #ccc; color: #555; cursor: not-allowed; } } }
const sel_file = document.getElementById("select_file"); const min_opa = document.getElementById("min_opacity"); const canvas_in = document.getElementById("canvas_in"); const canvas_out = document.getElementById("canvas_out"); const ctx_in = canvas_in.getContext("2d"); const ctx_out = canvas_out.getContext("2d"); const btn_conv = document.getElementById("convert"); const btn_dl = document.getElementById("download"); sel_file.addEventListener("change", (e) => { btn_conv.disabled = false; btn_dl.disabled = true; var file = e.target.files[0]; var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { var dataUrl = reader.result; var img = new Image(); img.src = dataUrl; img.onload = () => { var canvas_new_height = canvas_in.width * img.naturalHeight / img.naturalWidth; // / canvas_in.height = canvas_out.height = canvas_new_height; ctx_in.drawImage(img, 0, 0, canvas_in.width, canvas_in.height); } } }, false); btn_conv.onclick = () => { var imageData = ctx_in.getImageData(0, 0, canvas_in.width, canvas_in.height); var data = imageData.data; var min = parseInt(min_opa.value); for (let i = 0; i < data.length; i += 4) { var value = Math.max(data[i], data[i+1], data[i+2]); for (let j = 0; j < 3; j++) { data[i+j] *= 255 / value; // / } if (min == 0 || value >= min + 32) { data[i+3] = value; } else if (value >= min) { data[i+3] = Math.round((value - min) * (min + 32) / 32); // / } else { data[i+3] = 0; } } imageData.data = data; ctx_out.putImageData(imageData, 0, 0, 0, 0, canvas_out.width, canvas_out.height); btn_dl.disabled = false; }; // https://qiita.com/kitasenjudesign/items/70896c91ee2492fd7449 // https://stackoverflow.com/questions/72615770/store-canvas-screenshot-to-local-filesystem-with-filesystem-api btn_dl.onclick = () => { canvas_out.toBlob(async function(result) { const options = { types: [ { description: 'Images', accept: { 'image/png': ['.png'] }, }, ], suggestedName: 'download.png', }; imgFileHandle = await window.showSaveFilePicker(options); const writable = await imgFileHandle.createWritable(); await writable.write(result); await writable.close(); }); };
ページリビジョン: 30, 最終更新: 10 Dec 2024 07:17





