1. ホーム
  2. c#

[解決済み] コンソールアプリケーションで画像を表示する

2023-03-28 03:45:50

質問

画像を管理するコンソールアプリケーションを持っています。今、私はコンソールアプリケーション内の画像のプレビューのようなものを必要としています。コンソールにそれらを表示する方法はありますか?

現在の文字ベースの回答との比較です。

入力です。

出力します。

どのように解決するのですか?

DieterMeemken氏のコードでさらに遊んでみました。垂直解像度を半分にし、░▓を介してディザリングを追加しました。左側がDieter Meemkenの結果で、右側が私の結果です。下は出力に大まかに合わせてリサイズした元画像です。 マルウィンの変換機能は素晴らしいのですが、すべてのグレーカラーを使うわけではないのが残念なところです。

static int[] cColors = { 0x000000, 0x000080, 0x008000, 0x008080, 0x800000, 0x800080, 0x808000, 0xC0C0C0, 0x808080, 0x0000FF, 0x00FF00, 0x00FFFF, 0xFF0000, 0xFF00FF, 0xFFFF00, 0xFFFFFF };

public static void ConsoleWritePixel(Color cValue)
{
    Color[] cTable = cColors.Select(x => Color.FromArgb(x)).ToArray();
    char[] rList = new char[] { (char)9617, (char)9618, (char)9619, (char)9608 }; // 1/4, 2/4, 3/4, 4/4
    int[] bestHit = new int[] { 0, 0, 4, int.MaxValue }; //ForeColor, BackColor, Symbol, Score

    for (int rChar = rList.Length; rChar > 0; rChar--)
    {
        for (int cFore = 0; cFore < cTable.Length; cFore++)
        {
            for (int cBack = 0; cBack < cTable.Length; cBack++)
            {
                int R = (cTable[cFore].R * rChar + cTable[cBack].R * (rList.Length - rChar)) / rList.Length;
                int G = (cTable[cFore].G * rChar + cTable[cBack].G * (rList.Length - rChar)) / rList.Length;
                int B = (cTable[cFore].B * rChar + cTable[cBack].B * (rList.Length - rChar)) / rList.Length;
                int iScore = (cValue.R - R) * (cValue.R - R) + (cValue.G - G) * (cValue.G - G) + (cValue.B - B) * (cValue.B - B);
                if (!(rChar > 1 && rChar < 4 && iScore > 50000)) // rule out too weird combinations
                {
                    if (iScore < bestHit[3])
                    {
                        bestHit[3] = iScore; //Score
                        bestHit[0] = cFore;  //ForeColor
                        bestHit[1] = cBack;  //BackColor
                        bestHit[2] = rChar;  //Symbol
                    }
                }
            }
        }
    }
    Console.ForegroundColor = (ConsoleColor)bestHit[0];
    Console.BackgroundColor = (ConsoleColor)bestHit[1];
    Console.Write(rList[bestHit[2] - 1]);
}


public static void ConsoleWriteImage(Bitmap source)
{
    int sMax = 39;
    decimal percent = Math.Min(decimal.Divide(sMax, source.Width), decimal.Divide(sMax, source.Height));
    Size dSize = new Size((int)(source.Width * percent), (int)(source.Height * percent));   
    Bitmap bmpMax = new Bitmap(source, dSize.Width * 2, dSize.Height);
    for (int i = 0; i < dSize.Height; i++)
    {
        for (int j = 0; j < dSize.Width; j++)
        {
            ConsoleWritePixel(bmpMax.GetPixel(j * 2, i));
            ConsoleWritePixel(bmpMax.GetPixel(j * 2 + 1, i));
        }
        System.Console.WriteLine();
    }
    Console.ResetColor();
}

の使い方を説明します。

Bitmap bmpSrc = new Bitmap(@"HuwnC.gif", true);    
ConsoleWriteImage(bmpSrc);

EDIT

色の距離は複雑なトピックです ( はこちら , ここ といったページへのリンクがあります...)。私はYUVで距離を計算しようとしましたが、結果はRGBの場合よりもむしろ悪かったです。LabとDeltaEを使えばもっと良くなるかもしれませんが、それは試していません。RGBでの距離は十分なようです。実際、RGB 色空間でのユークリッド距離とマンハッタン距離の両方で結果は非常によく似ているので、選択する色が少なすぎるだけだと思われます。

あとは、色とパターン(=記号)のすべての組み合わせに対して、色を総当たりで比較しただけです。私は░▒▓▓の塗りつぶし率を1/4、2/4、3/4、4/4と述べました。この場合、3つ目の記号は実際には1つ目の記号に対して冗長である。しかし、比率がそれほど均一でない場合(フォントに依存する)、結果が変わる可能性があるので、将来の改良のために残しておいたのである。シンボルの平均色は、塗りつぶし比率に応じた foregroudColor と backgroundColor の重量平均として計算されます。これは直線的な色を想定しているので、かなり単純化しています。まだまだ改良の余地がありそうです。