颜色混合算法

<!-- /** 
* @fileOverview 接口文档填写
* 
* @module 
* @author 黄尧(355350) 
* @version 1.0.0 
* @description: 
* 
*/ -->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1.0" />
    <title></title>
    <script src="./modules/vue.min.js"></script>
    <link rel="stylesheet" href="./modules/element-ui.css" />
    <script src="./modules/element-ui.js"></script>
    <script src="./node_modules/sortablejs/Sortable.min.js"></script>
    <script src="./node_modules/vuedraggable/dist/vuedraggable.umd.min.js"></script>
    <style>
      body {
        margin: 0;
      }
      #app {
        width: 100vw;
        height: 100vh;
      }
      .canvas-box {
        background-color: aquamarine;
      }
      .color-card {
        width: 1500px;
        display: flex;
        flex-wrap: wrap;
      }
      .color-item {
        width: 32px;
        height: 32px;
        border-radius: 50%;
      }
    </style>
  </head>

  <body>
    <div id="app">
      <el-row>
        <el-col :span="1">
          <el-upload accept="image/png, image/jpeg" action="null" :limit="1" :on-change="onChange">
            <el-button size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-col>
        <el-col :span="canvasWidth/100*2">
          <canvas id="imgBeforeCanvas" class="canvas-box" :style="{width:canvasWidth,height:canvasHeight}" :width="canvasWidth" :height="canvasHeight"> </canvas>
        </el-col>
        <el-col :span="canvasWidth/100*2">
          <canvas id="imgAfterCanvas" class="canvas-box" :style="{width:canvasWidth,height:canvasHeight}" :width="canvasWidth" :height="canvasHeight"> </canvas>
        </el-col>
        <el-col :span="canvasWidth/100*2">
          <canvas id="imgAfterCanvas_1" class="canvas-box" :style="{width:canvasWidth,height:canvasHeight}" :width="canvasWidth" :height="canvasHeight"> </canvas>
        </el-col>
      </el-row>
      <span></span>
      <canvas id="imgAfterCanvas__0" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
      <span>主1</span>
      <canvas id="imgAfterCanvas__4" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
      <span>1</span>
      <canvas id="imgAfterCanvas__1" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
      <span></span>
      <canvas id="imgAfterCanvas__3" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
      <span>2</span>
      <canvas id="imgAfterCanvas__2" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
      <div class="color-card">
        <div v-for="item in colorList" :key="item" class="color-item" :style="{backgroundColor: `${getHexColor(`rgba(${item[0]},${item[1]},${item[2]},255)`)}`}"></div>
      </div>
    </div>
  </body>

  <script>
    function getBase64(file) {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      return new Promise((resolve) => {
        reader.addEventListener("load", () => resolve(reader.result))
      })
    }
    function getImageData(imgBeforeCanvas, url, imgAfterCanvas__0) {
      const ctx = imgBeforeCanvas.getContext("2d") // 设置在画布上绘图的环境
      const ctx_0 = imgAfterCanvas__0.getContext("2d") // 设置在画布上绘图的环境
      const image = new Image()
      image.src = url

      const w = imgBeforeCanvas.width
      const h = imgBeforeCanvas.height
      const w_0 = imgAfterCanvas__0.width
      const h_0 = imgAfterCanvas__0.height
      return new Promise((resolve) => {
        image.onload = function () {
          ctx.drawImage(image, 0, 0, w, h) // 将图片绘制到画布上
          ctx_0.drawImage(image, 0, 0, w_0, h_0) // 将图片绘制到画布上
          const imgData = ctx.getImageData(0, 0, w, h) // 获取画布上的图像像素
          resolve(imgData.data) // 获取到的数据为一维数组,包含图像的RGBA四个通道数据
        }
      })
    }
    function drawImage(dom, data) {
      const ctx = dom.getContext("2d")
      const matrix_obj = ctx.createImageData(dom.width, dom.height)
      matrix_obj.data.set(data)
      ctx.putImageData(matrix_obj, 0, 0)
    }
    function d1tod3(data, width, height) {
      const list = []
      const result = []
      const len = Math.ceil(data.length / 4)
      // 将每一个像素点的rgba四个值组合在一起
      for (let i = 0; i < len; i++) {
        const start = i * 4
        list.push([data[start], data[start + 1], data[start + 2], data[start + 3]])
      }
      //根据图形的宽和高将数据进行分类
      for (let hh = 0; hh < height; hh++) {
        const tmp = []
        for (let ww = 0; ww < width; ww++) {
          tmp.push(list[hh * width + ww])
        }
        result.push(tmp)
      }
      return result
    }
    function d3tod1(data) {
      const result = []
      for (let i = 0; i < data.length; i++) {
        for (let j = 0; j < data[i].length; j++) {
          result.push(data[i][j][0], data[i][j][1], data[i][j][2], data[i][j][3])
        }
      }
      return result
    }
    function colourDistanceLAB(rgb_1, rgb_2) {
      let [R_1, G_1, B_1] = rgb_1
      let [R_2, G_2, B_2] = rgb_2
      let rmean = (R_1 + R_2) / 2
      let R = R_1 - R_2
      let G = G_1 - G_2
      let B = B_1 - B_2
      return Math.sqrt((2 + rmean / 256) * R ** 2 + 4 * G ** 2 + (2 + (255 - rmean) / 256) * B ** 2)
    }
    function findNearestColorOne(color, colorList) {
      let result = []
      let d = Infinity
      colorList.forEach((item) => {
        let d_ = colourDistanceLAB(item, color)
        if (d_ < d) {
          d = d_
          result = [...item]
        }
      })
      return result
    }
    function findNearestColorTwo(color, colorList) {
      let result1 = []
      let d1 = Infinity
      let result2 = []
      let d2 = Infinity
      colorList.forEach((item) => {
        let d_ = colourDistanceLAB(item, color)
        if (d_ < d1) {
          d2 = d1
          result2 = [...result1]
          d1 = d_
          result1 = [...item]
        } else if (d_ < d2) {
          d2 = d_
          result2 = [...item]
        }
      })
      return [result1, result2]
    }
    function getHexColor(color) {
      var values = color
        .replace(/rgba?\(/, "")
        .replace(/\)/, "")
        .replace(/[\s+]/g, "")
        .split(",")
      var a = parseFloat(values[3] || 1),
        r = Math.floor(a * parseInt(values[0]) + (1 - a) * 255),
        g = Math.floor(a * parseInt(values[1]) + (1 - a) * 255),
        b = Math.floor(a * parseInt(values[2]) + (1 - a) * 255)
      return "#" + ("0" + r.toString(16)).slice(-2) + ("0" + g.toString(16)).slice(-2) + ("0" + b.toString(16)).slice(-2)
    }
    const colorList = [
      [193, 195, 192],
      [195, 183, 13],
      [213, 185, 59],
      [216, 186, 0],
      [141, 120, 31],
      [211, 109, 0],
      [215, 134, 52],
      [206, 155, 76],
      [208, 87, 1],
      [206, 151, 0],
      [209, 127, 0],
      [221, 73, 3],
      [211, 44, 2],
      [201, 21, 0],
      [190, 5, 2],
      [130, 15, 22],
      [82, 21, 16],
      [62, 27, 21],
      [240, 188, 201],
      [249, 175, 198],
      [240, 114, 198],
      [251, 137, 195],
      [226, 59, 109],
      [249, 90, 94],
      [241, 96, 111],
      [214, 34, 46],
      [65, 46, 31],
      [137, 191, 226],
      [213, 169, 218],
      [130, 61, 162],
      [47, 60, 169],
      [113, 59, 85],
      [142, 145, 138],
      [107, 107, 99],
      [37, 44, 60],
      [20, 24, 23],
      [241, 190, 161],
      [248, 194, 166],
      [248, 174, 147],
      [215, 185, 149],
      [177, 126, 165],
      [120, 78, 38],
      [88, 58, 30],
      [125, 91, 53],
      [108, 79, 37],
      [212, 233, 69],
      [228, 235, 140],
      [197, 241, 182],
      [133, 237, 168],
      [140, 235, 107],
      [150, 230, 81],
      [80, 216, 76],
      [7, 186, 130],
      [41, 131, 37],
      [99, 162, 30],
      [0, 162, 42],
      [3, 118, 94],
      [19, 59, 58],
      [83, 117, 43],
      [15, 87, 42],
      [31, 54, 32],
      [2, 73, 161],
      [32, 41, 108],
      [101, 209, 222],
      [59, 155, 176],
      [30, 128, 215],
      [56, 193, 206],
      [0, 147, 161],
      [97, 195, 240],
      [78, 178, 237],
      [0, 80, 179],
      [29, 152, 222],

    //   [255, 255, 255],
    //   [250, 245, 242],
    //   [209, 183, 160],
    //   [112, 77, 66],
    //   [184, 136, 116]
    ]

    const vm = new Vue({
      el: "#app",
      data: {
        colorList,
        imgbase64: "",
        canvasWidth: 100,
        canvasHeight: 100,
        d3Data: null
      },
      computed: {},
      methods: {
        async onChange(file) {
          //   console.log("file", file)
          this.imgbase64 = await getBase64(file.raw)
          //   console.log("imgbase64", this.imgbase64)

          //   将图像绘制到canvas并获取图像数据
          const imgBeforeCanvas = document.getElementById("imgBeforeCanvas") // canvas画布
          const imgAfterCanvas__0 = document.getElementById("imgAfterCanvas__0") // canvas画布
          const w = imgBeforeCanvas.width
          const h = imgBeforeCanvas.height
          let data = await getImageData(imgBeforeCanvas, this.imgbase64, imgAfterCanvas__0)
          //   console.log("data", data)

          //   将数据转为高维数组
          let d3Data = d1tod3(data, w, h)
          this.d3Data = d3Data
          //   console.log("d3Data", d3Data)

          //   处理图像数据
          //   就近单值映射
          let d3DataMapOne = JSON.parse(JSON.stringify(d3Data))
          let d3DataMapOne_1 = JSON.parse(JSON.stringify(d3Data))
          d3Data.forEach((row, i) => {
            row.forEach((item, j) => {
              let [res1, res2] = findNearestColorTwo(item, colorList)
              d3DataMapOne[i][j] = [...res1, 255]
              d3DataMapOne_1[i][j] = [...res2, 255]
            })
          })
          //   console.log("d3DataMapOne", d3DataMapOne)

          //   就近2值映射
          let d3DataMapTwo1 = JSON.parse(JSON.stringify(d3Data))
          let d3DataMapTwo2 = JSON.parse(JSON.stringify(d3Data))
          let d3DataMapTwo3 = JSON.parse(JSON.stringify(d3Data))
          let d3DataMapTwo4 = JSON.parse(JSON.stringify(d3Data))
          d3Data.forEach((row, i) => {
            row.forEach((item, j) => {
              let [res1, res2] = findNearestColorTwo(item, colorList)
              d3DataMapTwo1[i][j] = [...res1, 255]
              d3DataMapTwo2[i][j] = [...res2, 255]
            })
          })
          let d1Data__1 = []
          let d1Data__2 = []
          let d1Data__3 = []
          let d1Data__4 = []
          for (let i = 0; i < this.canvasWidth; i++) {
            for (let j = 0; j < this.canvasHeight; j++) {
              d1Data__1.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo1[i][j])
              d1Data__2.push(...d3DataMapTwo2[i][j], ...d3DataMapTwo2[i][j])
              d1Data__3.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo2[i][j])
              d1Data__4.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo1[i][j])
            }
            for (let j = 0; j < this.canvasHeight; j++) {
              d1Data__1.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo1[i][j])
              d1Data__2.push(...d3DataMapTwo2[i][j], ...d3DataMapTwo2[i][j])
              d1Data__3.push(...d3DataMapTwo2[i][j], ...d3DataMapTwo1[i][j])
              d1Data__4.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo2[i][j])
            }
          }
          //   console.log("d1Data__1", d1Data__1)

          //   将高维数组转为一维数组
          let d1Data = d3tod1(d3DataMapOne)
          let d1Data_1 = d3tod1(d3DataMapOne_1)
          //   console.log("d1Data", d1Data)

          //   将处理后的数据绘制到imgAfterCanvas
          //   const imgAfterCanvas = document.getElementById("imgAfterCanvas") // canvas画布
          //   drawImage(imgAfterCanvas, d1Data)
          //   const imgAfterCanvas_1 = document.getElementById("imgAfterCanvas_1") // canvas画布
          //   drawImage(imgAfterCanvas_1, d1Data_1)
          const imgAfterCanvas__1 = document.getElementById("imgAfterCanvas__1") // canvas画布
          drawImage(imgAfterCanvas__1, d1Data__1)
          const imgAfterCanvas__2 = document.getElementById("imgAfterCanvas__2") // canvas画布
          drawImage(imgAfterCanvas__2, d1Data__2)
          const imgAfterCanvas__3 = document.getElementById("imgAfterCanvas__3") // canvas画布
          drawImage(imgAfterCanvas__3, d1Data__3)
          const imgAfterCanvas__4 = document.getElementById("imgAfterCanvas__4") // canvas画布
          drawImage(imgAfterCanvas__4, d1Data__4)
        }
      }
    })
  </script>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值