妈见打编码系列之canvas,image,blob,base64 数据转换

234 阅读1分钟

直接上代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no"
    />
    <title>data_transform</title>
    <script>
      const appendChild = (ele = document.createElement("div"), title = "") => {
        const div = document.createElement("div");
        title && (div.innerHTML = `<div>${title}</div>`);
        div.appendChild(ele);
        return div;
      };

      const downloadAction = (
        data_url = "",
        file_name = "file_name",
        file_ext = "jpeg"
      ) => {
        const a = document.createElement("a");
        a.textContent = "Download";
        a.download = `${file_name}.${file_ext}`;
        a.href = data_url;
        a.click();
      };

      const DataTransform = {
        file2DataUrl: (file, is_blob_url = false) =>
          new Promise((res, rej) => {
            if (is_blob_url === true) {
              res(window.URL.createObjectURL(file));
            } else {
              const reader = new FileReader();
              reader.onload = () => {
                res(reader.result, reader);
              };
              reader.onerror = rej;
              reader.readAsDataURL(file);
            }
          }),
        url2Image: (url = "") =>
          new Promise((res, rej) => {
            const image = new Image();
            image.src = url;
            image.onload = () => res(image);
            image.onerror = rej;
          }),
        image2Canvas: (
          image = document.createElement("img"),
          { width, height, position: { top = 0, left = 0 } = {} } = {}
        ) => {
          const canvas = document.createElement("canvas");
          const ctx = canvas.getContext("2d");
          canvas.width = width || image.naturalWidth;
          canvas.height = height || image.naturalHeight;
          ctx.drawImage(image, top, left, canvas.width, canvas.height);
          return Promise.resolve(canvas);
        },
        canvas2DataUrl: (
          canvas = document.createElement("canvas"),
          {
            mime_type = "image/jpeg",
            quality = undefined,
            is_blob = false
          } = {}
        ) =>
          new Promise(res => {
            if (is_blob) {
              canvas.toBlob(blob => res(blob), mime_type, quality);
            } else {
              res(canvas.toDataURL(mime_type, quality));
            }
          }),
        dataUrl2Blob: (data_url = "", mime_type = "") => {
          const [data_type, data] = data_url.split(",");
          const [, mime] = data_type.match(/^data:(.*?);(base64?)/);
          const bin_str = atob(data);
          const arr = new Uint8Array(data.length).map((v, k) =>
            bin_str.charCodeAt(k)
          );

          return Promise.resolve(new Blob([arr], { type: mime_type || mime }));
        }
      };

      function inputOnChange({ files }) {
        DataTransform.file2DataUrl(files[0])
          // .then(data_url => {
          //   alert("下载原图");
          //   downloadAction(data_url);
          //   return data_url;
          // })
          .then(DataTransform.url2Image)
          .then(DataTransform.image2Canvas)
          .then(DataTransform.canvas2DataUrl)
          // .then(data_url => {
          //   alert("下载 canvas2DataUrl 图");
          //   downloadAction(data_url);
          //   return data_url;
          // })
          .then(DataTransform.dataUrl2Blob)
          .then(DataTransform.file2DataUrl)
          // .then(data_url => {
          //   alert("下载 file2DataUrl 图");
          //   downloadAction(data_url);
          //   return data_url;
          // })
          .then(DataTransform.url2Image)
          .then(image => {
            document.body.append(appendChild(image, "1 image"));
            return image;
          })
          .catch(console.error);
      }
    </script>
  </head>
  <body>
    <input type="file" onchange="inputOnChange(this)" />
  </body>
</html>

请使用 jpeg 图片进行玩耍,png 会出现转换后比原始图片大的情况。