ฉันมีแอปพลิเคชันคอนโซลที่จัดการรูปภาพ ตอนนี้ฉันต้องการบางอย่างเช่นการดูตัวอย่างรูปภาพภายในแอปพลิเคชันคอนโซล มีวิธีแสดงในคอนโซลหรือไม่?
นี่คือการเปรียบเทียบคำตอบตามอักขระปัจจุบัน:
อินพุต:
เอาท์พุต:
คำตอบ:
ฉันเล่นกับรหัสจาก @DieterMeemken เพิ่มเติม ฉันลดความละเอียดแนวตั้งลงครึ่งหนึ่งและเพิ่มการแยกทางผ่าน░▒▓ ทางด้านซ้ายคือผลลัพธ์ของ Dieter Meemken ทางด้านขวาของฉัน ด้านล่างเป็นภาพต้นฉบับที่ปรับขนาดให้ตรงกับเอาต์พุต แม้ว่าฟังก์ชั่นการแปลง 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);
แก้ไข
ระยะสีเป็นเรื่องที่ซับซ้อน ( ที่นี่ , ที่นี่และการเชื่อมโยงในหน้าเหล่านั้น ... ) ฉันพยายามคำนวณระยะทางใน YUV และผลลัพธ์ค่อนข้างแย่กว่าใน RGB พวกเขาน่าจะดีกว่าเมื่อใช้ Lab และ DeltaE แต่ฉันไม่ได้ลอง ระยะห่างใน RGB ดูเหมือนจะดีพอ ในความเป็นจริงผลลัพธ์มีความคล้ายคลึงกันมากสำหรับระยะห่างของยุคลิดและแมนฮัตตันในพื้นที่สี RGB ดังนั้นฉันจึงสงสัยว่ามีสีให้เลือกน้อยเกินไป
ส่วนที่เหลือเป็นเพียงการเปรียบเทียบสีกับการผสมสีและรูปแบบทั้งหมด (= สัญลักษณ์) ฉันระบุอัตราส่วนการเติมสำหรับ░▒▓█เป็น 1/4, 2/4, 3/4 และ 4/4 ในกรณีนี้ในความเป็นจริงสัญลักษณ์ที่สามซ้ำซ้อนกับสัญลักษณ์แรก แต่ถ้าอัตราส่วนไม่เท่ากัน (ขึ้นอยู่กับแบบอักษร) ผลลัพธ์อาจเปลี่ยนแปลงได้ดังนั้นฉันจึงปล่อยไว้ที่นั่นเพื่อปรับปรุงในอนาคต สีเฉลี่ยของสัญลักษณ์คำนวณตามน้ำหนักเฉลี่ยของ foregroudColor และ backgroundColor ตามอัตราส่วนการเติม มันถือว่าเป็นสีเชิงเส้นสิ่งที่ทำให้เข้าใจง่ายมาก ดังนั้นยังมีช่องว่างสำหรับการปรับปรุง
แม้ว่าการแสดงภาพในคอนโซลไม่ใช่การใช้งานคอนโซลตามที่ตั้งใจไว้ แต่คุณก็สามารถแฮ็กสิ่งต่างๆได้อย่างแน่นอนเนื่องจากหน้าต่างคอนโซลเป็นเพียงหน้าต่างเช่นเดียวกับหน้าต่างอื่น ๆ
จริงๆแล้วเมื่อฉันได้เริ่มพัฒนาไลบรารีควบคุมข้อความสำหรับแอปพลิเคชันคอนโซลที่รองรับกราฟิก ฉันไม่เคยทำสิ่งนั้นสำเร็จแม้ว่าฉันจะมีการสาธิตแนวคิดที่ใช้งานได้:
และหากคุณได้รับขนาดตัวอักษรคอนโซลคุณสามารถวางภาพได้อย่างแม่นยำ
นี่คือวิธีที่คุณสามารถทำได้:
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;
และผลลัพธ์:
[
Button
, TextBox
ฯลฯ ยังคงหายไป ความฝันของฉันคือการสนับสนุน XAML แบบเต็มรูปแบบด้วยการผูกข้อมูลและปรัชญา "ฝังอะไรลงในอะไรก็ได้" แบบ WPF แต่ฉันอยู่ไกลจากนั้นมาก ... ดีในขณะนี้ :)
หากคุณใช้ 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 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"));
อินพุตตัวอย่าง:
ตัวอย่างผลลัพธ์:
นั้นน่าสนุก. ขอบคุณfuboฉันลองใช้วิธีแก้ปัญหาของคุณแล้วและสามารถเพิ่มความละเอียดของการแสดงตัวอย่างได้ 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();
}
}
}
ในการรันตัวอย่างบิตแมป "image.bmp" จะต้องอยู่ในไดเร็กทอรีเดียวกับไฟล์ปฏิบัติการ ฉันเพิ่มขนาดของคอนโซลขนาดของตัวอย่างยังคงเป็น 39 และสามารถเปลี่ยนแปลงได้ที่int sMax = 39;
.
น้ำยาจากทอฟฟี่ก็เด็ดมากเช่นกัน คุณสองคนมีคะแนนโหวตของฉัน ...
ฉันกำลังอ่านเกี่ยวกับช่องว่างสีและพื้นที่LABดูเหมือนจะเป็นตัวเลือกที่ดีสำหรับคุณ (ดูคำถามนี้: การค้นหา "ระยะห่าง" ระหว่างสีและอัลกอริทึมที่แม่นยำเพื่อตรวจสอบความคล้ายคลึงกันของสี )
การอ้างถึงหน้าWikipedia CIELABข้อดีของพื้นที่สีนี้คือ:
แตกต่างจากรุ่นสี RGB และ CMYK Lab color ได้รับการออกแบบมาเพื่อประมาณการมองเห็นของมนุษย์ มันต้องการความสม่ำเสมอในการรับรู้และส่วนประกอบ L ของมันตรงกับการรับรู้ความสว่างของมนุษย์อย่างใกล้ชิด ดังนั้นจึงสามารถใช้เพื่อทำการแก้ไขสมดุลสีที่ถูกต้องได้โดยการแก้ไขเส้นโค้งเอาต์พุตในส่วนประกอบ a และ b
ในการวัดระยะห่างระหว่างสีคุณสามารถใช้ระยะเดลต้า 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
คุณสามารถใช้วิธีการต่อไปนี้ (จากที่นี่ ):
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 do ('█', '▓', '▒', '░') ซึ่งจะช่วยให้คุณได้สีมากกว่า 16 สีที่รวมสีคอนโซล (โดยใช้Combine
วิธีการ)
ที่นี่เราสามารถปรับปรุงบางอย่างได้โดยการคำนวณสีที่จะใช้ล่วงหน้า:
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);
}
ภาพผลลัพธ์:
โซลูชันต่อไปนี้ไม่ได้ขึ้นอยู่กับตัวอักษร แต่ให้ภาพที่มีรายละเอียดครบถ้วน
คุณสามารถวาดบนหน้าต่างใดก็ได้โดยใช้ตัวจัดการเพื่อสร้าง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);
}
สิ่งนี้ดูดี แต่ถ้าคอนโซลถูกปรับขนาดหรือเลื่อนภาพจะหายไปเนื่องจากมีการรีเฟรชหน้าต่าง (อาจใช้กลไกบางอย่างในการวาดภาพใหม่ในกรณีของคุณ)
อีกวิธีหนึ่งคือการฝังหน้าต่าง ( 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);
}
แน่นอนว่าคุณสามารถตั้งค่าFormBorderStyle = FormBorderStyle.None
ให้ซ่อนขอบหน้าต่างได้ (ภาพขวา)
ในกรณีนี้คุณสามารถปรับขนาดคอนโซลและภาพ / หน้าต่างยังคงอยู่ที่นั่น
ข้อดีอย่างหนึ่งของวิธีนี้คือคุณสามารถค้นหาหน้าต่างที่คุณต้องการและเปลี่ยนภาพได้ตลอดเวลาโดยเพียงแค่เปลี่ยนBackgroundImage
คุณสมบัติ
ไม่มีทางตรง แต่คุณอาจลองใช้ตัวแปลง image-to-ascii-art แบบนี้ก็ได้
ใช่คุณสามารถทำได้หากคุณยืดคำถามเล็กน้อยโดยการเปิด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แม้ว่าคุณจะใช้หน้าต่างที่ใหญ่ขึ้นและบล็อกกราฟิกมันจะไม่ใช่การแสดงตัวอย่าง แต่เป็นเรื่องยุ่ง!
อัปเดต:ดูเหมือนว่าคุณสามารถทำได้หลังจากวาด GDI ทั้งหมดลงในแบบฟอร์มคอนโซล ดูคำตอบของ Taffer!