画像をANSIに変換する

これが誰にとって興味深いかわからないが、先日私は遊んで次のことをすることにした。



指定:640 x 400、フォント8 x 16の画像(BMPなど)



必要です:80 x 25文字の標準モードでANSI疑似グラフィックに変換するには、文字と背景に任意の色(トゥルーカラー)を設定できます。



画像



非常に良いコメントのおかげで、バージョンを更新しました: リンク

これを使用すると、次の写真について取得できます。 画像





16色の「真の」EGAテキストモードは、低解像度と文字サイズの大きさのために見た目が悪くなりすぎるため、機能しません。 2番目の引数:タスクは、フォントを減らしたり、解像度を上げたりすることができるため、画像を記号表現にできるだけ近づけてはなりません。 タスクは、上記のようなフィルターを作成することです。



ここでこれを公開する理由:初心者のプログラマーがアルゴリズムの理解を練習するのに役立つように思えたので、この資料をチュートリアルとしてマークしました。



実装には、ピクセルを取得してピクセルを取得できるグラフィックスを操作するための何らかの種類のライブラリが必要です。つまり、画面からピクセルの色を取得し、画面に指定の色でピクセルを描画します。 私は古いが実績のあるAllegroライブラリ(www.allegro.cc)を使用しています。これは使いやすく、さまざまなオペレーティングシステム(MSDOSでも!)で作業できます。



しかし、十分な言葉、それはビジネスへの時間です。



const int size_x=640; const int size_y=400; const int ascii_x=80; const int ascii_y=25;
      
      







画像のサイズとそのテキスト表現のサイズを決定する定数を設定します。



 for(int cx=0;cx<ascii_x;cx++) for(int cy=0;cy<ascii_y;cy++){ int fullr=0; int fullg=0; int fullb=0; int pixels=0; //find background color for(int i=0;i<size_x/ascii_x;i++) for(int j=0;j<size_y/ascii_y;j++){ int col=getpixel(pic,i+cx*size_x/ascii_x,j+cy*size_y/ascii_y); int r=getr(col); int g=getg(col); int b=getb(col); fullr+=r;fullg+=g;fullb+=b; pixels++; } fullr/=pixels;fullg/=pixels;fullb/=pixels;
      
      







メインサイクルを開始します。このサイクルでは、80〜25個のマトリックスの各シンボルが順番に検出されます。 次のサイクルは、画面上のこのマトリックスの特定のシンボルに対応する画像の領域の各ピクセルです。 ご想像のとおり、この領域は640/80 = 8 x 400/25 = 16ピクセルです。 ここで覚えておくと便利なのは、これがまさにフォントのサイズであることです。



この2番目のサイクルのタスクは、ANSIシンボルの背景色として設定する中間色を見つけることです。 これを行うのは非常に簡単です。R、G、Bコンポーネントの色をレイアウトし、それぞれの平均を計算します。



 //find ascii and its color int rms=100000000; for(int curch=1;curch<256;curch++){ //loop over ASCII table int charr=0; int charg=0; int charb=0; //find char color pixels=0; //number of pixels for char for(i=0;i<size_x/ascii_x;i++) for(int j=0;j<size_y/ascii_y;j++){ int col=getpixel(pic,i+cx*size_x/ascii_x,j+cy*size_y/ascii_y); int r=getr(col); int g=getg(col); int b=getb(col); int colch=getpixel(font,i+(curch%32)*8,j+(curch/32)*16); int rc=getr(colch); int gc=getg(colch); int bc=getb(colch); if(rc!=0&&gc!=0&&bc!=0){ //get actual char pixels only charr+=r; charg+=g; charb+=b; pixels++; } } if(pixels!=0){ charr/=pixels;charg/=pixels;charb/=pixels; }
      
      







さらに興味深い。 別のサイクルを挿入する必要があります-ASCIIテーブルの各文字(合計256個あります)。 フォントを使用して白黒の画像からそれらを取得します。つまり、理論的には、8 x 16の任意の画像をシンボルとして使用できます。 この場所では、文字の単一の領域(キリル文字など)のみに制限できるため、結果に大きく影響することに注意してください。



上記のコードでは、キャラクターの色を見つけます。 これを行うには、量を上記のように考慮しますが、わずかに変更します。ピクセルは、フォントの現在の文字であるマスクによって取得されます。 したがって、2番目の「中間色」は、文字自体が描画されるピクセルにのみ対応します。



また、このようなピクセルの数はゼロになる可能性があることに注意してください(たとえば、文字32はスペースです)。 これには注意する必要があります。



 //find rms int currms=0; for(i=0;i<size_x/ascii_x;i++) for(int j=0;j<size_y/ascii_y;j++){ int col=getpixel(pic,i+cx*size_x/ascii_x,j+cy*size_y/ascii_y); int r=getr(col); int g=getg(col); int b=getb(col); int rr=0,gg=0,bb=0; int colch=getpixel(font,i+(curch%32)*8,j+(curch/32)*16); int rc=getr(colch); int gc=getg(colch); int bc=getb(colch); if(rc!=0&&gc!=0&&bc!=0){ //char pixel rr=charr; gg=charg; bb=charb; } else{ //back pixel rr=fullr; gg=fullg; bb=fullb; } currms+=sqrt((r-rr)*(r-rr)+(g-gg)*(g-gg)+(b-bb)*(b-bb)); } if(currms<rms){ //find minimal rms findr=charr; findg=charg; findb=charb; findch=curch; rms=currms; if(DEBUG)printf("!!!%d %d\n",currms, curch); } else if(DEBUG)printf("%d %d\n",currms, curch); } //find char
      
      







さて、最後に、彼らは塩そのものに来ました。 このコードでは、画像の特定の領域のピクセルを再度調べ、背景色またはシンボルからの3つの色成分すべてのRMS(標準偏差)を考慮します(このピクセルが背景にあるかシンボルにあるかによって異なります)。 合計RMSは、特定の文字が画像の特定の領域にどれだけ適切に対応するかの基準になります。



以下は画面への出力です(2つのモード-背景ありと背景なし( ))が、ここではすべてが自明であるため、ここでは詳しく説明しません。



画像



プログラムとソースコードは、次の場所からダウンロードできます: dimouse.ru/data/ansiconv.rar (130 Kb)。



このケースをテキストモードで描画してみませんか? ご覧のとおり、プログラムは結果を含むファイルを作成します(新しいbmpを除く)。ascii。 ここで、各文字について、その値はASCIIテーブル、色、および背景の色に保存されます。 テキストモードにはpdcurses.sourceforge.netを使用します(何かもっとよく知っている場合はコメントに書いてください!)が、このライブラリはSDL(いずれにしてもWindowsバージョン-確かに)のラッパーですが、色を表示できません16:古代の重い遺産。 おそらく覚えているように、PDCursesは有名なInteractive FictionゲームCursesに由来します。 しかし、1人の友人がこのライブラリの改善を書いて、ここに投稿しました: www.projectpluto.com/win32a.htm



残念ながら、ビットマップフォントを使用することはできず、システムフォントのみを使用できます(ただし、いずれかを選択できます)。これにより、印象が多少損なわれます。 ただし、タスクは完了したと見なすこともできます。



asciiを読み取るためのプログラムは、こちらからダウンロードできます: dimouse.ru/data/ascii.rar (70 Kb)。



All Articles