当前位置: 首页 > news >正文

图片边缘采样

普通采样

 const getEdgeColors = (img) => {const canvas = document.createElement('canvas');const context = canvas.getContext('2d');canvas.width = img.width;canvas.height = img.height;try {context.drawImage(img, 0, 0);// 获取左边缘颜色const leftPixel = context.getImageData(0, Math.floor(img.height / 2), 1, 1).data;const leftColor = `rgb(${leftPixel[0]}, ${leftPixel[1]}, ${leftPixel[2]})`;// 获取右边缘颜色const rightPixel = context.getImageData(img.width - 1, Math.floor(img.height / 2), 1, 1).data;const rightColor = `rgb(${rightPixel[0]}, ${rightPixel[1]}, ${rightPixel[2]})`;console.log('获取图片边缘颜色成功:', leftColor, rightColor);return { leftColor, rightColor };} catch (error) {console.error('获取图片边缘颜色失败:', error);return { leftColor: '#ffffff', rightColor: '#ffffff' };}};

优化:

1)采样多个点而不是只取中间一点,提高颜色准确性;
2)实现边缘区域的平均采样,避免单点采样可能带来的颜色偏差;
3)添加颜色增强处理,使背景色更加美观;
4)优化错误处理机制,确保在各种情况下都能返回合适的颜色值;
5)添加颜色平滑过渡效果,使轮播切换时背景色变化更加自然。

  // 获取图片边缘颜色 - 优化版本const getEdgeColors = (img) => {const canvas = document.createElement('canvas');const context = canvas.getContext('2d');canvas.width = img.width;canvas.height = img.height;try {context.drawImage(img, 0, 0);// 采样点数量和区域大小const samplePoints = 5; // 垂直方向采样点数量const sampleWidth = 10;  // 水平方向采样宽度const sampleHeight = Math.floor(img.height / samplePoints); // 每个采样点的高度间隔// 左边缘颜色采样let leftR = 0, leftG = 0, leftB = 0;for (let i = 0; i < samplePoints; i++) {// 计算当前采样点的垂直位置const y = Math.floor(sampleHeight * (i + 0.5));// 获取左边缘区域的平均颜色const leftData = context.getImageData(0, y, sampleWidth, 1).data;for (let j = 0; j < sampleWidth * 4; j += 4) {leftR += leftData[j];leftG += leftData[j + 1];leftB += leftData[j + 2];}}// 计算左边缘平均颜色leftR = Math.floor(leftR / (samplePoints * sampleWidth));leftG = Math.floor(leftG / (samplePoints * sampleWidth));leftB = Math.floor(leftB / (samplePoints * sampleWidth));// 右边缘颜色采样let rightR = 0, rightG = 0, rightB = 0;for (let i = 0; i < samplePoints; i++) {// 计算当前采样点的垂直位置const y = Math.floor(sampleHeight * (i + 0.5));// 获取右边缘区域的平均颜色const rightData = context.getImageData(img.width - sampleWidth, y, sampleWidth, 1).data;for (let j = 0; j < sampleWidth * 4; j += 4) {rightR += rightData[j];rightG += rightData[j + 1];rightB += rightData[j + 2];}}// 计算右边缘平均颜色rightR = Math.floor(rightR / (samplePoints * sampleWidth));rightG = Math.floor(rightG / (samplePoints * sampleWidth));rightB = Math.floor(rightB / (samplePoints * sampleWidth));// 颜色增强处理 - 适当提高饱和度const enhanceColor = (r, g, b) => {// 计算亮度const brightness = (r + g + b) / 3;// 如果颜色太暗或太亮,适当调整if (brightness < 30) {// 提亮暗色return {r: Math.min(255, r + 30),g: Math.min(255, g + 30),b: Math.min(255, b + 30)};} else if (brightness > 220) {// 降低过亮的颜色return {r: Math.max(0, r - 20),g: Math.max(0, g - 20),b: Math.max(0, b - 20)};} else {// 适当提高饱和度const max = Math.max(r, g, b);const min = Math.min(r, g, b);const delta = max - min;if (delta > 10) { // 有一定色差才增强饱和度const saturationFactor = 1.2;const newR = r + (r - brightness) * saturationFactor;const newG = g + (g - brightness) * saturationFactor;const newB = b + (b - brightness) * saturationFactor;return {r: Math.min(255, Math.max(0, Math.round(newR))),g: Math.min(255, Math.max(0, Math.round(newG))),b: Math.min(255, Math.max(0, Math.round(newB)))};}return { r, g, b };}};// 应用颜色增强const enhancedLeft = enhanceColor(leftR, leftG, leftB);const enhancedRight = enhanceColor(rightR, rightG, rightB);// 生成最终颜色const leftColor = `rgb(${enhancedLeft.r}, ${enhancedLeft.g}, ${enhancedLeft.b})`;const rightColor = `rgb(${enhancedRight.r}, ${enhancedRight.g}, ${enhancedRight.b})`;console.log('获取图片边缘颜色成功:', leftColor, rightColor);return { leftColor, rightColor };} catch (error) {console.error('获取图片边缘颜色失败:', error);// 返回一个柔和的默认颜色,而不是纯白色return { leftColor: '#f5f5f5', rightColor: '#f5f5f5' };}};

采用切片的方案进行循环填充

// 创建边缘切片的canvas
export const createEdgeSlice = (img: HTMLImageElement, isLeft: boolean): string => {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');const sliceWidth = 1; // 切片宽度canvas.width = sliceWidth;canvas.height = img.height;if (isLeft) {if (ctx) {ctx.drawImage(img, 0, 0, sliceWidth, img.height, 0, 0, sliceWidth, img.height);} else {// 如果ctx为null则抛出错误throw new Error('无法获取canvas上下文');}} else {if (ctx) {ctx.drawImage(img, img.width - sliceWidth, 0, sliceWidth, img.height, 0, 0, sliceWidth, img.height);} else {// 如果ctx为null则抛出错误throw new Error('无法获取canvas上下文');}}console.log('获取到了边缘切片 base64')return canvas.toDataURL();
};

采样某个点进行渐变

export const getEdgeColors = (img) => {const canvas = document.createElement('canvas');const context = canvas.getContext('2d');canvas.width = img.width;canvas.height = img.height;try {// 检查 context 是否为 nullif (!context) {throw new Error('无法获取 canvas context');}context.drawImage(img, 0, 0);// 获取顶部中间位置的左右边缘颜色const middleX = Math.floor(img.width / 2);// 使用中间点位即可const middlePixel = context.getImageData(middleX, 0, 1, 1).data;// const leftPixel = context.getImageData(0, 0, 1, 1).data;// const rightPixel = context.getImageData(img.width - 1, 0, 1, 1).data;const leftPixel = middlePixel;const rightPixel = middlePixel;// 创建渐变色字符串const createGradient = (color, direction) => {const [r, g, b] = color;// direction: 渐变方向,可以是'right'或'left'// r,g,b: RGB颜色值// 渐变包含6个颜色节点:// 1. 0%位置: 完全不透明的原始颜色// 2. 20%位置: 85%透明度// 3. 40%位置: 60%透明度// 4. 60%位置: 35%透明度// 5. 80%位置: 15%透明度// 6. 100%位置: 完全透明return `linear-gradient(to ${direction}, rgb(${r}, ${g}, ${b}) 0%, rgba(${r}, ${g}, ${b}, 0.85) 20%, rgba(${r}, ${g}, ${b}, 0.6) 40%, rgba(${r}, ${g}, ${b}, 0.35) 60%, rgba(${r}, ${g}, ${b}, 0.15) 80%, rgba(${r}, ${g}, ${b}, 0) 100%)`;};const leftColor = createGradient([leftPixel[0], leftPixel[1], leftPixel[2]], 'right');const rightColor = createGradient([rightPixel[0], rightPixel[1], rightPixel[2]], 'left');console.log('获取图片边缘渐变颜色成功:', leftColor, rightColor);return { leftColor, rightColor };} catch (error) {console.error('获取图片边缘颜色失败:', error);// 返回柔和的默认渐变颜色const defaultColor = [245, 245, 245]; // #f5f5f5return {leftColor: `linear-gradient(to right, rgb(${defaultColor.join(',')}) 0%, rgba(${defaultColor.join(',')}, 0) 100%)`,rightColor: `linear-gradient(to left, rgb(${defaultColor.join(',')}) 0%, rgba(${defaultColor.join(',')}, 0) 100%)`};}
};

http://www.mrgr.cn/news/96804.html

相关文章:

  • dubbo http流量接入dubbo后端服务
  • Android学习之计算器app(java + 详细注释 + 源码)
  • 在Windows下使用Docker部署Nacos注册中心(基于MySQL容器)
  • 华为交换综合实验——VRRP、MSTP、Eth-trunk、NAT、DHCP等技术应用
  • MySQL数据库学习笔记1.SQL(1)
  • 使用 GitHub Pages 快速部署静态网页
  • Mysql之事务(下)
  • Linux安装Ubuntu24.04系统 并安装配置Nvidia 4090 显卡驱动
  • 论文阅读笔记:Denoising Diffusion Implicit Models (2)
  • STM32_HAL之程序编写、编译、烧写、上板测试初体验
  • 使用SpringBoot + Thymeleaf + iText实现动态PDF导出
  • git 按行切割 csv文件
  • echarts+HTML 绘制3d地图,加载散点+散点点击事件
  • C#:第一性原理拆解属性(property)
  • Anaconda和Pycharm的区别,以及如何选择两者
  • k8s 1.30 安装ingress-nginx
  • 为什么 Three.js 里 Cannon.js 物体堆叠时会有空隙?
  • 【C语言】深入理解指针(三):C语言中的高级指针应用
  • Prompt攻击是什么
  • Anolis系统下安装Jenkins