如何使用.NET在内存中动态创建jpg图像?
我有一个用C#编写的.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中的图形function非常不熟悉所以我的问题是:
- 这是否可以使用.NET 3.5 SP1而没有额外的第三方库(我想避免)?
- 我必须遵循的基本步骤是什么,以及为实现这一目标需要了解的重要.NET命名空间,类和方法是什么(特别是在内存中绘制线条和其他简单的图形元素并将结果转换为字节jpg格式的数组)?
提前感谢您的建议!
以下是一个完整的代码示例,它将使用GDI绘制网格并放置一个十字(带有红色背景),就像下面的示例图像一样。 它像其他答案一样使用GDI,但真正的工作是通过循环遍历单元格和绘制网格线来实现的。
以下代码
byte[] bytes = CreateGridImage(10,10, 9, 9, 30);
将创建一个10×10网格,其中十字形位于9×9位置:
CreateGridImage()
的新增function是添加了一个boxSize参数,用于设置网格中每个“square”的大小
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(); } }
-
创建一个System.Drawing.Bitmap对象。
-
创建一个Graphics对象来进行绘图。
-
将位图作为JPEG对象保存到MemoryStream。
不要忘记在临时位图上调用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(); } }
首先,关于绘图,您可以:
- 使用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(); }
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(); } /// /// Helper method. /// 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中(替换此行):
===
快乐的编码!