কনসোল অ্যাপ্লিকেশনটিতে একটি চিত্র প্রদর্শন করুন


86

আমার কাছে একটি কনসোল অ্যাপ্লিকেশন রয়েছে যা চিত্রগুলি পরিচালনা করে। এখন আমার কনসোল অ্যাপ্লিকেশনটির মধ্যে চিত্রগুলির পূর্বরূপের মতো কিছু দরকার। এগুলি কনসোলে প্রদর্শন করার কোনও উপায় আছে কি?

এখানে বর্তমান চরিত্র ভিত্তিক উত্তরের তুলনা করা হল:

ইনপুট:

এখানে চিত্র বর্ণনা লিখুন

আউটপুট:

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন


কনসোলটিতে, কনসোল উইন্ডো হিসাবে? না, আপনি আলাদা ডায়ালগ / উইন্ডো শুরু করতে পারেন।
খ্রিস্টান.কে

কনসোল অ্যাপ্লিকেশনগুলি কেবলমাত্র পাঠ্য অ্যাপ্লিকেশনগুলির জন্য ব্যবহৃত হয়। কোনও চিত্র প্রদর্শন করার কোনও উপায় নেই। আপনি অন্য একটি অ্যাপ্লিকেশন চালু করতে পারেন যা চিত্রটি প্রদর্শন করে। এই অন্যান্য অ্যাপ্লিকেশনটির একটি চিত্র পাস করার জন্য সম্ভবত একটি কমান্ড লাইন বিকল্পটি সমর্থন করা দরকার।
লিন্ডোস পেচোস

আপনি কেন কনসোল অ্যাপ্লিকেশন ব্যবহার করবেন? কোথায় চলে? আপনি সর্বদা আপনার নিজের নিজস্ব ডিফল্ট চিত্র দর্শক বা একটি উইনফর্মস ইত্যাদি অ্যাপ আনার জন্য একটি প্রক্রিয়া শুরু করতে পারেন ..
তাউব

4
আমার আন্তোনে লেজসেকের কোডটির উন্নতি প্রয়োজন (যা দুর্দান্ত)। কয়েকটি রঙ-মিসম্যাচ রয়েছে এবং উন্নত পারফরম্যান্সের সাথে আমি খুব অ্যানিমেটেড
জিআইএফও

উত্তর:


58

আমি আরও @ ডিটারমিমেকেনের কোড দিয়ে খেলি। আমি উল্লম্ব রেজোলিউশন অর্ধেক রেখেছি এবং via এর মধ্য দিয়ে কিছুটা যুক্ত করেছি ░▒▓ বামদিকে ডিয়েটার মেমকেন ফলাফল, ডানদিকে আমার। নীচের অংশে আউটপুটটির সাথে রাগলি ম্যাচ করতে আসল চিত্রটির আকার পরিবর্তন করা হয়েছে। আউটপুট ফলাফল যদিও মালউইন রূপান্তর ফাংশনটি চিত্তাকর্ষক, তবে এটি ধূসর রঙের সমস্ত ধরণের রঙ ব্যবহার করে না।

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);

সম্পাদনা

রঙের দূরত্ব জটিল বিষয় ( এখানে , এখানে এবং সেই পৃষ্ঠাগুলিতে লিঙ্কগুলি ...)। আমি YUV- এ দূরত্ব গণনা করার চেষ্টা করেছি এবং ফলাফলগুলি আরজিবির চেয়ে খারাপ ছিল। ল্যাব এবং ডেল্টা দিয়ে তারা আরও ভাল হতে পারে তবে আমি এটি চেষ্টা করি নি। আরজিবিতে দূরত্ব যথেষ্ট ভাল বলে মনে হচ্ছে। আসলে আরজিবি রঙের জায়গাতে ইউক্লিডিয়ান এবং ম্যানহাটনের দূরত্ব উভয়ের জন্য ফলাফলগুলি খুব অনুকরণীয়, তাই আমি সন্দেহ করি যে চয়ন করার জন্য খুব কম রঙ রয়েছে।

বাকিগুলি হ'ল রঙ এবং নিদর্শনগুলির সমস্ত সংমিশ্রণের সাথে রঙের তুলনা করা (নিদর্শনগুলি) নিষ্ঠুর বলের। আমি 1/4, 2/4, 3/4 এবং 4/4 এর জন্য পূরণ অনুপাত বলেছি। সেক্ষেত্রে তৃতীয় প্রতীকটি আসলে প্রথমটির কাছে অপ্রয়োজনীয়। তবে যদি অনুপাতগুলি এ জাতীয় অভিন্ন না হয় (ফন্টের উপর নির্ভর করে), ফলাফল পরিবর্তন হতে পারে, তাই ভবিষ্যতের উন্নতির জন্য আমি এটি সেখানে রেখেছি। প্রতীকের গড় রঙ পূরণ করা অনুপাত অনুসারে অগ্রভাগী রঙ এবং ব্যাকগ্রাউন্ড কালারের ওজনের গড় হিসাবে গণনা করা হয়। এটি লিনিয়ার রঙগুলি ধরে নিয়েছে, এটি বড় সরলকরণ কী। সুতরাং এখনও উন্নতির জন্য জায়গা আছে।


আপনাকে @ ফুবু ধন্যবাদ বিটিডব্লিউ আমি গামা সংশোধিত আরজিবি এবং ল্যাব নিয়ে পরীক্ষা-নিরীক্ষা করেছি এবং উভয়েরই উন্নতি হয়েছে। তবে পূরণের অনুপাতটি ব্যবহৃত ফন্টের সাথে মেলে সেট করতে হয়েছিল এবং ট্রুয়েটাইপ ফন্টের জন্য এটি মোটেও কাজ করে না। সুতরাং এটি আর এক আকারের সমস্ত সমাধানের জন্য ফিট করে না।
আন্তোনন লেজসেক

90

কনসোলে কোনও চিত্র দেখানো কনসোলের উদ্দেশ্যে ব্যবহার নয়, আপনি অবশ্যই অন্যান্য জিনিসগুলি হ্যাক করতে পারেন, কারণ কনসোল উইন্ডোটি অন্য উইন্ডোগুলির মতো একটি উইন্ডো মাত্র।

আসলে, একবার আমি গ্রাফিক্স সমর্থন সহ কনসোল অ্যাপ্লিকেশনগুলির জন্য একটি পাঠ্য নিয়ন্ত্রণের লাইব্রেরি বিকাশ শুরু করেছি। আমি কখনই এটি শেষ করিনি, যদিও আমার কাছে ধারণার ডেমো-র কার্যকারী প্রমাণ রয়েছে:

চিত্র সহ পাঠ্য নিয়ন্ত্রণ

এবং যদি আপনি কনসোল ফন্টের আকার পান তবে আপনি চিত্রটি খুব স্পষ্টভাবে রাখতে পারেন।

এইভাবে আপনি এটি করতে পারেন:

static void Main(string[] args)
{
    Console.WriteLine("Graphics in console window!");

    Point location = new Point(10, 10);
    Size imageSize = new Size(20, 10); // desired image size in characters

    // draw some placeholders
    Console.SetCursorPosition(location.X - 1, location.Y);
    Console.Write(">");
    Console.SetCursorPosition(location.X + imageSize.Width, location.Y);
    Console.Write("<");
    Console.SetCursorPosition(location.X - 1, location.Y + imageSize.Height - 1);
    Console.Write(">");
    Console.SetCursorPosition(location.X + imageSize.Width, location.Y + imageSize.Height - 1);
    Console.WriteLine("<");

    string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonPictures), @"Sample Pictures\tulips.jpg");
    using (Graphics g = Graphics.FromHwnd(GetConsoleWindow()))
    {
        using (Image image = Image.FromFile(path))
        {
            Size fontSize = GetConsoleFontSize();

            // translating the character positions to pixels
            Rectangle imageRect = new Rectangle(
                location.X * fontSize.Width,
                location.Y * fontSize.Height,
                imageSize.Width * fontSize.Width,
                imageSize.Height * fontSize.Height);
            g.DrawImage(image, imageRect);
        }
    }
}

আপনি কীভাবে বর্তমান কনসোল হরফ আকার পেতে পারেন তা এখানে:

private static Size GetConsoleFontSize()
{
    // getting the console out buffer handle
    IntPtr outHandle = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, 
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        IntPtr.Zero,
        OPEN_EXISTING,
        0,
        IntPtr.Zero);
    int errorCode = Marshal.GetLastWin32Error();
    if (outHandle.ToInt32() == INVALID_HANDLE_VALUE)
    {
        throw new IOException("Unable to open CONOUT$", errorCode);
    }

    ConsoleFontInfo cfi = new ConsoleFontInfo();
    if (!GetCurrentConsoleFont(outHandle, false, cfi))
    {
        throw new InvalidOperationException("Unable to get font information.");
    }

    return new Size(cfi.dwFontSize.X, cfi.dwFontSize.Y);            
}

এবং প্রয়োজনীয় অতিরিক্ত WinApi কল, ধ্রুবক এবং প্রকারগুলি:

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetConsoleWindow();

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(
    string lpFileName,
    int dwDesiredAccess,
    int dwShareMode,
    IntPtr lpSecurityAttributes,
    int dwCreationDisposition,
    int dwFlagsAndAttributes,
    IntPtr hTemplateFile);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetCurrentConsoleFont(
    IntPtr hConsoleOutput,
    bool bMaximumWindow,
    [Out][MarshalAs(UnmanagedType.LPStruct)]ConsoleFontInfo lpConsoleCurrentFont);

[StructLayout(LayoutKind.Sequential)]
internal class ConsoleFontInfo
{
    internal int nFont;
    internal Coord dwFontSize;
}

[StructLayout(LayoutKind.Explicit)]
internal struct Coord
{
    [FieldOffset(0)]
    internal short X;
    [FieldOffset(2)]
    internal short Y;
}

private const int GENERIC_READ = unchecked((int)0x80000000);
private const int GENERIC_WRITE = 0x40000000;
private const int FILE_SHARE_READ = 1;
private const int FILE_SHARE_WRITE = 2;
private const int INVALID_HANDLE_VALUE = -1;
private const int OPEN_EXISTING = 3;

এবং ফলাফল:

[কনসোল গ্রাফিক্স


4
বাহ, এটা সত্যিই আকর্ষণীয়! আপনি দয়া করে আপনার বোঝাতে চাইছেন এমন কিছুটা ব্যাখ্যা করতে পারেন যে আমি কখনই এটি শেষ করিনি, যদিও আমার কাছে কার্য-ধারণার ডেমো রয়েছে ? কোন ত্রুটি বা শুধু নিখোঁজ পোলিশ ..?
তাউ

এর অর্থ প্রকল্পটি খুব অসম্পূর্ণ। আমি মৌলিক স্থাপত্য, বেস ঘটনা-চালিত OO যেমন পণ্য পরিবেশ, মাউস সমর্থন, বার্তা পাম্প, ইত্যাদি কিন্তু যেমন এমনকি সবচেয়ে মৌলিক নিয়ন্ত্রণ প্রণীত Button, TextBoxএখনো নিখোঁজ ইত্যাদি। আমার স্বপ্নটি ডেটা বাঁধাইয়ের সাথে এবং ডাব্লুপিএফ-এর মতো "যে কোনও কিছুতে এম্বেড করুন" দর্শনের সাথে মোটামুটি সম্পূর্ণ এক্সএএমএল সমর্থন করা। তবে আমি এ থেকে খুব দূরে আছি ... ঠিক আছে, এই মুহুর্তে :)
গাইরিজিয়ান কাসজেগ

4
ঠিক আছে, আমি দেখছি, তবে কোডটি দেখে মনে হচ্ছে এটি কোনও কম, কম উচ্চাকাঙ্ক্ষী প্রকল্পের জন্য ব্যবহার করা যেতে পারে, হ্যাঁ?
তাউ

4
ভাল, তার বর্তমান ফর্ম ... আসলে না। তবে আমি একবার এটিকে কিছুটা স্থিতিশীল এবং সুসংহত করে তুললে গিটহাবে প্রকাশের পরিকল্পনা করি।
গিরিগেস কাসেজেগ

এটি নিয়ন্ত্রণহীন ডিএলএল ব্যবহারের প্রয়োজনীয়তা বাদে সত্যিই দুর্দান্ত দেখাচ্ছে। এছাড়াও, আমরা কীভাবে গ্রন্থাগারগুলির বিকাশের উপর নজর রাখতে পারি?
এয়ারউইগ

57

যদি আপনি দুবার ASCII 219 (█) ব্যবহার করেন তবে আপনার কাছে পিক্সেলের মতো কিছু রয়েছে (██)। এখন আপনি পিক্সেলের পরিমাণ এবং আপনার কনসোল অ্যাপ্লিকেশনটিতে রঙের পরিমাণ দ্বারা সীমাবদ্ধ।

  • যদি আপনি ডিফল্ট সেটিংস রাখেন তবে আপনার প্রায় 39x39 পিক্সেল রয়েছে, যদি আপনি আরও চান তবে আপনি Console.WindowHeight = resSize.Height + 1;এবং এর সাথে আপনার কনসোলকে আকার পরিবর্তন করতে পারেন Console.WindowWidth = resultSize.Width * 2;

  • আপনাকে যতদূর সম্ভব চিত্রের দিক-অনুপাত রাখতে হবে, সুতরাং বেশিরভাগ ক্ষেত্রে আপনার 39x39 হবে না

  • মালউইন রূপান্তর System.Drawing.Colorকরতে একটি সম্পূর্ণ আন্ডাররেটেড পদ্ধতি পোস্ট করেছেSystem.ConsoleColor

সুতরাং আমার পদ্ধতির হবে

using System.Drawing;

public static int ToConsoleColor(System.Drawing.Color c)
{
    int index = (c.R > 128 | c.G > 128 | c.B > 128) ? 8 : 0;
    index |= (c.R > 64) ? 4 : 0;
    index |= (c.G > 64) ? 2 : 0;
    index |= (c.B > 64) ? 1 : 0;
    return index;
}

public static void ConsoleWriteImage(Bitmap src)
{
    int min = 39;
    decimal pct = Math.Min(decimal.Divide(min, src.Width), decimal.Divide(min, src.Height));
    Size res = new Size((int)(src.Width * pct), (int)(src.Height * pct));
    Bitmap bmpMin = new Bitmap(src, res);
    for (int i = 0; i < res.Height; i++)
    {
        for (int j = 0; j < res.Width; j++)
        {
            Console.ForegroundColor = (ConsoleColor)ToConsoleColor(bmpMin.GetPixel(j, i));
            Console.Write("██");
        }
        System.Console.WriteLine();
    }
}

তাই আপনি পারেন

ConsoleWriteImage(new Bitmap(@"C:\image.gif"));

নমুনা ইনপুট:

এখানে চিত্র বর্ণনা লিখুন

নমুনা আউটপুট:

এখানে চিত্র বর্ণনা লিখুন


7
@ উইলিওনকা_ডাইলিব্লাহ - এটি তাঁবুর দিন থেকে বেগুনি তাঁবু। ডুম নয়
ব্লাটজ

@ ব্ল্যাটজ0 আর মানে ডুমের মতো গ্রাফিক্স ... তেহ ব্লকে

4
সমস্ত ক্ষমা করা হয় :- পি। আপনার যদি কখনও সুযোগ থাকে তবে ডেটি চেষ্টা করুন যদি তাঁবুটি এটি দুর্দান্ত খেলা তবে এটি দুর্দান্ত।
ব্ল্যাটজ0

38

ঐটা মজা ছিল. ধন্যবাদ ফুবু , আমি আপনার সমাধানটি চেষ্টা করেছিলাম এবং 4 (2x2) দ্বারা পূর্বরূপের রেজোলিউশন বাড়িয়ে তুলতে সক্ষম হয়েছি।

আমি খুঁজে পেয়েছি, আপনি প্রতিটি পৃথক চর জন্য পটভূমি রঙ সেট করতে পারেন। সুতরাং, দুটি ASCII 219 (█) অক্ষর ব্যবহার না করে আমি ASCII 223 (▀) দুইবার বিভিন্ন অগ্রভাগ এবং ব্যাকগ্রাউন্ড কালার ব্যবহার করেছি। এটি বড় পিক্সেল (██) এর মতো 4 টি উপ-পিক্সেলে (▀▄) ভাগ করে।

এই উদাহরণে আমি উভয় চিত্র একে অপরের পাশে রেখেছি, যাতে আপনি পার্থক্যটি সহজেই দেখতে পান:

এখানে চিত্র বর্ণনা লিখুন

কোডটি এখানে:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace ConsoleWithImage
{
  class Program
  {

    public static void ConsoleWriteImage(Bitmap bmpSrc)
    {
        int sMax = 39;
        decimal percent = Math.Min(decimal.Divide(sMax, bmpSrc.Width), decimal.Divide(sMax, bmpSrc.Height));
        Size resSize = new Size((int)(bmpSrc.Width * percent), (int)(bmpSrc.Height * percent));
        Func<System.Drawing.Color, int> ToConsoleColor = c =>
        {
            int index = (c.R > 128 | c.G > 128 | c.B > 128) ? 8 : 0;
            index |= (c.R > 64) ? 4 : 0;
            index |= (c.G > 64) ? 2 : 0;
            index |= (c.B > 64) ? 1 : 0;
            return index;
        };
        Bitmap bmpMin = new Bitmap(bmpSrc, resSize.Width, resSize.Height);
        Bitmap bmpMax = new Bitmap(bmpSrc, resSize.Width * 2, resSize.Height * 2);
        for (int i = 0; i < resSize.Height; i++)
        {
            for (int j = 0; j < resSize.Width; j++)
            {
                Console.ForegroundColor = (ConsoleColor)ToConsoleColor(bmpMin.GetPixel(j, i));
                Console.Write("██");
            }

            Console.BackgroundColor = ConsoleColor.Black;
            Console.Write("    ");

            for (int j = 0; j < resSize.Width; j++)
            {
                Console.ForegroundColor = (ConsoleColor)ToConsoleColor(bmpMax.GetPixel(j * 2, i * 2));
                Console.BackgroundColor = (ConsoleColor)ToConsoleColor(bmpMax.GetPixel(j * 2, i * 2 + 1));
                Console.Write("▀");

                Console.ForegroundColor = (ConsoleColor)ToConsoleColor(bmpMax.GetPixel(j * 2 + 1, i * 2));
                Console.BackgroundColor = (ConsoleColor)ToConsoleColor(bmpMax.GetPixel(j * 2 + 1, i * 2 + 1));
                Console.Write("▀");
            }
            System.Console.WriteLine();
        }
    }

    static void Main(string[] args)
    {
        System.Console.WindowWidth = 170;
        System.Console.WindowHeight = 40;

        Bitmap bmpSrc = new Bitmap(@"image.bmp", true);

        ConsoleWriteImage(bmpSrc);

        System.Console.ReadLine();
    }
  }
}

উদাহরণটি চালানোর জন্য, বিটম্যাপ "ইমেজ.বিএমপি" এক্সিকিউটেবলের মতো একই ডিরেক্টরিতে থাকতে হবে। আমি কনসোলের আকার বাড়িয়েছি, পূর্বরূপটির আকার এখনও 39 এবং এটিতে পরিবর্তন করা যেতে পারে int sMax = 39;

টাফার থেকে সমাধানটিও খুব দুর্দান্ত। আপনারা দুজনেই আমার উপভোগ করেছেন ...


24

আমি পড়া ছিল রঙ স্পেস এবং ল্যাব স্থান একটি ভালো বিকল্প হতে আপনার জন্য প্রদর্শিত হবে (এই প্রশ্ন দেখুন: রং মধ্যে একটি সঠিক "দূরত্ব" খোঁজা এবং অ্যালগরিদম রঙের সাদৃশ্য চেক করতে )

উইকিপিডিয়া সিআইএলএবি পৃষ্ঠার উদ্ধৃতি দিয়ে , এই রঙের স্থানের সুবিধাগুলি হ'ল :

আরজিবি এবং সিএমওয়াইকে রঙের মডেলগুলির বিপরীতে ল্যাব রঙটি প্রায় মানুষের দৃষ্টিভঙ্গির জন্য ডিজাইন করা হয়েছে। এটি অনুধাবনযোগ্য অভিন্নতা অর্জনের উচ্চাকাঙ্ক্ষী এবং এর এল উপাদানটি স্বাচ্ছন্দ্যের সাথে মানুষের ধারণার সাথে ঘনিষ্ঠভাবে মেলে। সুতরাং, এ এবং বি উপাদানগুলিতে আউটপুট বক্ররেখা সংশোধন করে সঠিক রঙের ভারসাম্য সংশোধন করতে এটি ব্যবহার করা যেতে পারে।

রঙগুলির মধ্যে দূরত্ব পরিমাপ করতে আপনি ডেল্টা ই দূরত্ব ব্যবহার করতে পারেন ।

এই আপনি থেকে ভাল অনুমান করতে পারে Colorথেকে ConsoleColor:

প্রথমত, আপনি CieLabএই স্থানটিতে রঙ উপস্থাপন করতে কোনও শ্রেণি সংজ্ঞায়িত করতে পারেন :

public class CieLab
{
    public double L { get; set; }
    public double A { get; set; }
    public double B { get; set; }

    public static double DeltaE(CieLab l1, CieLab l2)
    {
        return Math.Pow(l1.L - l2.L, 2) + Math.Pow(l1.A - l2.A, 2) + Math.Pow(l1.B - l2.B, 2);
    }

    public static CieLab Combine(CieLab l1, CieLab l2, double amount)
    {
        var l = l1.L * amount + l2.L * (1 - amount);
        var a = l1.A * amount + l2.A * (1 - amount);
        var b = l1.B * amount + l2.B * (1 - amount);

        return new CieLab { L = l, A = a, B = b };
    }
}

দুটি স্থিতিশীল পদ্ধতি রয়েছে, একটি হ'ল ডেল্টা ই ( DeltaE) ব্যবহার করে দূরত্ব পরিমাপ করার জন্য এবং অন্যটি দুটি রঙের সংমিশ্রণে প্রতিটি রঙের কত পরিমাণ নির্দিষ্ট করে ( Combine)।

আর থেকে রুপান্তর জন্য RGBকরতে LABআপনি নিম্নলিখিত পদ্ধতি (থেকে ব্যবহার করতে পারেন এখানে ):

public static CieLab RGBtoLab(int red, int green, int blue)
{
    var rLinear = red / 255.0;
    var gLinear = green / 255.0;
    var bLinear = blue / 255.0;

    double r = rLinear > 0.04045 ? Math.Pow((rLinear + 0.055) / (1 + 0.055), 2.2) : (rLinear / 12.92);
    double g = gLinear > 0.04045 ? Math.Pow((gLinear + 0.055) / (1 + 0.055), 2.2) : (gLinear / 12.92);
    double b = bLinear > 0.04045 ? Math.Pow((bLinear + 0.055) / (1 + 0.055), 2.2) : (bLinear / 12.92);

    var x = r * 0.4124 + g * 0.3576 + b * 0.1805;
    var y = r * 0.2126 + g * 0.7152 + b * 0.0722;
    var z = r * 0.0193 + g * 0.1192 + b * 0.9505;

    Func<double, double> Fxyz = t => ((t > 0.008856) ? Math.Pow(t, (1.0 / 3.0)) : (7.787 * t + 16.0 / 116.0));

    return new CieLab
    {
        L = 116.0 * Fxyz(y / 1.0) - 16,
        A = 500.0 * (Fxyz(x / 0.9505) - Fxyz(y / 1.0)),
        B = 200.0 * (Fxyz(y / 1.0) - Fxyz(z / 1.0890))
    };
}

ধারণাটি হ'ল @ অ্যান্টোনিনলেজেক ডু ('█', '▓', '▒', '░') এর মতো ছায়াযুক্ত অক্ষর ব্যবহার করুন, এটি আপনাকে কনসোল রঙগুলির সমন্বয় ( Combineপদ্ধতি ব্যবহার করে ) 16 টিরও বেশি রঙ পেতে দেয় ।

এখানে, রঙগুলি ব্যবহার করার জন্য প্রাক-গণনা করে আমরা কিছু উন্নতি করতে পারি:

class ConsolePixel
{
    public char Char { get; set; }

    public ConsoleColor Forecolor { get; set; }
    public ConsoleColor Backcolor { get; set; }
    public CieLab Lab { get; set; }
}

static List<ConsolePixel> pixels;
private static void ComputeColors()
{
    pixels = new List<ConsolePixel>();

    char[] chars = { '█', '▓', '▒', '░' };

    int[] rs = { 0, 0, 0, 0, 128, 128, 128, 192, 128, 0, 0, 0, 255, 255, 255, 255 };
    int[] gs = { 0, 0, 128, 128, 0, 0, 128, 192, 128, 0, 255, 255, 0, 0, 255, 255 };
    int[] bs = { 0, 128, 0, 128, 0, 128, 0, 192, 128, 255, 0, 255, 0, 255, 0, 255 };

    for (int i = 0; i < 16; i++)
        for (int j = i + 1; j < 16; j++)
        {
            var l1 = RGBtoLab(rs[i], gs[i], bs[i]);
            var l2 = RGBtoLab(rs[j], gs[j], bs[j]);

            for (int k = 0; k < 4; k++)
            {
                var l = CieLab.Combine(l1, l2, (4 - k) / 4.0);

                pixels.Add(new ConsolePixel
                {
                    Char = chars[k],
                    Forecolor = (ConsoleColor)i,
                    Backcolor = (ConsoleColor)j,
                    Lab = l
                });
            }
        }
}

আর একটি উন্নতি ব্যবহারের LockBitsপরিবর্তে চিত্রের ডেটাতে সরাসরি অ্যাক্সেস হতে পারে GetPixel

আপডেট : চিত্রটিতে একই রঙের অংশ থাকলে আপনি পৃথক অক্ষরের পরিবর্তে একই বর্ণযুক্ত অক্ষরের অঙ্কন প্রক্রিয়াটি যথেষ্ট গতিতে করতে পারেন:

public static void DrawImage(Bitmap source)
{
    int width = Console.WindowWidth - 1;
    int height = (int)(width * source.Height / 2.0 / source.Width);

    using (var bmp = new Bitmap(source, width, height))
    {
        var unit = GraphicsUnit.Pixel;
        using (var src = bmp.Clone(bmp.GetBounds(ref unit), PixelFormat.Format24bppRgb))
        {
            var bits = src.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, src.PixelFormat);
            byte[] data = new byte[bits.Stride * bits.Height];

            Marshal.Copy(bits.Scan0, data, 0, data.Length);

            for (int j = 0; j < height; j++)
            {
                StringBuilder builder = new StringBuilder();
                var fore = ConsoleColor.White;
                var back = ConsoleColor.Black;

                for (int i = 0; i < width; i++)
                {
                    int idx = j * bits.Stride + i * 3;
                    var pixel = DrawPixel(data[idx + 2], data[idx + 1], data[idx + 0]);


                    if (pixel.Forecolor != fore || pixel.Backcolor != back)
                    {
                        Console.ForegroundColor = fore;
                        Console.BackgroundColor = back;
                        Console.Write(builder);

                        builder.Clear();
                    }

                    fore = pixel.Forecolor;
                    back = pixel.Backcolor;
                    builder.Append(pixel.Char);
                }

                Console.ForegroundColor = fore;
                Console.BackgroundColor = back;
                Console.WriteLine(builder);
            }

            Console.ResetColor();
        }
    }
}

private static ConsolePixel DrawPixel(int r, int g, int b)
{
    var l = RGBtoLab(r, g, b);

    double diff = double.MaxValue;
    var pixel = pixels[0];

    foreach (var item in pixels)
    {
        var delta = CieLab.DeltaE(l, item.Lab);
        if (delta < diff)
        {
            diff = delta;
            pixel = item;
        }
    }

    return pixel;
}

অবশেষে, এর DrawImageমতো কল করুন :

static void Main(string[] args)
{
    ComputeColors();

    Bitmap image = new Bitmap("image.jpg", true);
    DrawImage(image);

}

ফলাফল চিত্রসমূহ:

কনসোল 1

কনসোল 2



নিম্নলিখিত সমাধানগুলি অক্ষরের উপর ভিত্তি করে নয় তবে সম্পূর্ণ বিশদ চিত্র সরবরাহ করে


কোনও বস্তু তৈরি করতে আপনি কোনও উইন্ডোটির হ্যান্ডলারটি ব্যবহার করে আঁকতে পারেন Graphics। কনসোল অ্যাপ্লিকেশনটির হ্যান্ডলারটি পেতে আপনি এটি আমদানি করতে পারেন GetConsoleWindow:

[DllImport("kernel32.dll", EntryPoint = "GetConsoleWindow", SetLastError = true)]
private static extern IntPtr GetConsoleHandle();

তারপরে, হ্যান্ডলারের সাহায্যে একটি গ্রাফিক তৈরি করুন (ব্যবহার করে Graphics.FromHwnd) এবং Graphicsঅবজেক্টের পদ্ধতি ব্যবহার করে চিত্রটি আঁকুন , উদাহরণস্বরূপ:

static void Main(string[] args)
{            
    var handler = GetConsoleHandle();

    using (var graphics = Graphics.FromHwnd(handler))
    using (var image = Image.FromFile("img101.png"))
        graphics.DrawImage(image, 50, 50, 250, 200);
}

সংস্করণ 1

এটি দুর্দান্ত দেখায় তবে কনসোলটির আকার পরিবর্তন বা স্ক্রোল করা থাকলে উইন্ডোজ সতেজ হওয়ার কারণে চিত্রটি অদৃশ্য হয়ে যায় (সম্ভবত আপনার ক্ষেত্রে চিত্র পুনর্নির্মাণের জন্য কোনও ধরণের প্রক্রিয়া প্রয়োগ করা সম্ভব))


অন্য সমাধানটি Formকনসোল অ্যাপ্লিকেশনটিতে একটি উইন্ডো ( ) এম্বেড করা। এটি করতে আপনাকে আমদানি করতে হবে SetParent(এবং MoveWindowকনসোলের ভিতরে উইন্ডোটি স্থানান্তর করতে হবে):

[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

তারপরে আপনাকে কেবল একটি তৈরি করতে এবং পছন্দসই চিত্রটিতে সম্পত্তি Formসেট BackgroundImageকরতে হবে (এটি একটিতে করুন Threadবা Taskকনসোলটি ব্লক করা এড়াতে):

static void Main(string[] args)
{
    Task.Factory.StartNew(ShowImage);

    Console.ReadLine();
}

static void ShowImage()
{
    var form = new Form
    {                
        BackgroundImage = Image.FromFile("img101.png"),
        BackgroundImageLayout = ImageLayout.Stretch
    };

    var parent = GetConsoleHandle();
    var child = form.Handle;

    SetParent(child, parent);
    MoveWindow(child, 50, 50, 250, 200, true);

    Application.Run(form);
}

সংস্করণ 2

অবশ্যই আপনি FormBorderStyle = FormBorderStyle.Noneউইন্ডোস বর্ডারগুলি লুকানোর জন্য সেট করতে পারেন (ডান চিত্র)

এই ক্ষেত্রে আপনি কনসোলটির আকার পরিবর্তন করতে পারেন এবং চিত্র / উইন্ডোটি এখনও সেখানে থাকবে।

এই পদ্ধতির সাথে একটি সুবিধা হ'ল আপনি যে উইন্ডোটি চান তা সন্ধান করতে পারেন এবং যে কোনও সময়ে কেবল BackgroundImageসম্পত্তি পরিবর্তন করে চিত্রটি পরিবর্তন করতে পারেন ।


আপনার প্রচেষ্টার জন্য আপনাকে ধন্যবাদ তবে আপনি অ্যান্টোন লেজসেকের সমাধানের চেয়ে 6x কম ধীরে ধীরে এগিয়ে যান। যাইহোক খুব আকর্ষণীয় ল্যাপ ফলাফল।
বাইও

4

সরাসরি কোন উপায় নেই। কিন্তু আপনার মত একটি চিত্র-টু-ASCII অত্যাধুনিক কনভার্টার ব্যবহার করতে চেষ্টা করতে পারেন এই এক


:-) তবে মনে রাখবেন যে কনসোল (উইন্ডোর) রঙের ক্ষমতাগুলিও বেশ সীমাবদ্ধ। সুতরাং "বিবর্ণ" প্রভাবগুলি ইত্যাদিও সম্ভব নয়।
খ্রিস্টান.কে

4
ঠিক আছে, এটি রেজোলিউশনের সাথে মেলে: পি
ডার্কওয়ানডেরার

4
@ ক্রিশ্চিয়ান.কে অ্যান্টোন লেজসেকের উত্তর বিবর্ণ হওয়া সম্ভব করে
বাইয়ো

0

হ্যাঁ, আপনি যদি Formকনসোল অ্যাপ্লিকেশনটির মধ্যে থেকে কোনও প্রশ্নটি খানিকটা প্রসারিত করেন তবে আপনি এটি করতে পারেন ।

আপনি কীভাবে অ্যাপ্লিকেশনটিকে একটি ফর্ম খুলতে এবং একটি চিত্র প্রদর্শন করতে পারেন তা এখানে:

  • আপনার প্রকল্পে এই দুটি উল্লেখ অন্তর্ভুক্ত করুন: System.DrawingএবংSystem.Windows.Forms
  • পাশাপাশি দুটি নামস্থানও অন্তর্ভুক্ত করুন:

using System.Windows.Forms;
using System.Drawing;

কিভাবে যে এই পোস্টে দেখুন !

এই জাতীয় কিছু যুক্ত করার জন্য এখন আপনার যা দরকার তা হল:

Form form1 = new Form();
form1.BackgroundImage = bmp;
form1.ShowDialog();

অবশ্যই আপনি একটি ব্যবহার করতে পারেন PictureBox..

এবং form1.Show();প্রাকদর্শন দেখানোর সময় আপনি কনসোলটি বাঁচিয়ে রাখতে ব্যবহার করতে পারেন ..

আসল পোস্ট: অবশ্যই আপনি 25x80 উইন্ডোর ভিতরে কোনও চিত্র সঠিকভাবে প্রদর্শন করতে পারবেন না ; এমনকি যদি আপনি একটি বৃহত্তর উইন্ডো এবং ব্লক গ্রাফিক ব্যবহার করেন তবে এটি পূর্বরূপ নয় বরং একটি জগাখিচুড়ি!

আপডেট: দেখে মনে হচ্ছে আপনি সমস্ত জিডিআই পরে কনসোল ফর্মটিতে একটি চিত্র আঁকতে পারেন; টাফারের উত্তর দেখুন!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.