Как я могу получить цвет фона изображения, даже если на изображении больше цветов? ⇐ C#
-
Anonymous
Как я могу получить цвет фона изображения, даже если на изображении больше цветов?
Фон изображения в этом случае белый, но есть и синие цвета и, возможно, даже больше цветов, но если я перемещаю мышь на белых областях, он всегда получает RGB 255,255,2555555555555551111 раза. что, когда я использую мышь для рисования прямоугольника, где я хочу заменить/добавить текст, который не только белый. белый. Если я нарисую прямоугольник на белой области только на изображении, он поместит там белый цвет, и он будет выглядеть хорошо. /> Есть ли способ найти или сделать цвет фона, чтобы быть похожим на цвет фона изображения, даже если я нарисовал прямоугольник по областям с другими цветами? < /p>
Полный код. Это немного длинное, но все, что там связано, поэтому я не уверен, какие части только показывать: < /p>
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace ImageTextReplacer
{
public partial class Form1 : Form
{
private Bitmap? originalImage;
private Rectangle selectionRect;
private bool isSelecting = false;
private Point startPoint;
private StreamWriter? colorLoggerFile;
public Form1()
{
InitializeComponent();
}
private void btnLoadImage_Click(object sender, EventArgs e)
{
using (OpenFileDialog dlg = new OpenFileDialog())
{
dlg.Title = "Open Image";
dlg.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.bmp";
if (dlg.ShowDialog() == DialogResult.OK)
{
originalImage = new Bitmap(dlg.FileName);
pictureBox.Image = new Bitmap(originalImage);
}
}
}
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (pictureBox.Image == null) return;
isSelecting = true;
startPoint = e.Location;
selectionRect = new Rectangle(e.Location, new Size(0, 0));
pictureBox.Invalidate();
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (isSelecting)
{
int x = Math.Min(e.X, startPoint.X);
int y = Math.Min(e.Y, startPoint.Y);
int width = Math.Abs(e.X - startPoint.X);
int height = Math.Abs(e.Y - startPoint.Y);
selectionRect = new Rectangle(x, y, width, height);
pictureBox.Invalidate();
}
if(originalImage == null) return;
{
GetColorsMouseMove(e, originalImage);
}
}
private void GetColorsMouseMove(MouseEventArgs e, Bitmap originalBitmap)
{
if (originalBitmap == null) return;
float scale = Math.Min((float)pictureBox.Width / originalBitmap.Width,
(float)pictureBox.Height / originalBitmap.Height);
int offsetX = (int)((pictureBox.Width - originalBitmap.Width * scale) / 2);
int offsetY = (int)((pictureBox.Height - originalBitmap.Height * scale) / 2);
int imgX = (int)((e.X - offsetX) / scale);
int imgY = (int)((e.Y - offsetY) / scale);
if (imgX < 0 || imgY < 0 || imgX >= originalBitmap.Width || imgY >= originalBitmap.Height) return;
Color pixel = originalBitmap.GetPixel(imgX, imgY);
string line = $"X={imgX}, Y={imgY}, Color={pixel.Name}, R={pixel.R}, G={pixel.G}, B={pixel.B}";
textBoxColor.Text = line;
Console.WriteLine(line); // for debug output
try
{
colorLoggerFile ??= new StreamWriter("color_scan_log.txt", append: true);
colorLoggerFile.WriteLine(line);
colorLoggerFile.Flush();
}
catch { }
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
isSelecting = false;
pictureBox.Invalidate();
}
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
if (selectionRect != Rectangle.Empty && selectionRect.Width > 0 && selectionRect.Height > 0)
{
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, selectionRect);
}
}
}
private void btnReplaceText_Click(object sender, EventArgs e)
{
if (originalImage == null || selectionRect.Width == 0 || selectionRect.Height == 0)
{
MessageBox.Show("Please load image and select area.");
return;
}
Rectangle imageRect = GetActualImageRectangle();
if (imageRect == Rectangle.Empty) return;
float scaleX = (float)originalImage.Width / imageRect.Width;
float scaleY = (float)originalImage.Height / imageRect.Height;
Rectangle mappedRect = new Rectangle(
(int)((selectionRect.X - imageRect.X) * scaleX),
(int)((selectionRect.Y - imageRect.Y) * scaleY),
(int)(selectionRect.Width * scaleX),
(int)(selectionRect.Height * scaleY)
);
Bitmap edited = new Bitmap(originalImage);
Color backgroundColor = SampleCenterColor(edited, mappedRect);
using (Graphics g = Graphics.FromImage(edited))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
using (Brush brush = new SolidBrush(backgroundColor))
{
g.FillRectangle(brush, mappedRect);
}
string text = textBoxNewText.Text;
Font bestFont = CalculateBestFitFont(g, text, mappedRect, "Arial");
using (Brush textBrush = new SolidBrush(Color.FromArgb(0,70,140)))
{
StringFormat sf = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
g.DrawString(text, bestFont, textBrush, mappedRect, sf);
}
}
pictureBox.Image?.Dispose();
pictureBox.Image = new Bitmap(edited);
originalImage?.Dispose();
originalImage = new Bitmap(edited);
selectionRect = Rectangle.Empty;
pictureBox.Invalidate();
}
private Font CalculateBestFitFont(Graphics g, string text, Rectangle rect, string fontName)
{
float fontSize = 300; // Start large
Font font = new Font(fontName, fontSize, FontStyle.Bold);
SizeF textSize = g.MeasureString(text, font);
const float tolerance = 0.95f; // To leave padding
while ((textSize.Width > rect.Width * tolerance || textSize.Height > rect.Height * tolerance) && fontSize > 1)
{
fontSize -= 1f;
font.Dispose();
font = new Font(fontName, fontSize, FontStyle.Bold);
textSize = g.MeasureString(text, font);
}
return font;
}
private Color SampleCenterColor(Bitmap bmp, Rectangle rect)
{
int centerX = rect.X + rect.Width / 2;
int centerY = rect.Y + rect.Height / 2;
if (centerX >= bmp.Width) centerX = bmp.Width - 1;
if (centerY >= bmp.Height) centerY = bmp.Height - 1;
return bmp.GetPixel(centerX, centerY);
}
private Rectangle GetActualImageRectangle()
{
if (pictureBox.Image == null || originalImage == null)
return Rectangle.Empty;
float imgAspect = (float)originalImage.Width / originalImage.Height;
float boxAspect = (float)pictureBox.Width / pictureBox.Height;
int width, height, x, y;
if (imgAspect > boxAspect)
{
width = pictureBox.Width;
height = (int)(width / imgAspect);
x = 0;
y = (pictureBox.Height - height) / 2;
}
else
{
height = pictureBox.Height;
width = (int)(height * imgAspect);
x = (pictureBox.Width - width) / 2;
y = 0;
}
return new Rectangle(x, y, width, height);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
try
{
colorLoggerFile?.Close();
}
catch
{ /* Ignore errors on close */
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... -on-the-im
Фон изображения в этом случае белый, но есть и синие цвета и, возможно, даже больше цветов, но если я перемещаю мышь на белых областях, он всегда получает RGB 255,255,2555555555555551111 раза. что, когда я использую мышь для рисования прямоугольника, где я хочу заменить/добавить текст, который не только белый. белый. Если я нарисую прямоугольник на белой области только на изображении, он поместит там белый цвет, и он будет выглядеть хорошо. /> Есть ли способ найти или сделать цвет фона, чтобы быть похожим на цвет фона изображения, даже если я нарисовал прямоугольник по областям с другими цветами? < /p>
Полный код. Это немного длинное, но все, что там связано, поэтому я не уверен, какие части только показывать: < /p>
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace ImageTextReplacer
{
public partial class Form1 : Form
{
private Bitmap? originalImage;
private Rectangle selectionRect;
private bool isSelecting = false;
private Point startPoint;
private StreamWriter? colorLoggerFile;
public Form1()
{
InitializeComponent();
}
private void btnLoadImage_Click(object sender, EventArgs e)
{
using (OpenFileDialog dlg = new OpenFileDialog())
{
dlg.Title = "Open Image";
dlg.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.bmp";
if (dlg.ShowDialog() == DialogResult.OK)
{
originalImage = new Bitmap(dlg.FileName);
pictureBox.Image = new Bitmap(originalImage);
}
}
}
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (pictureBox.Image == null) return;
isSelecting = true;
startPoint = e.Location;
selectionRect = new Rectangle(e.Location, new Size(0, 0));
pictureBox.Invalidate();
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (isSelecting)
{
int x = Math.Min(e.X, startPoint.X);
int y = Math.Min(e.Y, startPoint.Y);
int width = Math.Abs(e.X - startPoint.X);
int height = Math.Abs(e.Y - startPoint.Y);
selectionRect = new Rectangle(x, y, width, height);
pictureBox.Invalidate();
}
if(originalImage == null) return;
{
GetColorsMouseMove(e, originalImage);
}
}
private void GetColorsMouseMove(MouseEventArgs e, Bitmap originalBitmap)
{
if (originalBitmap == null) return;
float scale = Math.Min((float)pictureBox.Width / originalBitmap.Width,
(float)pictureBox.Height / originalBitmap.Height);
int offsetX = (int)((pictureBox.Width - originalBitmap.Width * scale) / 2);
int offsetY = (int)((pictureBox.Height - originalBitmap.Height * scale) / 2);
int imgX = (int)((e.X - offsetX) / scale);
int imgY = (int)((e.Y - offsetY) / scale);
if (imgX < 0 || imgY < 0 || imgX >= originalBitmap.Width || imgY >= originalBitmap.Height) return;
Color pixel = originalBitmap.GetPixel(imgX, imgY);
string line = $"X={imgX}, Y={imgY}, Color={pixel.Name}, R={pixel.R}, G={pixel.G}, B={pixel.B}";
textBoxColor.Text = line;
Console.WriteLine(line); // for debug output
try
{
colorLoggerFile ??= new StreamWriter("color_scan_log.txt", append: true);
colorLoggerFile.WriteLine(line);
colorLoggerFile.Flush();
}
catch { }
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
isSelecting = false;
pictureBox.Invalidate();
}
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
if (selectionRect != Rectangle.Empty && selectionRect.Width > 0 && selectionRect.Height > 0)
{
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, selectionRect);
}
}
}
private void btnReplaceText_Click(object sender, EventArgs e)
{
if (originalImage == null || selectionRect.Width == 0 || selectionRect.Height == 0)
{
MessageBox.Show("Please load image and select area.");
return;
}
Rectangle imageRect = GetActualImageRectangle();
if (imageRect == Rectangle.Empty) return;
float scaleX = (float)originalImage.Width / imageRect.Width;
float scaleY = (float)originalImage.Height / imageRect.Height;
Rectangle mappedRect = new Rectangle(
(int)((selectionRect.X - imageRect.X) * scaleX),
(int)((selectionRect.Y - imageRect.Y) * scaleY),
(int)(selectionRect.Width * scaleX),
(int)(selectionRect.Height * scaleY)
);
Bitmap edited = new Bitmap(originalImage);
Color backgroundColor = SampleCenterColor(edited, mappedRect);
using (Graphics g = Graphics.FromImage(edited))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
using (Brush brush = new SolidBrush(backgroundColor))
{
g.FillRectangle(brush, mappedRect);
}
string text = textBoxNewText.Text;
Font bestFont = CalculateBestFitFont(g, text, mappedRect, "Arial");
using (Brush textBrush = new SolidBrush(Color.FromArgb(0,70,140)))
{
StringFormat sf = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
g.DrawString(text, bestFont, textBrush, mappedRect, sf);
}
}
pictureBox.Image?.Dispose();
pictureBox.Image = new Bitmap(edited);
originalImage?.Dispose();
originalImage = new Bitmap(edited);
selectionRect = Rectangle.Empty;
pictureBox.Invalidate();
}
private Font CalculateBestFitFont(Graphics g, string text, Rectangle rect, string fontName)
{
float fontSize = 300; // Start large
Font font = new Font(fontName, fontSize, FontStyle.Bold);
SizeF textSize = g.MeasureString(text, font);
const float tolerance = 0.95f; // To leave padding
while ((textSize.Width > rect.Width * tolerance || textSize.Height > rect.Height * tolerance) && fontSize > 1)
{
fontSize -= 1f;
font.Dispose();
font = new Font(fontName, fontSize, FontStyle.Bold);
textSize = g.MeasureString(text, font);
}
return font;
}
private Color SampleCenterColor(Bitmap bmp, Rectangle rect)
{
int centerX = rect.X + rect.Width / 2;
int centerY = rect.Y + rect.Height / 2;
if (centerX >= bmp.Width) centerX = bmp.Width - 1;
if (centerY >= bmp.Height) centerY = bmp.Height - 1;
return bmp.GetPixel(centerX, centerY);
}
private Rectangle GetActualImageRectangle()
{
if (pictureBox.Image == null || originalImage == null)
return Rectangle.Empty;
float imgAspect = (float)originalImage.Width / originalImage.Height;
float boxAspect = (float)pictureBox.Width / pictureBox.Height;
int width, height, x, y;
if (imgAspect > boxAspect)
{
width = pictureBox.Width;
height = (int)(width / imgAspect);
x = 0;
y = (pictureBox.Height - height) / 2;
}
else
{
height = pictureBox.Height;
width = (int)(height * imgAspect);
x = (pictureBox.Width - width) / 2;
y = 0;
}
return new Rectangle(x, y, width, height);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
try
{
colorLoggerFile?.Close();
}
catch
{ /* Ignore errors on close */
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... -on-the-im
Мобильная версия