2015-11-05 4 views
75

У меня есть консольное приложение, которое управляет изображениями. Теперь мне нужно что-то вроде предварительного просмотра изображений в консольном приложении. Есть ли способ отобразить их в консоли?Показать изображение в консольном приложении

Вот сравнение текущих ответов на основе характера:

Вход:

enter image description here

Выход:

enter image description here

enter image description here

enter image description here

enter image description here

+0

В консоли, как в окне консоли? Нет. Однако вы можете запустить отдельный диалог/окно. –

+0

Консольные приложения используются в основном для текстовых приложений. Невозможно отобразить изображение. Вы можете запустить другое приложение, которое отображает изображение. Для этого другого приложения, скорее всего, потребуется поддержка опции командной строки для передачи изображения на нее. –

+0

Почему вы используете консольное приложение? Где это работает? вы всегда можете запустить процесс, чтобы открыть средство просмотра изображений по умолчанию или просто приложение winforms и т. д. – TaW

ответ

47

Далее я играл с кодом от @DieterMeemken. Я уменьшил вдвое вертикальное разрешение и добавил сглаживание через ░▒▓. Слева - результат Дитера Меменка, справа мой. На нижней части находится исходное изображение, измененное по размеру, чтобы точно соответствовать выходному значению. Output result Хотя функция преобразования Malwyns впечатляет, она не использует все серые цвета, что жалко.

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

Цвет расстояние сложная тема (here, here и ссылки на этих страницах ...). Я попытался рассчитать расстояние в YUV, и результаты оказались хуже, чем в RGB. Они могут быть лучше с Lab и DeltaE, но я этого не делал. Расстояние в RGB кажется достаточно хорошим. Фактически результаты очень похожи на эвклидовое и манхэттенское расстояние в цветовом пространстве RGB, поэтому я подозреваю, что на выбор слишком мало цветов.

Остальное - это просто грубая сила сравнения цвета со всеми комбинациями цветов и узоров (= символы). Я сказал, что коэффициент заполнения для ░▒▓█ равен 1/4, 2/4, 3/4 и 4/4. В этом случае третий символ фактически избыточен для первого. Но если коэффициенты не были такими единообразными (зависит от шрифта), результаты могут измениться, поэтому я оставил его там для будущих улучшений. Средний цвет символа рассчитывается как взвешенное среднее значение foregroudColor и backgroundColor в соответствии с коэффициентом заполнения. Он предполагает линейные цвета, что также является большим упрощением. Таким образом, есть еще место для улучшения.

+0

Спасибо @fubo. Кстати, я экспериментировал с гамма-коррекцией RGB и Lab, и оба были улучшения. Но коэффициент заполнения должен был быть установлен в соответствии с используемым шрифтом, и он не работал вообще для шрифтов truetype. Таким образом, он больше не будет одного размера, соответствующего разрешению. –

4

Там нет прямого пути. Но вы можете попытаться использовать конвертер image-to-ascii-art, например this one

+0

:-), но обратите внимание, что возможности цвета консоли (окна) также довольно ограничены. Таким образом, эффекты «затухания» и т. Д. Даже невозможны. –

+1

Ну, это соответствует разрешению: P – DarkWanderer

+1

@ Christian.K Ответ Антонина Лейсека делает возможным затухание – Byyo

1

Да, вы можете это сделать, если немного растянуть вопрос, открыв Form из приложения Консоль.

Вот как вы можете иметь вы консольное приложение открыть форму и отобразить изображение:

  • включить эти две ссылки в вашем проекте: System.Drawing и System.Windows.Forms
  • включает два пространства имен, а также:

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

См this post on how to do that!

Теперь все, что вам нужно, чтобы добавить что-то вроде этого:

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

Конечно, вы можете также использовать PictureBox ..

И вы можете использовать form1.Show(); держать консоль жив в то время как просмотр показывает ..

Оригинальное сообщение: конечно, вы не можете правильно отобразить изображение внутри, окном 25x80; даже если вы используете большее окно и блокируете графику, это будет не предварительный просмотр, а беспорядок!

Обновление: Похоже, что вы все-таки можете GDI-нарисовать изображение на Консольной форме; см. ответ taffer!

53

Если вы используете ASCII 219 (█) дважды, у вас есть что-то вроде пикселя (██). Теперь вы ограничены количеством пикселей и количеством цветов в консольном приложении.

  • , если сохранить настройки по умолчанию у вас есть около 39x39 пикселей, если вы хотите больше вы можете изменить вашу консоль с Console.WindowHeight = resSize.Height + 1; и Console.WindowWidth = resultSize.Width * 2;

  • вы должны держать коэффициент пропорциональности на изображении, как, насколько это возможно, так что вы не будете иметь 39x39 в большинстве случаев

  • Malwyn опубликовал совершенно недооцененный метод для преобразования System.Drawing.Color в System.ConsoleColor

так что мой подход был бы

using System.Drawing; 

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); 
    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("██"); 
     } 
     System.Console.WriteLine(); 
    } 
} 

так что вы можете

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

вход образца:

enter image description here

Пример вывода:

enter image description here

+0

Doom! ахх хорошие времена –

+7

@willywonka_dailyblah - Это фиолетовое щупальце от Дня щупальца. Not Doom – Blaatz0r

+0

@ Blaatz0r я имею в виду Doom-подобную графику ... imma new kid on the block Я знаю только Doom –

77

Хотя показ изображения в консоли не предназначен для использования в консоли, вы можете, конечно, взломать вещи, поскольку окно консоли - это просто окно, как и любые другие окна.

Фактически, как только я начал разрабатывать библиотеку текстовых элементов управления для консольных приложений с поддержкой графики. Я никогда не заканчивал, что, хотя у меня есть рабочий доказательство о концепции демо:

Text controls with image

И если вы получите размер шрифта консоли, вы можете поместить изображение очень точно.

Это, как вы можете это сделать:

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; 

И результат:

[Graphics in Console

+2

Ничего себе, это действительно интересно! Не могли бы вы рассказать немного о том, что вы подразумеваете под _I, я никогда не закончил это, хотя у меня есть демонстрация пробной версии? Любые недостатки или просто недостающий лак ..? – TaW

+0

Это означает, что проект очень неполный. Я создал базовую архитектуру, основанную на событиях среду OO, поддержку мыши, насос сообщений и т. Д.Но даже самые фундаментальные элементы управления, такие как 'Button',' TextBox' и т. Д., Все еще отсутствуют. Моя мечта - сделать довольно полную поддержку XAML с привязкой данных и с WPF-подобной философией «внедрить что-нибудь во что-нибудь». Но я очень далек от этого ... ну, в этот момент :) – taffer

+3

ОК, я вижу, но код выглядит так, как будто он может быть использован для любого менее полного, менее амбициозного проекта, да? – TaW

35

Это было весело. Спасибо fubo, я попробовал ваше решение и смог увеличить разрешение предварительного просмотра на 4 (2x2).

Я обнаружил, что вы можете установить цвет фона для каждого отдельного символа. Итак, вместо использования двух символов ASCII 219 (█) я использовал ASCII 223 (▀) два раза с разными цветами переднего и заднего плана. Это делит большой пиксель (██) на 4 подпикселя, подобный этому (▀▄).

В этом примере я поставил оба изображения рядом друг с другом, так что вы можете увидеть разницу легко:

enter image description here

Вот код:

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

Чтобы запустить пример, битмап «image.bmp» должен находиться в том же каталоге, что и исполняемый файл. Я увеличил размер консоли, размер предварительного просмотра по-прежнему равен 39 и может быть изменен на int sMax = 39;.

Решение от taffer также очень круто. У вас есть мой верхний ...

18

Я читал о цветовых пространствах и LAB пространства, кажется, хороший вариант для вас (см этих вопросов: Finding an accurate “distance” between colors и Algorithm to check similarity of colors)

Цитирования Википедии CIELAB страницы, преимущество этого цветового пространства :

В отличие от цветовых моделей RGB и CMYK, цвет Lab предназначен для приближения человеческого зрения. Он стремится к единообразию восприятия, а его компонент L близко соответствует восприятию человеком легкости. Таким образом, его можно использовать для точной коррекции цветового баланса путем изменения выходных кривых в компонентах a и b.

Чтобы измерить расстояние между цветами, вы можете использовать расстояние Delta E.

С этим можно аппроксимировать лучше от 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 }; 
    } 
} 

Есть два статических метода, один для измерения расстояние, используя Delta E (DeltaE) и другие, чтобы объединить два цвета, указав, сколько из каждого цвета (Combine).

И для преобразования из RGB в LAB вы можете использовать следующий метод (от here):

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

Идея является использование тени, как символы @AntoninLejsek сделать ('█', '▓', «▒ ',' ░ '), это позволяет получить более 16 цветов, сочетающих цвета консоли (с использованием метода Combine).

Здесь мы можем сделать некоторые улучшения путем предварительного вычисления цвета использовать:

Другое усовершенствование может быть доступ непосредственно данные изображения, используя LockBits вместо использования GetPixel.

UPDATE: Если изображение имеет детали с тем же цветом вы можете значительно ускорить процесс рисования кусок символов, имеющих одни и те же цвета, а не отдельных людей символов:

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

} 

Результат изображения:

Console1

Console2



Следующие решения не основаны на гольцов, но предоставляет полные детальные изображения


Вы можете рисовать поверх любого окна, используя его обработчик для создания a 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); 
} 

Version 1

Это выглядит хорошо, но если консоль изменяются или прокручивается, изображение исчезает, потому что окна обновляются (возможно осуществление некоторых к ind механизма для перерисовки изображения возможно в вашем случае).


Другим решением является встраивание окно (Form) в консольном приложении. Для этого нужно импортировать SetParentMoveWindow переместить окно внутри консоли):

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

Version2

конечно, вы можете установить FormBorderStyle = FormBorderStyle.None, чтобы скрыть границы окон (правое изображение)

В этом случае вы можете изменить размер консоли, а изображение/окно все еще должно быть там.

Одним из преимуществ такого подхода является то, что вы можете найти нужное окно и изменить изображение в любое время, просто изменив свойство BackgroundImage.

+0

Спасибо за ваши усилия, но вы приближаетесь на 6 раз медленнее, чем решение Антонина Лейсека. Во всяком случае очень интересный результат Lap. – Byyo

Смежные вопросы