【JavaScript】实现简单的图片处理

目录

图片在前端的存储形式

前端上传图片

图片处理

灰度操作

负片效果

压缩

膨胀

马赛克

字符画

参考资料


图片在前端的存储形式

图片以Uint8ClampedArray的格式存储. 这是一个一维数组,每四位组成一个像素点,分别代表rgba四个参数,每个参数的取值范围都是0~2^8-1(0~255).

// 这是一个全黑色,透明的像素点
const pixel = new Uint8ClampedArrray([0,0,0,255]);

一张图片就是由 宽 x 高 个这样的像素点组成的.

前端上传图片

图片的容器标签是<img />,在JavaScript中可以用new Image()来构造.

export function createImageElement(src) {
    const img = new Image();
    img.src = src;
    return img;
}

前端选择文件,都通过<input type="file"/>来完成,对于选中的图片文件,使用FileReaderreadAsDataURL方法读取.

const reader = new FileReader();
reader.onload = () => {
  const img = createImageElement(reader.result);
};
reader.readAsDataURL(file);

这里为了方便DOM操作,用svelte框架来快速实现一个图片上传器.

<script>
  import { createEventDispatcher, onMount, tick } from "svelte";
  import { createImageElement } from "../../utils";

  export let size = 50;

  let image;
  let imgSrc;
  let inputDom;
  let container;

  onMount(() => {
    container.style.setProperty("--trigger-size", size + "px");
  });

  const dispatch = createEventDispatcher();

  const pickHandler = (event) => {
    const file = event.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = async () => {
      imgSrc = reader.result;
      const img = createImageElement(reader.result);
      await tick();
      dispatch("picked", {
        preview: image,
        src: reader.result,
        img,
        file,
        event,
      });
    };
    reader.readAsDataURL(file);
  };

  const triggerClick = () => {
    inputDom.click();
  };
</script>

<div bind:this={container} class="image-picker_container">
  <div on:click|stopPropagation={triggerClick} class="image-picker_trigger">
    {#if imgSrc}
      <img
        bind:this={image}
        src={imgSrc}
        alt="Error"
        class="image-picker_preview"
      />
    {:else}
      <div class="image-picker_cross" />
    {/if}

    <input
      bind:this={inputDom}
      type="file"
      on:change={pickHandler}
      class="image-picker_input-hidden"
    />
  </div>
</div>

<style>
  .image-picker_container {
    --trigger-padding: 4px;
    --trigger-border: 1px;
    --cross-size: calc(var(--trigger-size) * 0.6);
  }
  .image-picker_preview {
    width: var(--trigger-size);
    height: var(--trigger-size);
    object-fit: contain;
  }
  .image-picker_input-hidden {
    display: none;
  }
  .image-picker_trigger {
    border: var(--trigger-border) dashed;
    padding: var(--trigger-padding);
    height: var(--trigger-size);
    width: var(--trigger-size);
    position: relative;
  }
  .image-picker_cross::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: var(--cross-size);
    border: calc((var(--trigger-size) * 0.2) / 2) solid #ccc;
  }
  .image-picker_cross::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50
  • 14
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值