GNU/Linux >> Linux の 問題 >  >> Linux

LinuxでASCIIアートを使ってハロウィーンの挨拶を印刷する

フルカラーASCIIアートはDOSで非常に人気があり、拡張ASCII文字セットとその描画要素のコレクションを活用できました。 ASCIIアートをクールな「ウェルカム」画面として、またはプログラムに関する詳細情報を含むカラフルな「終了」画面として追加することで、次のFreeDOSプログラムに視覚的な興味を少し加えることができます。

しかし、このスタイルのASCIIアートは、FreeDOSアプリケーションだけに限定されていません。 Linuxターミナルモードプログラムでも同じ方法を使用できます。 LinuxはDOSのconioの代わりにncursesを使用して画面を制御しますが、関連する概念はLinuxプログラムにうまく適用されます。この記事では、CプログラムからカラフルなASCIIアートを生成する方法について説明します。

その他のLinuxリソース

  • Linuxコマンドのチートシート
  • 高度なLinuxコマンドのチートシート
  • 無料のオンラインコース:RHELの技術概要
  • Linuxネットワーキングのチートシート
  • SELinuxチートシート
  • Linuxの一般的なコマンドのチートシート
  • Linuxコンテナとは何ですか?
  • 最新のLinux記事

ASCIIアートファイル

さまざまなツールを使用して、ASCIIアートを描くことができます。この例では、TheDrawという古いDOSアプリケーションを使用しましたが、Linux上でMoebius(Apacheライセンス)やPabloDraw(MITライセンス)などの最新のオープンソースASCIIアートプログラムを見つけることができます。保存されたデータがどのように見えるかを知っていれば、どのツールを使用してもかまいません。

これは、Cソースコードとして保存されたサンプルASCIIアートファイルの一部です。コードスニペットはいくつかの値を定義していることに注意してください:IMAGEDATA_WIDTH およびIMAGEDATA_DEPTH 画面上の列と行の数を定義します。この場合、それは80x25のASCIIアートの「画像」です。 IMAGEDATA_LENGTH IMAGEDATAのエントリ数を定義します 配列。 ASCIIアート画面の各文字は、2バイトのデータで表すことができます。表示する文字と、文字の前景色と背景色の両方を含む色属性です。各文字が属性とペアになっている80x25画面の場合、配列には4000エントリが含まれます(つまり、80 * 25 * 2 =4000)。

#define IMAGEDATA_WIDTH 80
#define IMAGEDATA_DEPTH 25
#define IMAGEDATA_LENGTH 4000
unsigned char IMAGEDATA [] = {
    '.', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,
    ' ', 0x08,  ' ', 0x08,  '.', 0x0F,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,
    ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  '.', 0x0F,
    ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,
    ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,  ' ', 0x08,

アレイの残りの部分についても同様です。

このASCIIアートを画面に表示するには、配列を読み取り、各文字を適切な色で印刷する小さなプログラムを作成する必要があります。

色属性の設定

このASCIIアートファイルのcolor属性は、1バイトで背景色と前景色の両方を定義し、0x08のような16進値で表されます。 または0x6E 。 16進数は、このような色の「ペア」を表現するためのコンパクトな方法であることがわかりました。

LinuxのncursesやDOSのconioなどの文字モードシステムでは、16色しか表示できません。これは、16の可能なテキストカラーと8つの背景カラーです。バイナリで16個の値(0から15)をカウントするには、4ビットしか必要ありません:

  • 1111 バイナリで16です

そして便利なことに、16進数は0から15を1文字で表すことができます:0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、およびF。 F 16進数は15、つまり1111です。 バイナリで。

カラーペアを使用すると、背景色と前景色の両方を8ビットの1バイトでエンコードできます。これは、テキストの色(16進数で0から15または0からF)の場合は4ビット、背景色の場合(16進数で0から7または0からE)の3ビットです。バイトの残りのビットはここでは使用されないため、無視できます。

色のペアまたは属性をプログラムで使用できる色の値に変換するには、ビットマスクを使用して、テキストの色または背景色に使用されるビットのみを指定する必要があります。 FreeDOSでOpenWatcomCコンパイラを使用すると、次の関数を記述して、color属性から色を適切に設定できます。

void
textattr(int newattr)
{
  _settextcolor(newattr & 15);         /* 0000xxxx */
  _setbkcolor((newattr >> 4) & 7);     /* 0xxx0000 */
}

_settextcolor 関数は、テキストの色と_setbkcolorだけを設定します 関数は背景色を設定します。どちらもgraph.hで定義されています 。 color属性には、1バイトの値に背景色と前景色の両方が含まれているため、textattr 関数は&を使用します (バイナリAND)属性の最後の4ビットのみを分離するビットマスクを設定します。ここで、色のペアに前景色の0〜15の値が格納されます。

背景色を取得するために、関数は最初にビットシフトを実行してビットを右に「プッシュ」します。これにより、「上位」ビットが「下位」ビット範囲に配置されるため、0xxx0000などのビットはすべて 00000xxxになります 代わりは。 7で別のビットマスクを使用できます(バイナリ0111 )背景色の値を選択します。

ASCIIアートの表示

IMAGEDATA 配列には、ASCIIアート画面全体と各文字の色の値が含まれています。アスキーアートを画面に表示するには、プログラムで配列をスキャンし、色属性を設定してから、一度に1文字ずつ画面に表示する必要があります。

画面の下部に、ユーザーへの別のメッセージまたはプロンプト用のスペースを残しましょう。つまり、80列のASCII画面の25行すべてを表示するのではなく、最初の24行だけを表示したいのです。

  /* print one line less than the 80x25 that's in there:
     80 x 24 x 2 = 3840 */

  for (pos = 0; pos < 3840; pos += 2) {
...
  }

forの内部 ループ、色を設定してから文字を印刷する必要があります。 OpenWatcomCコンパイラは関数_outtextを提供します 現在の色の値でテキストを表示します。ただし、これには文字列を渡す必要があり、行の各文字に異なる色が必要な場合に、各文字を一度に1つずつ処理する必要がある場合は、非効率的です。

代わりに、OpenWatcomには_outmemと呼ばれる同様の関数があります これにより、表示する文字数を指定できます。一度に1文字ずつ、IMAGEDATAの文字値へのポインタを指定できます。 配列して_outtextに伝えます 1文字だけ表示します。これにより、現在の色属性を使用して文字が表示されます。これが必要です。

  for (pos = 0; pos < 3840; pos += 2) {
    ch = &IMAGEDATA[pos];              /* pointer assignment */
    attr = IMAGEDATA[pos + 1];
 
    textattr(attr);
    _outmem(ch, 1);
  }

この更新されたfor ループは文字chを設定します IMAGEDATAにポインタを割り当てる。 配列。次に、ループはテキスト属性を設定し、_outmemで文字を表示します 。

すべてをまとめる

textattrを使用 関数とfor 配列を処理するためのループ、ASCIIアートファイルの内容を表示するための完全なプログラムを書くことができます。この例では、ASCIIアートをimgdata.incとして保存します #includeを使用してソースファイルに含めます ステートメント。

#include <stdio.h>
#include <conio.h>
#include <graph.h>

#include "imgdata.inc"

void
textattr(int newattr)
{
  _settextcolor(newattr & 15);         /* 0000xxxx */
  _setbkcolor((newattr >> 4) & 7);     /* 0xxx0000 */
}

int
main()
{
  char *ch;
  int attr;
  int pos;

  if (_setvideomode(_TEXTC80) == 0) {
    fputs("Error setting video mode", stderr);
    return 1;
  }

  /* draw the array */

  _settextposition(1, 1);              /* top left */

  /* print one line less than the 80x25 that's in there:
     80 x 24 x 2 = 3840 */

  for (pos = 0; pos < 3840; pos += 2) {
    ch = &IMAGEDATA[pos];              /* pointer assignment */
    attr = IMAGEDATA[pos + 1];

    textattr(attr);
    _outmem(ch, 1);
  }

  /* done */

  _settextposition(25, 1);             /* bottom left */

  textattr(0x0f);
  _outtext("Press any key to quit");

  getch();

  textattr(0x00);
  return 0;
}

FreeDOSのOpenWatcomCコンパイラを使用してプログラムをコンパイルすると、このホリデーメッセージを表示する新しいプログラムが表示されます。

みなさん、ハッピーハロウィン!

ここからINCコードファイルをダウンロードします。

ここからCコードファイルをダウンロードします。

imgdata.inc_.txt hallown.c.txt
Linux
  1. aptによるLinuxパッケージ管理

  2. Linuxコマンドラインツールを使用してJSONを解析してきれいに印刷する方法

  3. LinuxでのJQコマンドと例

  1. Linux –ツリーとディレクトリサイズを組み合わせる方法は?

  2. 大文字の単語のみを出力する (Linux)

  3. Linux seq コマンドで IP アドレスの範囲を出力する方法

  1. Ardourを使用してLinuxで音楽を作成する

  2. LinuxでAudacityを使用してオーディオを編集する

  3. Flatpakを使用してLinuxにアプリをインストールする