[Linux] make remote desktop in Terminal

< Real desktop >

 

< fontsize 12 : xterm-color >

 

< fontsize 2 : xterm-color >

 

 

 

 

 

 

 

 

 

Why need this program?

secure shell(ssh)을 통해 작업을 하다보면, 원격에서 서버의 GUI를 직접 확인하고 싶을 때가 있다. (물론 대다수의 서버용 컴퓨터는 GUI를 사용하지 않겠지만…)

또는, 직접 서버의 GUI모드에서 마우스를 움직이거나 키보드를 칠 필요성이 있을 것이다.

이 소스 코드는 별도의 비용 없이(팀뷰어 등) 간단한 원격 작업을 수행할 수 있다.

 

 

 

 

Remote control in Terminal

터미널 원격제어 프로그램은 이전 포스트에서 소개한 Image2ASCII(http://siya.co.kr/?p=439)에 두 가지 모듈을 추가하여 만든다.

 

  1. robotjs node.js 데스크톱 자동화도구
  2. shutter : 스크린샷 어플리케이션

 

데스크톱을 직접 제어하기위해 robotjs(https://github.com/octalmage/robotjs)를 사용한다. 그 결과 화면을 shutter가 캡쳐하고, Image2ASCII가 출력한다.

 

 

 

Install

npm i robotjs

sudo apt-get install shutter

 

 

 

Usage

  • robotjs

 

공식 사이트를 참조하여 필요한 기능을 추가한다.

(https://robotjs.io/docs/syntax)

 

Example : 마우스 이동 후 클릭

const robot = require('robotjs');

 

robot.moveMouse(X, Y);

robot.mouseClick();

 

 

  • shutter

 

shutter help를 치고 필요한 옵션을 찾으면 된다.

 

Example : 스크립트로 데스크톱 전체화면 캡쳐

shutter -f -e -o="./desktop.png"

 

 

 

Source code

아래 코드는 node.js 버전으로 작성되었으며, github(https://url)을 통해서도 받을 수 있다.

//CODE ADD


[Linux] make Image viewer in Terminal

< original image >

 

< fontsize 12 : xterm-color >

 

< fontsize 2 : xterm-color >

 

< fontsize 2: xterm-greyscale>

 

 

 

 

 

 

 

 

Why need this program?

secure shell(ssh)을 통해 작업을 하다보면, GUI가 필요한 순간이 있다.

예를들면 딥러닝 작업을 할 때 결과물을 그래프로 보고 싶은 경우가 있다.

물론, scp(secure copy)를 통해 그래프를 로컬로 가져와서 보는 방법도 있지만, 아무래도 귀찮은 것이 사실이다.

이 경우에 (비록 저화질이더라도)터미널로 이미지를 바로 볼 수 있다면 작업속도가 향상 될 것이다.

 

 

 

GreyScale

각 글자 별로 칸을 차지하는 크기가 다르다는 것에 착안하였다.

Paul Bourke에 의하면(http://paulbourke.net/dataformats/asciiart/)  아래 문자열은왼쪽에서 오른쪽으로 갈 수록 밝아진다고 하였다.(검은색 배경, 흰색 폰트 기준)

[ .\’`^”,:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$]

 

따라서 이미지를 Greyscale 한 후, 위 문자열로 적당히 매핑해주면 될 것이다.

Greyscale에는 여러 방법이 있다.

Tanner(http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/)가 이런 방법을 잘 정리해놓았다.

각자 원하는 방법으로 Greyscale을 하면 될 것이다.

(나는 r*0.2126 + g*0.7152 + b*0.0722의 수식을 썼을때 가장 그럴싸한 이미지를 얻었다.)

 

let black2white = "  .\'`^",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"

let greyscale = r*0.2126 + g*0.7152 + b*0.0722

let character = black2white.charAt(Math.floor(black2white.length * (greyscale - 0.0001) / 255));

 

 

 

Color quantization

Xterm color sheet(https://jonasjacek.github.io/colors/)를 보면 색상간에 규칙이 존재한다.

코드 16번(rgb(0,0,0))부터 b, g, r순으로 0, 95, 135, 175, 215, 255를 표현하고 있다.

즉 색상코드를 16 + R*6^2 + G*6 + B로 정의할 수 있다. (R, G, B는 r, g, b를 0 ~ 5 값으로 축소한 것)

RGB의 각 값은 0 ~ 255인데 반해, 표현 가능한 색상은 6가지 뿐이므로, 각 색상값마다 표현 가능한 가장 가까운 값으로 매핑할 필요가 있다.

 

매핑에는 여러 방법이 있겠지만, 나의 경우 아래의 방법을 썼다.

let colorGap = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5];

let color = colorGap[r/10] * 36 + colorGap[g/10] * 6 + colorGap[b/10] + 16

 

어떤 방법을 쓰든, 각 자리의 색상값을 매핑하여 출력하면, 216가지 색깔로 양자화 된 이미지가 나온다.

조금 더 다양한 색상을 표현하고 싶다면, 위 Greyscale 방법과 합쳐서 글자, 배경색, 전경색 세가지 요소로 픽셀을 표현해도 괜찮을 것이다.

 

 

 

Source code

아래 코드는 node.js 버전으로 작성되었으며, github(https://url)을 통해서도 받을 수 있다.

//CODE ADD

[Mecab] 영어 명사 추출

예전엔 영어 명사 분리가 잘 안되서 만들었던거 같은데, 지금은 기본 mecab으로도 잘 된다. 결과적으로 필요 없는 글이다.

아마 예전에 mecab을 잘못 설치하거나 이상하게 써서 안됐을지도…

 

dic.txt는 다운받아서 같은 경로에 두면 되며, 데이터는 http://www.114pda.com/language/dic-data/dic-ek-51873.htm에서 가져왔다.

정확도를 높이려면 사전을 추가하면 되는데, https://github.com/liks79/edic/tree/master/data에서 가져오면 될 듯 하다.

var mecab = require('mecab-ffi');
var fs = require('fs');

let tsvParser = (filePath) => {
    let data = fs.readFileSync(filePath, 'utf-8').split('\r\n');
    let result = {};
    for (let i = 0; i < data.length; i++) {
        if (!data[i]) break;
        let item = data[i].split(' /// ');

        if (!item[1] || item[1].length <= 0) {
            item[1] = '';
        }

        result[item[0]] = {eng: item[0], tag: item[1].match(/([A-Z].)/gim), kor: item[1]};
    }

    return result;
};

mecab.siyaParse = (string) => {
    result = mecab.parseSync(string);

    for (let i = 0; i < result.length; i++) {
        if (result[i][1] == 'SL') {
            if (data[result[i][0].toLowerCase()])
                result[i] = [result[i][0], data[result[i][0].toLowerCase()].tag, data[result[i][0].toLowerCase()].kor];
        }
    }

    return result;
}


var data = tsvParser('./dic.txt');

// Synchronously
result = mecab.siyaParse("It is test");
console.log(result);