Как создать динамическое изображение jpg в памяти с помощью .NET?
У меня есть библиотека .NET(3.5 SP1) (DLL), написанная на С#. Я должен расширить эту библиотеку методом класса, который будет иметь следующую подпись:
public byte[] CreateGridImage(int maxXCells, int maxYCells,
int cellXPosition, int cellYPosition)
{
...
}
Этот метод должен делать следующее:
- Входные параметры
maxXCells
и maxYCells
определяют размер сетки ячеек в направлениях X и Y. maxXCells
и maxYCells
- количество ячеек в каждом направлении. Отдельные ячейки имеют квадратную форму. (Это своего рода асимметричная шахматная доска.)
- Входные параметры
cellXPosition
и cellYPosition
идентифицируют одну специальную ячейку внутри этой сетки, и эта ячейка должна быть заполнена крестом.
- Необязательная графика не нужна, на самом деле только черные линии сетки на белом фоне и X в одной из ячеек.
- Полученный графический файл должен иметь формат jpg.
- Создание этой графики должно происходить в памяти, и ничто не должно храниться в файле на диске и не нарисоваться на экране.
- Метод возвращает сгенерированное изображение как
byte[]
Я очень не знаком с графическими функциями в .NET, поэтому мои вопросы:
- Возможно ли это вообще с .NET 3.5 SP1 без дополнительных сторонних библиотек (чего я бы хотел избежать)?
- Каковы основные шаги, которые я должен выполнить, и каковы важные пространства, классы и методы .NET, которые мне нужно знать для достижения этой цели (особенно для рисования линий и других простых графических элементов "в памяти" и преобразования результата в массив байтов в формате jpg)?
Благодарим вас за предложения заранее!
Ответы
Ответ 1
Ниже приведен полный пример кода, который будет использовать GDI для рисования сетки и размещения креста (с красным фоном), как в примере ниже. Он использует GDI так же, как и другие ответы, но реальная работа выполняется путем прокрутки ячеек и рисования линий сетки.
Следующий код
byte[] bytes = CreateGridImage(10,10, 9, 9, 30);
создаст сетку 10x10 с крестом в позиции 9x9:
![enter image description here]()
Новое дополнение к CreateGridImage()
- это добавление аргумента boxSize, который задает размер каждого "квадрата" в сетке
public static byte[] CreateGridImage(
int maxXCells,
int maxYCells,
int cellXPosition,
int cellYPosition,
int boxSize)
{
using (var bmp = new System.Drawing.Bitmap(maxXCells * boxSize+1, maxYCells * boxSize+1))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Yellow);
Pen pen = new Pen(Color.Black);
pen.Width = 1;
//Draw red rectangle to go behind cross
Rectangle rect = new Rectangle(boxSize * (cellXPosition - 1), boxSize * (cellYPosition - 1), boxSize, boxSize);
g.FillRectangle(new SolidBrush(Color.Red), rect);
//Draw cross
g.DrawLine(pen, boxSize * (cellXPosition - 1), boxSize * (cellYPosition - 1), boxSize * cellXPosition, boxSize * cellYPosition);
g.DrawLine(pen, boxSize * (cellXPosition - 1), boxSize * cellYPosition, boxSize * cellXPosition, boxSize * (cellYPosition - 1));
//Draw horizontal lines
for (int i = 0; i <= maxXCells;i++ )
{
g.DrawLine(pen, (i * boxSize), 0, i * boxSize, boxSize * maxYCells);
}
//Draw vertical lines
for (int i = 0; i <= maxYCells; i++)
{
g.DrawLine(pen, 0, (i * boxSize), boxSize * maxXCells, i * boxSize);
}
}
var memStream = new MemoryStream();
bmp.Save(memStream, ImageFormat.Jpeg);
return memStream.ToArray();
}
}
Ответ 2
-
Создайте объект System.Drawing.Bitmap.
-
Создайте графический объект, чтобы сделать свой рисунок.
-
Сохраните битмап в MemoryStream как объект JPEG.
Не забудьте вызвать Dispose на вашем временном растровом изображении!
Ниже приведен пример кода, вы можете изменить форматы пикселей и различные параметры ниже, взгляните на документацию MSDN.
public static byte[] CreateGridImage(
int maxXCells,
int maxYCells,
int cellXPosition,
int cellYPosition)
{
// Specify pixel format if you like..
using(var bmp = new System.Drawing.Bitmap(maxXCells, maxYCells))
{
using (Graphics g = Graphics.FromImage(bmp))
{
// Do your drawing here
}
var memStream = new MemoryStream();
bmp.Save(memStream, ImageFormat.Jpeg);
return memStream.ToArray();
}
}
Ответ 3
Прежде всего, о рисовании вы можете:
- Используйте класс Graphics для использования того, что GDI дает вам
- Заблокировать растровое изображение и нарисовать его вручную
Что касается сохранения, вы можете использовать класс MemoryStream
, чтобы сохранить свои байты, а затем получить из него массив байтов.
Пример кода может выглядеть так (если вы хотите использовать объект Graphics
для рисования по растровому изображению:
public byte[] CreateGridImage(int maxXCells, int maxYCells,
int cellXPosition, int cellYPosition)
{
int imageWidth = 1;
int imageHeight = 2;
Bitmap bmp = new Bitmap(imageWidth, imageHeight);
using (Graphics g = Graphics.FromImage(bmp))
{
//draw code in here
}
MemoryStream imageStream = new MemoryStream();
bmp.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();
return imageStream.ToArray();
}
Ответ 4
Slauma,
Вот еще один способ, который использует элемент управления WindowsForm DataGridView для рисования сетки.
public byte[] GetData()
{
Form form = new Form();
//Create a new instance of DataGridView(WindowsForm) control.
DataGridView dataGridView1 = new DataGridView();
form.Controls.Add(dataGridView1);
//Customize output.
dataGridView1.RowHeadersVisible = false;
dataGridView1.ColumnHeadersVisible = false;
dataGridView1.ScrollBars = ScrollBars.None;
dataGridView1.AutoSize = true;
//Set datasource.
dataGridView1.DataSource = GetDataTable();
//Export as image.
Bitmap bitmap = new Bitmap(dataGridView1.Width, dataGridView1.Height);
dataGridView1.DrawToBitmap(bitmap, new Rectangle(Point.Empty, dataGridView1.Size));
//bitmap.Save("sample.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
MemoryStream ms = new MemoryStream();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
bitmap.Dispose();
form.Dispose();
return ms.ToArray();
}
/// <summary>
/// Helper method.
/// </summary>
DataTable GetDataTable()
{
DataTable dt = new DataTable();
for (int i = 0; i < 2; i++)
dt.Columns.Add(string.Format("Column{0}", i));
for (int i = 0; i < dt.Columns.Count; i++)
{
for (int j = 0; j < 10; j++)
{
dt.Rows.Add(new string[] { "X1", "Y1" });
}
}
return dt;
}
===
В клиенте app.config(замените эту строку):
<readerQuotas maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
===
Счастливое кодирование!