js+css实现图片转成ASCII码艺术效果代码

代码语言:html

所属分类:其他

代码描述:js+css实现图片转成ASCII码艺术效果代码

代码标签: js css 图片 ASCII 艺术

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
 
<meta charset="UTF-8">
 
 
 
<style>
body
{
 
margin: 0;
 
font-family: system-ui, sans-serif;
 
background-color: #000; /* Dark theme by default */
 
color: #eee;
}

.layout {
 
display: flex;
 
height: 100vh;
}

/* Increase sidebar width to fit labels and numeric values */
.sidebar {
 
width: 380px;
 
flex-shrink: 0;
 
background: #111; /* Matches dark theme */
 
color: #eee;
 
padding: 20px;
 
box-sizing: border-box;
 
overflow-y: auto;
 
position: fixed;
 
top: 0;
 
bottom: 0;
 
left: 0;
}

.sidebar h3 {
 
margin: 10px 0;
 
font-size: 1.1rem;
}

.control-group {
 
margin-bottom: 20px;
 
border-bottom: 1px solid #666;
 
padding-bottom: 10px;
}

.control-group:last-of-type {
 
border-bottom: none;
}

.control {
 
display: flex;
 
align-items: center;
 
margin: 8px 0;
}

.control label {
 
flex: 0 0 150px;
 
margin-right: 10px;
 
font-size: 0.9rem;
 
white-space: nowrap;
}

.control input[type="range"],
.control select,
.control input[type="text"] {
 
flex: 1;
}

.value-label {
 
display: inline-block;
 
width: 40px;
 
text-align: center;
 
margin-left: 8px;
 
font-size: 0.9rem;
}

.main-content {
 
flex: 1;
 
margin-left: 380px;
 
padding: 20px;
 
overflow-y: auto;
 
background: #000;
 
color: #eee;
 
box-sizing: border-box;
}

#ascii-art {
 
background: #000;
 
padding: 10px;
 
white-space: pre;
 
font-family: Consolas, Monaco, "Liberation Mono", monospace;
 
font-size: 7px;
 
line-height: 7px;
}

button
{
 
margin-right: 10px;
 
padding: 5px 10px;
}

body
.light-mode {
 
background-color: #fff;
 
color: #000;
}

body
.light-mode .sidebar {
 
background: #F4F4F4;
 
color: #000;
}

body
.light-mode .main-content {
 
background: #fff;
 
color: #000;
}

body
.light-mode #ascii-art {
 
background: #fff;
}
</style>


 
 
</head>

<body translate="no">
 
<div class="layout">
 
<aside class="sidebar">
   
<section class="control-group global-settings">
     
<h3>Global Settings</h3>
     
<div class="control">
       
<label for="theme">Theme:</label>
       
<select id="theme">
         
<option value="dark" selected>Dark</option>
         
<option value="light">Light</option>
       
</select>
     
</div>
     
<div class="control">
       
<label for="ignoreWhite">Ignore Pure White:</label>
       
<input type="checkbox" id="ignoreWhite" checked>
     
</div>
   
</section>
   
   
<section class="control-group upload-group">
     
<h3>1. Upload Your File</h3>
     
<div class="control">
       
<input type="file" id="upload" accept="image/*">
     
</div>
   
</section>
   
   
<section class="control-group image-processing">
     
<h3>2. Basic Adjustments</h3>
     
<div class="control">
       
<label for="asciiWidth">Output Width (chars):</label>
       
<input type="range" id="asciiWidth" min="20" max="300" value="150">
       
<span class="value-label" id="asciiWidthVal">100</span>
     
</div>
     
<div class="control">
       
<label for="brightness">Brightness:</label>
       
<input type="range" id="brightness" min="-100" max="100" value="0">
       
<span class="value-label" id="brightnessVal">0</span>
     
</div>
     
<div class="control">
       
<label for="contrast">Contrast:</label>
       
<input type="range" id="contrast" min="-100" max="100" value="0">
       
<span class="value-label" id="contrastVal">0</span>
     
</div>
     
<div class="control">
       
<label for="blur">Blur (px):</label>
       
<input type="range" id="blur" min="0" max="10" step="0.01" value="0">
       
<span class="value-label" id="blurVal">0</span>
     
</div>
     
<div class="control">
       
<label for="invert">Invert Colors:</label>
       
<input type="checkbox" id="invert">
     
</div>
   
</section>
   
   
<section class="control-group dithering-settings">
     
<h3>3. Dithering Options</h3>
     
<div class="control">
       
<label for="dithering">Enable Dithering:</label>
       
<input type="checkbox" id="dithering" checked>
     
</div>
     
<div class="control">
       
<label for="ditherAlgorithm">Dither Algorithm:</label>
       
<select id="ditherAlgorithm">
         
<option value="floyd" selected>Floyd–Steinberg</option>
         
<option value="atkinson">Atkinson</option>
         
<option value="noise">Noise</option>
         
<option value="ordered">Ordered</option>
       
</select>
     
</div>
   
</section>
   
   
<section class="control-group charset-settings">
     
<h3>4. Character Set</h3>
     
<div class="control">
       
<label for="charset">Select Set:</label>
       
<select id="charset">
         
<option value="detailed" selected>Detailed</option>
         
<option value="standard">Standard</option>
         
<option value="blocks">Blocks</option>
         
<option value="binary">Binary</option>
         
<option value="hex">Hex</option>
         
<option value="manual">Manual</option>
       
</select>
     
</div>
     
<div class="control" id="manualCharControl" style="display: none;">
       
<label for="manualCharInput">Manual Character:</label>
       
<input type="text" id="manualCharInput" maxlength="1" value="0">
     
</div>
   
</section>
   
   
<section class="control-group edge-detection-settings">
     
<h3>5. Edge Detection</h3>
     
<p>Select one edge detection method:</p>
     
<div class="control">
       
<input type="radio" name="edgeMethod" id="edgeNone" value="none" checked>
       
<label for="edgeNone">No Edge Detection</label>
     
</div>
     
<div class="control">
       
<input type="radio" name="edgeMethod" id="edgeSobel" value="sobel">
       
<label for="edgeSobel">Sobel Edge Detection</label>
     
</div>
     
<div class="control">
       
<input type="radio" name="edgeMethod" id="edgeDoG" value="dog">
       
<label for="edgeDoG">DoG (Contour) Detection</label>
     
</div>
     
<div class="control" id="sobelThresholdControl" style="display: none;">
       
<label for="edgeThreshold">Sobel Threshold:</label>
       
<input type="range" id="edgeThreshold" min="0" max="255" value="100">
       
<span class="value-label" id="edgeThresholdVal">100</span>
     
</div>
     
<div class="control" id="dogThresholdControl" style="display: none;">
       
<label for="dogEdgeThreshold">DoG Threshold:</label>
       
<input type="range" id="dogEdgeThreshold" min="0" max="255" value="100">
       
<span class="value-label" id="dogEdgeThresholdVal">100</span>
     
</div>
   
</section>
   
   
<section class="control-group display-settings">
     
<h3>6. Display Settings</h3>
     
<div class="control">
       
<label for="zoom">Zoom (%):</label>
       
<input type="range" id="zoom" min="20" max="600" value="100">
       
<span class="value-label" id="zoomVal">100</span>
     
</div>
   
</section>
   
   
<section class="control-group misc-settings">
     
<div class="control">
       
<button id="reset">Reset All Settings</button>
     
</div>
   
</section>
 
</aside>
 
 
<main class="main-content">
   
<pre id="ascii-art"></pre>
   
<button id="copyBtn">Copy ASCII Art</button>
   
<button id="downloadBtn">Download PNG</button>
 
</main>
</div>
<canvas id="canvas" style="display: none;"></canvas>
 
     
<script >
// ---------------- Global Variables ----------------
let currentImage = null;
const baseFontSize = 7; // Base font size for ASCII art

// ---------------- Helper Functions ----------------

// Clamp a value between min and max.
function clamp(value, min, max) {
  return Math.max(min, Math.min(max, value));
}

// Generate a normalized 2D Gaussian kernel.
function gaussianKernel2D(sigma, kernelSize) {
  const kernel = [];
  const half = Math.floor(kernelSize / 2);
  let sum = 0;
  for (let y = -half; y <= half; y++) {
    const row = [];
    for (let x = -half; x <= half; x++) {
      const value = Math.exp(-(x * x + y * y) / (2 * sigma * sigma));
      row.push(value);
      sum += value;
    }
    kernel.push(row);
  }
  // Normalize the kernel.
  for (let y = 0; y < kernelSize; y++) {
    for (let x = 0; x < kernelSize; x++) {
      kernel[y][x] /= sum;
    }
  }
  return kernel;
}

// Convolve a 2D image (array) with a 2D kernel.
function convolve2D(img, kernel) {
  const height = img.length,
        width = img[0].length;
  const kernelSize = kernel.length,
        half = Math.floor(kernelSize / 2);
  const output = [];
  for (let y = 0; y < height; y++) {
    output[y] = [];
    for (let x = 0; x < width; x++) {
      let sum = 0;
      for (let ky = 0; ky < kernelSize; ky++) {
        for (let kx = 0; kx < kernelSize; kx++) {
          const yy = y + ky - half;
          const xx = x + kx - half;
          let pixel = (yy >= 0 && yy < height && xx >= 0 && xx < width) ? img[yy][xx] : 0;
          sum += pixel * kernel[ky][kx];
        }
      }
      output[y][x] = sum;
    }
  }
  return output;
}

// Compute the Difference of Gaussians on a 2D grayscale image.
function differenceOfGaussians2D(gray, sigma1, sigma2, kernelSize) {
  const kernel1 = gaussianKernel2D(sigma1, kernelSize);
  const kernel2 = gaussianKernel2D(sigma2, kernelSize);
  const blurred1 = convolve2D(gray, kernel1);
  const blurred2 = convolve2D(gray, kernel2);
  const height = gray.length,
        width = gray[0].length;
  const dog = [];
  for (let y = 0; y < height; y++) {
    dog[y] = [];
    for (let x = 0; x < width; x++) {
      dog[y][x] = blurred1[y][x] - blurred2[y][x];
    }
  }
  return dog;
}

// Apply the Sobel operator to a 2D image, returning gradient magni.........完整代码请登录后点击上方下载按钮下载查看

网友评论0