【momo的源码基石】图片梳理-1

328 阅读4分钟

前言:经过和面试官的激情交流,终于进入理想的公司开始新的旅程。之前在公司听到大佬对对计算机图像的分享,还有一些图片安全问题,于是乎故事开始了......

图片简述

  在平时的生产使用中,我们总会看到不同格式的图片,在表现形式上看,他们之间的差别是他们的文件后缀名不一致,例如:Jpg、Png、Svg、WMF等。对平时的使用,我们将很不会对其内容进行深究,但是空闲下来,我们也需要进行相关知识的积累。不同的图片格式名称反映他们采用了不同的压缩算法、特性和用途。但是归根结底,他们在计算机中被分成两类,也就是本篇中想介绍的位图矢量图

  位图是由一组像素点描绘的图形。位图由一个个不可分割的像素点组成。通常,像素点的内存由颜色值和有可能的附加信息组成(附加信息可能是位置、像素状态、Alpha通道等信息)。不考虑附加信息时,像素点由RGB三个分量组成rgb(255,255,255)使用三个8位二进制数进行表示那么大小就是1字节(byte)。如果考虑Alpha信息那么像素点将由rgba四个通道构成rbga(255,255,255,128)则需要四个8位二进制数进行表示。

  矢量图是指由一组数学公式描述的图形要素(如直线、弧线、多边形等)构成的图像。在矢量图中,每个图形要素都表示为一些数学公式,这些公式描述了图像中每个点的位置、颜色、透明度等属性。因此,矢量图可以被缩放至任意大小而不失真,因为图像实际上是由这些公式计算而成的,而不是由像素点构成的。

image.png

图像二进制表示的获取

  使用js代码可以获取图片并输出其二进制数据,当然,这里输出的二进制信息不一定上述所说的原始图片的rgb信息,毕竟图片可能被进行压缩,也可能携带有其他的图片私藏的信息。   使用下面案例的代码可以获取图片最终存储的二进制信息并且下载图片。

image.png

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>获取图片</title>
  </head>
  <body>
    <script>
      function createImageFromBinary(binaryData) {
        const blob = new Blob([binaryData], {
          type: "application/octet-stream",
        });
        const imageUrl = URL.createObjectURL(blob);

        const img = document.createElement("img");
        img.src = imageUrl;
        document.body.appendChild(img);
        img.onload = function () {
          const width = img.width;
          const height = img.height;

          console.log("宽:" + width + "高:"+ height);
        };
        // 如果需要下载图片,可以创建一个链接并模拟点击
        const downloadLink = document.createElement("a");
        downloadLink.href = imageUrl;
        downloadLink.download = "image.jpg";
        document.body.appendChild(downloadLink);
        downloadLink.click();
      }

      function readBitmap(file) {
        return new Promise((resolve, reject) => {
          const reader = new FileReader();

          reader.onload = function (event) {
            resolve(new Uint8Array(event.target.result));
          };

          reader.onerror = function (event) {
            reject(event.target.error);
          };

          reader.readAsArrayBuffer(file);
        });
      }

      // 获取图像
      const fileInput = document.createElement("input");
      fileInput.type = "file";
      fileInput.addEventListener("change", async function (event) {
        const file = event.target.files[0];

        try {
            // 读取二进制数据
            const binaryData = await readBitmap(file);
          console.log(binaryData);
          createImageFromBinary(binaryData);
        } catch (error) {
          console.error(error);
        }
      });

      // 将input元素加入到DOM树中
      document.body.appendChild(fileInput);
    </script>
  </body>
</html>

像素风图片创作

  经过概念和相关信息的获取,我们可以进行位图图像的创作,可以根据不同的数学公式去定义我们的像素矩阵。但是保存下来实际的图像跟我们计算的图像带下不一致,必然是经过处理,这个得下一次进行分析(继续挖坑)。

image.png

他的分辨率又是跟预期一致的。。。。。。

image.png

 <script>
      function drawImageFromBinaryData(width, height, binaryData,fileName) {
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        canvas.width = width;
        canvas.height = height;
        console.log(binaryData,binaryData.length);
          // 创建ImageData对象并将二进制数据传递给它
          const imageData = new ImageData(binaryData, width, height);

        // 将图像数据绘制到Canvas上
        ctx.putImageData(imageData, 0, 0);
        // 创建节点
        document.body.appendChild(canvas);
        // 创建链接元素
        const link = document.createElement("a");
        link.href = canvas.toDataURL();
        // 设置文件名
        link.download = fileName;
        // 触发链接的点击事件
        link.click();
      }
      function creatBinaryData(width,height,alpha){
        // 计算大小
        const total = 3*width*height

        // 创建矩阵
        const rgbData = []
        for(let i = 0;i<total;i+=3){
            // 黑色
            //   rgbData.push(0)
            //   rgbData.push(0)
            //   rgbData.push(0)
            rgbData.push(Math.floor(Math.random() * 256))
            rgbData.push(Math.floor(Math.random() * 256))
            rgbData.push(Math.floor(Math.random() * 256))
            if(arguments.length===3){
              rgbData.push(alpha)
            }else{
              rgbData.push(Math.floor(Math.random() * 256))
            }
        }
        
        return Uint8ClampedArray.from(rgbData)
      }

      const fileName = "momo.bmp";
      const width = 200
      const height = 200
      const binaryData = creatBinaryData(width,height,255)
      drawImageFromBinaryData(width, height, binaryData,fileName);
    </script>

ps:个人对图片的理解还比较浅薄,如果您在阅读的过程中发现有啥问题,欢迎批评指正!