我会为您生成一个可直接运行的HTML文档,它利用浏览器原生的Canvas功能,帮助您将彩色图片转换为黑白效果。

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">图片转黑白 · 脚本实现</title>
<style>
* {
box-sizing: border-box;
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}
body {
background: #f4f6f9;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 2rem 1rem;
}
.card {
background: white;
max-width: 800px;
width: 100%;
border-radius: 28px;
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.08);
padding: 2rem 2rem 2.5rem;
transition: 0.2s;
}
h1 {
font-size: 1.9rem;
font-weight: 500;
letter-spacing: -0.3px;
color: #1e293b;
margin-top: 0.2rem;
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 8px;
}
h1 small {
font-size: 1rem;
font-weight: 400;
color: #64748b;
margin-left: 8px;
}
.sub {
color: #475569;
border-left: 4px solid #94a3b8;
padding-left: 14px;
margin: 0.8rem 0 1.8rem 0;
font-size: 0.95rem;
background: #f8fafc;
border-radius: 0 8px 8px 0;
line-height: 1.5;
}
.upload-area {
border: 2px dashed #cbd5e1;
border-radius: 24px;
padding: 2.5rem 1rem;
text-align: center;
background: #fafcff;
transition: all 0.2s;
cursor: pointer;
}
.upload-area:hover {
border-color: #3b82f6;
background: #f0f7ff;
}
.upload-area.dragover {
border-color: #2563eb;
background: #eef2ff;
transform: scale(1.01);
}
.upload-icon {
font-size: 2.8rem;
margin-bottom: 8px;
}
.upload-text {
font-size: 1.1rem;
font-weight: 450;
color: #1e293b;
}
.upload-hint {
font-size: 0.9rem;
color: #64748b;
margin-top: 6px;
}
#fileInput {
display: none;
}
.preview-grid {
display: flex;
flex-wrap: wrap;
gap: 1.8rem;
margin: 2rem 0 1.2rem;
justify-content: center;
}
.img-box {
flex: 1 1 200px;
min-width: 160px;
background: #f1f5f9;
border-radius: 18px;
padding: 12px 12px 16px;
box-shadow: 0 2px 6px rgba(0,0,0,0.02);
transition: 0.1s;
}
.img-box p {
margin: 6px 0 4px 0;
font-weight: 450;
font-size: 0.9rem;
color: #334155;
display: flex;
justify-content: space-between;
}
.img-box img, .img-box canvas {
width: 100%;
height: auto;
border-radius: 12px;
display: block;
background: #ffffff;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.action-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
margin: 1.6rem 0 0.6rem;
gap: 12px;
}
.btn-group {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.btn {
background: #ffffff;
border: 1px solid #d1d9e8;
padding: 0.6rem 1.2rem;
border-radius: 40px;
font-weight: 500;
font-size: 0.9rem;
color: #1e293b;
cursor: pointer;
transition: 0.15s;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 1px 2px rgba(0,0,0,0.02);
}
.btn-primary {
background: #1e293b;
border: 1px solid #1e293b;
color: white;
}
.btn-primary:hover {
background: #0f172a;
border-color: #0f172a;
}
.btn-outline {
border: 1px solid #cbd5e1;
background: white;
}
.btn-outline:hover {
background: #f1f5f9;
}
.btn:active {
transform: scale(0.96);
}
.btn:disabled {
opacity: 0.4;
pointer-events: none;
filter: grayscale(0.3);
}
.slider-box {
display: flex;
align-items: center;
gap: 12px;
background: #f8fafc;
padding: 0.2rem 1rem 0.2rem 1.2rem;
border-radius: 40px;
border: 1px solid #e2e8f0;
}
.slider-box label {
font-size: 0.85rem;
font-weight: 450;
color: #334155;
}
input[type="range"] {
width: 100px;
height: 4px;
-webkit-appearance: none;
background: #cbd5e1;
border-radius: 4px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
border-radius: 50%;
background: #1e293b;
cursor: pointer;
border: 2px solid white;
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
}
.status {
color: #475569;
font-size: 0.9rem;
margin-top: 8px;
min-height: 28px;
padding: 0 4px;
}
.footer-note {
border-top: 1px solid #e9edf2;
margin-top: 1.8rem;
padding-top: 1.2rem;
font-size: 0.8rem;
color: #6b7280;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
@media (max-width: 550px) {
.card { padding: 1.5rem; }
.preview-grid { flex-direction: column; }
.action-bar { flex-direction: column; align-items: stretch; }
.slider-box { justify-content: center; }
}
</style>
</head>
<body>
<div class="card">
<h1>
🎯 图片转黑白
<small>· 浏览器脚本</small>
</h1>
<div class="sub">
⚡ 上传彩色图片,使用 Canvas 像素操作实时转换为黑白 · 可调节灰度强度
</div>
<!-- 上传区域 -->
<div class="upload-area" id="dropZone">
<div class="upload-icon">📸</div>
<div class="upload-text">点击上传 或 拖拽图片到这里</div>
<div class="upload-hint">支持 JPG / PNG / WebP</div>
<input type="file" id="fileInput" accept="image/*">
</div>
<!-- 预览区域 -->
<div class="preview-grid" id="previewContainer">
<div class="img-box" id="originalBox">
<p>🖼️ 原图 <span style="font-weight:400; color:#64748b;" id="originalInfo">—</span></p>
<img id="originalImage" src="" alt="原始图片" style="display:none;">
<canvas id="originalCanvas" style="display:none;"></canvas>
<div style="min-height:120px; display: flex; align-items: center; justify-content: center; color:#94a3b8;" id="placeholderOriginal">
<span>等待上传</span>
</div>
</div>
<div class="img-box" id="bwBox">
<p>⚫ 黑白效果 <span style="font-weight:400; color:#64748b;" id="bwInfo">—</span></p>
<canvas id="bwCanvas" style="display:none; width:100%; height:auto;"></canvas>
<div style="min-height:120px; display: flex; align-items: center; justify-content: center; color:#94a3b8;" id="placeholderBW">
<span>等待转换</span>
</div>
</div>
</div>
<!-- 控制栏 -->
<div class="action-bar">
<div class="btn-group">
<button class="btn btn-primary" id="convertBtn" disabled>✨ 转换为黑白</button>
<button class="btn btn-outline" id="downloadBtn" disabled>⬇ 下载黑白图</button>
</div>
<div class="slider-box">
<label for="strengthSlider">强度</label>
<input type="range" id="strengthSlider" min="0" max="100" value="100">
<span style="font-size:0.8rem; min-width:32px; font-weight:500;" id="strengthValue">100%</span>
</div>
</div>
<div class="status" id="statusMessage">💡 请上传一张图片开始</div>
<div class="footer-note">
<span>🛠 基于 Canvas · 像素级灰度算法</span>
<span>⚙️ 调节「强度」可混合原图色彩</span>
</div>
</div>
<script>
(function() {
// DOM 元素
const fileInput = document.getElementById('fileInput');
const dropZone = document.getElementById('dropZone');
const originalImage = document.getElementById('originalImage');
const originalCanvas = document.getElementById('originalCanvas');
const bwCanvas = document.getElementById('bwCanvas');
const placeholderOriginal = document.getElementById('placeholderOriginal');
const placeholderBW = document.getElementById('placeholderBW');
const convertBtn = document.getElementById('convertBtn');
const downloadBtn = document.getElementById('downloadBtn');
const strengthSlider = document.getElementById('strengthSlider');
const strengthValue = document.getElementById('strengthValue');
const statusMessage = document.getElementById('statusMessage');
const originalInfo = document.getElementById('originalInfo');
const bwInfo = document.getElementById('bwInfo');
// 状态
let currentFile = null; // 当前上传的文件
let imageLoaded = false; // 原图是否已加载到 img
let bwGenerated = false; // 是否已生成黑白图
let bwDataUrl = ''; // 最近生成的黑白 dataURL (用于下载)
// ---------- 辅助: 隐藏占位,显示图片/画布 ----------
function showOriginalElement() {
placeholderOriginal.style.display = 'none';
originalImage.style.display = 'block';
originalCanvas.style.display = 'none'; // 原图用img展示
}
function showOriginalPlaceholder() {
placeholderOriginal.style.display = 'flex';
originalImage.style.display = 'none';
originalCanvas.style.display = 'none';
}
function showBWCanvas() {
placeholderBW.style.display = 'none';
bwCanvas.style.display = 'block';
}
function showBWPlaceholder() {
placeholderBW.style.display = 'flex';
bwCanvas.style.display = 'none';
}
// ---------- 重置状态 (除了文件信息) ----------
function resetStates(keepFile = false) {
if (!keepFile) {
currentFile = null;
imageLoaded = false;
}
bwGenerated = false;
bwDataUrl = '';
convertBtn.disabled = true;
downloadBtn.disabled = true;
// 不重置滑块值
}
// ---------- 加载图片文件 ----------
function loadImageFile(file) {
// 校验类型
if (!file || !file.type.startsWith('image/')) {
statusMessage.textContent = '❌ 请上传有效的图片文件 (jpg/png/webp)';
return;
}
resetStates(true); // 保留 currentFile (下面会覆盖)
currentFile = file;
const reader = new FileReader();
reader.onload = (e) => {
const dataURL = e.target.result;
originalImage.onload = () => {
// 原图加载完成
imageLoaded = true;
// 显示原图
showOriginalElement();
// 更新图像信息
const w = originalImage.naturalWidth;
const h = originalImage.naturalHeight;
originalInfo.textContent = `${w} × ${h}`;
// 重置黑白区域
showBWPlaceholder();
bwInfo.textContent = '—';
bwGenerated = false;
bwDataUrl = '';
convertBtn.disabled = false;
downloadBtn.disabled = true;
statusMessage.textContent = `✅ 已加载: ${file.name} (${w}×${h}) · 点击「转换为黑白」`;
};
originalImage.onerror = () => {
statusMessage.textContent = '⚠️ 图片加载失败,请重试';
showOriginalPlaceholder();
resetStates(false);
};
originalImage.src = dataURL;
};
reader.onerror = () => {
statusMessage.textContent = '⚠️ 文件读取失败';
};
reader.readAsDataURL(file);
}
// ---------- 转换核心: 彩色 -> 黑白 (带强度混合) ----------
function convertToBlackWhite() {
if (!imageLoaded || !originalImage.complete || originalImage.naturalWidth === 0) {
statusMessage.textContent = '⚠️ 原图尚未加载完成,请等待';
return;
}
const img = originalImage;
const w = img.naturalWidth;
const h = img.naturalHeight;
// 设置原画布尺寸 (备用,但不一定显示)
originalCanvas.width = w;
originalCanvas.height = h;
const ctxOrig = originalCanvas.getContext('2d');
ctxOrig.drawImage(img, 0, 0);
// 设置黑白画布
bwCanvas.width = w;
bwCanvas.height = h;
const ctxBw = bwCanvas.getContext('2d');
// 先把原图画到黑白画布上 (作为基础)
ctxBw.drawImage(img, 0, 0);
// 获取像素数据
const imageData = ctxBw.getImageData(0, 0, w, h);
const data = imageData.data;
const strength = parseInt(strengthSlider.value, 10) / 100; // 0 ~ 1
// 如果没有强度 (strength=0) 直接就是原彩,但这种情况一般没必要,但仍处理
if (strength === 0) {
// 什么都不做,就是原图
} else {
// 遍历像素,应用灰度 + 混合
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
// 标准灰度 luminosity 权重
const gray = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
if (strength === 1) {
// 完全黑白
data[i] = gray; // R
data[i + 1] = gray; // G
data[i + 2] = gray; // B
} else {
// 混合: strength 控制黑白比例, (1-strength) 保留原色
const mixR = Math.round(gray * strength + r * (1 - strength));
const mixG = Math.round(gray * strength + g * (1 - strength));
const mixB = Math.round(gray * strength + b * (1 - strength));
data[i] = mixR;
data[i + 1] = mixG;
data[i + 2] = mixB;
}
// alpha 不变
}
}
// 将处理后的数据放回
ctxBw.putImageData(imageData, 0, 0);
// 显示黑白画布
showBWCanvas();
bwInfo.textContent = `${w} × ${h}`;
bwGenerated = true;
bwDataUrl = bwCanvas.toDataURL('image/png');
downloadBtn.disabled = false;
statusMessage.textContent = `🎯 黑白转换完成 (强度: ${strengthSlider.value}%)`;
}
// ---------- 下载黑白图片 ----------
function downloadBW() {
if (!bwGenerated || !bwDataUrl) {
statusMessage.textContent = '⚠️ 还没有可下载的黑白图片,请先转换';
return;
}
const link = document.createElement('a');
link.download = `黑白_${currentFile ? currentFile.name.replace(/\.[^.]+$/, '') : 'image'}.png`;
link.href = bwDataUrl;
link.click();
statusMessage.textContent = `⬇️ 下载已开始 (PNG 格式)`;
}
// ---------- 事件绑定 ----------
// 1. 上传按钮 / 拖拽
dropZone.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', (e) => {
if (e.target.files && e.target.files.length > 0) {
loadImageFile(e.target.files[0]);
}
fileInput.value = ''; // 允许重复选择相同文件
});
// 拖拽事件
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('dragover');
});
dropZone.addEventListener('dragleave', () => {
dropZone.classList.remove('dragover');
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.classList.remove('dragover');
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
loadImageFile(e.dataTransfer.files[0]);
}
});
// 2. 转换按钮
convertBtn.addEventListener('click', convertToBlackWhite);
// 3. 下载按钮
downloadBtn.addEventListener('click', downloadBW);
// 4. 滑块实时更新数值 + 自动重转换 (如果已经生成过黑白)
strengthSlider.addEventListener('input', function() {
strengthValue.textContent = `${this.value}%`;
if (imageLoaded && bwGenerated) {
// 如果已经有黑白图,重新转换以应用新的强度
convertToBlackWhite();
} else if (imageLoaded) {
// 有图但还没转黑白:什么都不做,或者显示提示
// 但为了友好,可以自动转换?这里选择如果图片已加载,点击转换才执行;但滑块不自动转(除非已转换过)
// 更合理:如果图片加载了且没有黑白,不动;但如果图片加载了,显示提示可以转换
if (!bwGenerated) {
statusMessage.textContent = '💡 拖动强度后,点击「转换为黑白」生效';
}
}
});
// 额外: 如果图片加载后用户没按转换,但拖动滑块,显示提示
strengthSlider.addEventListener('mouseup', function() {
if (imageLoaded && !bwGenerated) {
statusMessage.textContent = '👆 点击「转换为黑白」应用当前强度';
}
});
// 5. 快捷键 & 初始化占位
showOriginalPlaceholder();
showBWPlaceholder();
resetStates(false);
statusMessage.textContent = '💡 请上传一张图片开始';
// 如果用户点击原图或黑白占位,不做特殊处理
console.log('🖼 图片黑白转换脚本已启动');
})();
</script>
</body>
</html>
核心功能与操作流程
您可以通过上传图片并调节强度,轻松获得理想的黑白效果,其核心转换逻辑基于像素级的灰度算法,并提供了直观的控制选项。
- 图片上传:您可以通过点击上传区域或直接拖拽图片文件(支持 JPG、PNG、WebP 格式)来加载需要处理的彩色图片。
- 黑白转换与强度调节:点击“转换为黑白”按钮即可应用效果,您还可以通过“强度”滑块,在纯黑白与原图色彩之间进行混合调节,获得丰富的灰度过渡效果。
- 结果预览与下载:页面会并排显示原图与转换后的黑白效果,确认效果后,点击“下载黑白图”按钮即可将结果保存为 PNG 格式的图片。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播