Node JS에 ASCII 아트 생성기를 만들었습니다.

31626 단어 nodeartjavascriptascii
안녕하세요.👋
본 문서에서 이미지에서 ASCII 아트 생성기를 생성하는 방법을 보실 수 있습니다

결과:




그러나 우선

이것은 무슨 예술입니까?


ASCII art is a graphic design technique that uses computers for presentation and consists of pictures pieced together from the 95 printable characters defined by the ASCII Standard from 1963 and ASCII compliant character sets with proprietary extended characters


선결 조건


이러한 패키지를 사용할 예정입니다.
이 프로젝트에 대해 저는 제 JS 지식을 사용하고 싶습니다. 그래서 저는 다음과 같이 사용할 것입니다.
  • Node js
  • Sharp

  • readline-sync
  • npm i sharp readline-sync
    

    계획의 단계:


    내가 ASCII 예술을 생각했을 때 나는 그것이 어떤 변두리 검출 알고리즘으로 만들어졌다고 생각했다. 어머, 세상에. 내가 잘못했어. 그림으로 ASCII 예술을 만들었는데 네가 필요로 하는 것은 다음과 같다.
  • 이미지를 흑백으로 변환
  • 이미지 크기 조정
  • 모든 흑백 픽셀을 밝기와 어둠/음영의 문자 정의로 바꿉니다
  • .
    자, 시작합시다. 제가 먼저 가방을 만들겠습니다.다음과 같은 방법으로 json 파일을 만듭니다.
    npm init
    
    일단 가방이 생기면 색인을 만들 것입니다.js 파일, 이것이 바로 나의 코드입니다.
    좋습니다. 완료되면 이 프로젝트에 필요한 모든 종속성을 다음과 같이 가져옵니다.
    const sharp = require("sharp");
    const readlineSync = require("readline-sync");
    const fs = require("fs");
    
    그리고 사용자가 변환하고 싶은 그림을 먼저 물어보겠습니다

    사용자 입력 가져오기


    이를 위해 loadFileFromPath라는 함수를 만들고 다음 사용자 입력을 받습니다.
    var filePath = readlineSync.question("What's the file path ");
    
    ReadlineSync가 필요한 이유는 무엇입니까?
    readline Sync 패키지가 무엇인지 알고 싶을 수도 있습니다.이것은 컨트롤러에 입력을 동기화할 수 있도록 합니다. 노드 JS는 비동기적이기 때문에 코드가 계속 실행되기 때문에 사용자의 입력을 기다리기 위해 사용합니다.
    그런 다음 다음 다음 try/catch를 사용하여 경로가 정확한지 테스트합니다.
    try {
        const file = await sharp(filePath);
        return file;
      } catch (error) {
        console.error(error);
      }
    
    all 함수는 다음과 같습니다.
    const loadFileFromPath = async () => {
      var filePath = readlineSync.question("What's the file path ");
      try {
        const file = await sharp(filePath);
        return file;
      } catch (error) {
        console.error(error);
      }
    };
    

    흑백으로 바꾸다


    이렇게 하려면 먼저 다음과 같은 경로 매개 변수인 convertToGrayscale이라는 함수를 생성합니다.
    const convertToGrayscale = async (path) => {
      // code
    };
    
    이 함수에서, 나는 img을 불러오고, 색 값을 B&W로 변경하고, 마지막으로 B&W 결과를 되돌려줍니다
    const convertToGrayscale = async (path) => {
     const img = await path; 
     const bw = await img.gamma().greyscale();
     return bw;
    };
    

    이미지 크기 조정


    이렇게 하려면 먼저 bw와 newWidth=100개의 매개변수를 사용하여 resizeImg이라는 함수를 생성합니다.
    const resizeImg = async (bw, newWidth = 100) => {
      //code
    };
    
    t
    그리고, 나는 bw 이미지를 기다리고, 흑백이 선택할 수 있는 결과를 기다린 다음, sizes 속성에 접근할 수 있도록 메타데이터를 가져올 것이다
    const resizeImg = async (bw, newWidth = 100) => {
      const blackAndWhite = await bw;
      const size = await blackAndWhite.metadata();
    };
    
    그리고 우리는 그림의 비율을 계산한다. 우리는 너비를 높이로 나누기만 하면 비율을 얻을 수 있다.그런 다음 다음 다음 새 높이를 계산합니다.
    const ratio = size.width / size.height;
    newHeight = parseInt(newWidth * ratio);
    
    그런 다음 최종적으로 이미지 크기를 조정하고 다음과 같이 돌아갑니다.
    const resized = await blackAndWhite.resize(newWidth, newHeight, {
        fit: "outside",
      });
    return resized;
    
    전체 함수는 다음과 같아야 합니다.
    const resizeImg = async (bw, newWidth = 100) => {
      const blackAndWhite = await bw;
      const size = await blackAndWhite.metadata();
      const ratio = size.width / size.height;
      newHeight = parseInt(newWidth * ratio);
      const resized = await blackAndWhite.resize(newWidth, newHeight, {
        fit: "outside",
      });
    
      return resized;
    };
    

    픽셀을 ASCII 문자로 변환


    이렇게 하려면 다음과 같이 pixelToAscii라는 함수를 먼저 생성합니다.
    const pixelToAscii = async (img) => {
     //code
    };
    
    그리고wait 키워드로img을 저장하는 변수를 만들 것입니다.그리고 그림의 픽셀 그룹을 가져와pixels라는 변수에 저장합니다.
    var newImg = await img;
    const pixels = await newImg.raw().toBuffer();
    };
    
    그리고 빈 문자열을 포함하는characters라는 변수를 만들 것입니다.그런 다음 픽셀 배열의 각 픽셀을 옮겨다니며 ASCII 문자를 이전에 만든 문자열로 변환합니다.
    characters = "";
    pixels.forEach((pixel) => {
        characters = characters + ASCII_CHARS[Math.floor(pixel * interval)];
      });
    
    너는 내가 아직 언급하지 않은 두 개의 전역 변수를 알아차릴 수 있을 것이다.
  • 간격
  • ASCII 문자
  • 이 두 변수가 무엇인지 설명해 드리겠습니다.
  • ASCII CHARS는 모든 ASCII 문자를 저장하는 변수입니다.
  • ASCII_CHARS = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. ".split(
      ""
    );
    
  • 간격은 색상(강도)에 분배해야 하는 ascii 코드입니다.
  • charLength = ASCII_CHARS.length;
    interval = charLength / 256;
    
    자, 이제 이 변수들이 무엇인지 알았으니 함수로 돌아가자. 함수는 이제 이렇게 되어야 한다.
    const pixelToAscii = async (img) => {
      var newImg = await img;
      const pixels = await newImg.raw().toBuffer();
      characters = "";
      pixels.forEach((pixel) => {
        characters = characters + ASCII_CHARS[Math.floor(pixel * interval)];
      });
      return characters;
    };
    
    이제 애플리케이션의 핵심을 만드는 모든 단계가 이루어졌습니다.

    주요 기능


    이렇게 하려면 newWidth=100개의 매개 변수가 있는 main이라는 함수를 먼저 만듭니다.
    const main = async (newWidth = 100) => {
      //code
    };
    
    이 함수에서 다음과 같이 *newImgData라는 함수를 생성합니다.
    const main = async (newWidth = 100) => {
      const newImgData = await pixelToAscii(
        resizeImg(convertToGrayscale(loadFileFromPath()))
      );
    };
    
    그런 다음 문자의 길이를 얻고 다음과 같이 ASCII라는 빈 변수를 만듭니다.
    const pixels = newImgData.length;
    let ASCII = "";
    
    그런 다음 다음과 같이 픽셀 목록을 둘러봅니다.
    for (i = 0; i < pixels; i += newWidth) {
        let line = newImgData.split("").slice(i, i + newWidth);
        ASCII = ASCII + "\n" + line;
      }
    
    그래서 기본적으로 분할선을 설정하고 있습니다.나는 newWidth 크기를 얻은 다음, 그룹을 새 너비의 선으로 슬라이스했다
    다음 행으로 이동하려면\n 문자를 추가합니다.

    텍스트 파일로 내보내기


    마지막으로, 같은 함수에서, 나는 텍스트를 텍스트 파일에 저장한다
     setTimeout(() => {
        fs.writeFile("output.txt", ASCII, () => {
          console.log("done");
        });
      }, 5000);
    
    봐라, 우리가 그림에서 ASCII 예술 생성기를 얻었으니,main () 함수를 먼저 호출하는 것을 잊지 마라
    전체 코드는 다음과 같습니다.
    const sharp = require("sharp");
    const readlineSync = require("readline-sync");
    const fs = require("fs");
    
    ASCII_CHARS = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. ".split(
      ""
    );
    charLength = ASCII_CHARS.length;
    interval = charLength / 256;
    var newHeight = null;
    const main = async (newWidth = 100) => {
      const newImgData = await pixelToAscii(
        resizeImg(convertToGrayscale(loadFileFromPath()))
      );
      const pixels = newImgData.length;
      let ASCII = "";
      for (i = 0; i < pixels; i += newWidth) {
        let line = newImgData.split("").slice(i, i + newWidth);
        ASCII = ASCII + "\n" + line;
      }
    
      setTimeout(() => {
        fs.writeFile("output.txt", ASCII, () => {
          console.log("done");
        });
      }, 5000);
    };
    
    const convertToGrayscale = async (path) => {
      const img = await path;
      const bw = await img.gamma().greyscale();
      return bw;
    };
    
    const resizeImg = async (bw, newWidth = 100) => {
      const blackAndWhite = await bw;
      const size = await blackAndWhite.metadata();
      const ratio = size.width / size.height;
      newHeight = parseInt(newWidth * ratio);
      const resized = await blackAndWhite.resize(newWidth, newHeight, {
        fit: "outside",
      });
    
      return resized;
    };
    
    const pixelToAscii = async (img) => {
      var newImg = await img;
      const pixels = await newImg.raw().toBuffer();
      characters = "";
      pixels.forEach((pixel) => {
        characters = characters + ASCII_CHARS[Math.floor(pixel * interval)];
      });
      return characters;
    };
    
    const loadFileFromPath = async () => {
      var filePath = readlineSync.question("What's the file path ");
      try {
        const file = await sharp(filePath);
        return file;
      } catch (error) {
        console.error(error);
      }
    };
    main();
    

    전체 프로젝트에서 나는 무엇을 배웠습니까?


    이 프로젝트는 매우 재미있다. 나는 처음으로 함수를 끼워 넣을 수 있다는 것을 발견했고 ASCII 예술이 어떻게 작동하는지 발견했다. 나는 사용자가 입력한 node js 비동기 문제와 이 문제를 어떻게 해결하는지 배웠고 마지막으로 기본적인 이미지 처리를 어떻게 하는지 배웠다.

    결론


    본문을 읽어 주셔서 감사합니다. 저는 이것이 당신에게 도움이 되기를 바랍니다
    너는 나를 따라와도 된다.
    오늘 하루 잘 보내셨으면 좋겠습니다.
    계속 공부하는 것을 잊지 마라

    좋은 웹페이지 즐겨찾기