vue3+ts 实现简单抠图

前端实现简单抠图 vue3+ts

最近有一个简单的想法,拿到图片之后过滤颜色,实现简单的抠图。所以做了一个小demo简单实现了。

技术栈:vue3 + typescript

在这里插入图片描述

<template>
  <div style="display: flex">
    <div class="image-container">
      <span class="demonstration">转换前</span>
      <img
        :src="props._src"
        ref="imgRef"
        @load="onImageLoad"
        @error="onImageError"
        crossOrigin="anonymous"
      />
    </div>
    <div class="image-container">
      <span class="demonstration">转化后</span>
      <div class="canvas-container texture">
        <canvas id="image-canvas" ref="canvasRef"></canvas>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";

interface IProp {
  _src: string;
  scale: number;
}
const props = withDefaults(defineProps<IProp>(), {
  _src: () => "",
  scale: () => 1, // 设置过滤后的缩放大小
});

const canvasRef = ref<HTMLCanvasElement | null>(null);
const imgRef = ref<HTMLImageElement | null>(null);

function filter(data: Uint8ClampedArray) {
  let count = 0; // 记录过滤的像素数量
  for (let i = 0; i < data.length; i += 4) {
    let r = data[i],
      g = data[i + 1],
      b = data[i + 2];

    // 放宽过滤条件,色值在240-256之间都认为是白色
    if ([r, g, b].every((v) => v >= 138)) {
      data[i + 3] = 0; // 把白色改成透明的
      count++;
    }
  }
  console.log(`Filtered ${count} pixels`);
}

function onImageLoad() {
  if (canvasRef.value && imgRef.value) {
    const width = imgRef.value.width;
    const height = imgRef.value.height;
    console.log(width, height);

    // 动态设置画布的尺寸
    canvasRef.value.width = width;
    canvasRef.value.height = height;

    const ctx = canvasRef.value.getContext("2d");
    if (ctx) {
      ctx.scale(props.scale, props.scale); // 缩放画布
      ctx.drawImage(imgRef.value, 0, 0);

      // 获取画布像素信息
      const imageData = ctx.getImageData(0, 0, width, height);

      // 一个像素点由RGBA四个值组成,data为[R,G,B,A [,R,G,B,A[...]]]组成的一维数组
      // 可以通过修改该数组的数据,达到修改图片内容的目的
      const data = imageData.data;
      filter(data); // 这里对图像数据进行处理

      // 把新的内容画进画布里
      ctx.putImageData(imageData, 0, 0);
    }
  }
}

function onImageError() {
  console.error("图片加载失败");
}
</script>

<style scoped lang="less">
.image-container {
  box-sizing: border-box;
  margin-top: 30px;
  margin-right: 30px;
  border: 1px solid var(--el-border-color);
  border-radius: 10px;
  padding: 20px;
}
.demonstration {
  text-align: center;
  display: block;
  color: var(--el-text-color-secondary);
  font-size: 14px;
}
.canvas-container {
  width: 100%;
}
.texture { /* 设置透明底纹 */ 
  --ccc: #ccc;
  ---transparent: transparent;
  font-size: 0;
  background-image: -webkit-gradient(
      linear,
      0 0,
      100% 100%,
      color-stop(0.25, var(---transparent)),
      color-stop(0.25, transparent),
      to(transparent)
    ),
    -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, var(---transparent)), color-stop(0.25, transparent), to(transparent)),
    -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.75, transparent), color-stop(0.75, var(---transparent))),
    -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.75, transparent), color-stop(0.75, var(---transparent)));
  background-size: 10px 10px;
}
.image-canvas {
  scale: 1;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值