Comment créer une image jpg dynamicment en mémoire avec .NET?

J’ai une bibliothèque .NET (3.5 SP1) (DLL) écrite en C #. Je dois étendre cette bibliothèque par une méthode de classe qui aura la signature suivante:

public byte[] CreateGridImage(int maxXCells, int maxYCells, int cellXPosition, int cellYPosition) { ... } 

Cette méthode est supposée faire ce qui suit:

  • Les parameters d’entrée maxXCells et maxYCells définissent la taille d’une grid de cellules dans les directions X et Y. maxXCells et maxYCells sont le nombre de cellules dans chaque direction. Les cellules individuelles sont de forme carrée. (Donc, c’est un peu un échiquier asymésortingque.)
  • Les parameters d’entrée cellXPosition et cellYPosition identifient une cellule spéciale dans cette grid et cette cellule doit être remplie d’une croix.
  • Aucun graphique sophistiqué n’est nécessaire, mais uniquement des lignes de grid noires sur un fond blanc et un X dans l’une des cellules.
  • Le graphique obtenu doit être au format JPG.
  • La création de ce graphique doit avoir lieu en mémoire et rien ne doit être stocké dans un fichier sur disque ni peint à l’écran.
  • La méthode retourne l’image générée sous forme d’ byte[]

Comme je ne connais pas très bien les fonctions graphiques dans .NET, mes questions sont les suivantes:

  • Est-ce possible avec .NET 3.5 SP1 sans autres bibliothèques tierces (ce que j’aimerais éviter)?
  • Quelles sont les étapes de base que je dois suivre et quels sont les espaces de noms, les classes et les méthodes .NET essentiels que je dois connaître pour atteindre cet objective (notamment pour tracer des lignes et d’autres éléments graphiques simples “en mémoire” et convertir le résultat en octet tableau au format jpg)?

Merci pour vos suggestions à l’avance!

Ce qui suit est un exemple de code complet qui utilisera GDI pour dessiner une grid et placer une croix (avec un arrière-plan rouge), comme dans l’image d’exemple ci-dessous. Il utilise GDI comme les autres réponses, mais le vrai travail prend place en parcourant les cellules et en traçant des lignes de grid.

Le code suivant

 byte[] bytes = CreateGridImage(10,10, 9, 9, 30); 

créera une grid 10×10 avec une croix dans la position 9×9:

entrez la description de l'image ici

Un nouvel ajout à CreateGridImage() est l’ajout d’un argument boxSize qui définit la taille de chaque “carré” dans la grid.

 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(); } } 
  1. Créez un object System.Drawing.Bitmap.

  2. Créez un object Graphics pour faire votre dessin.

  3. Enregistrez le bitmap sur un MemoryStream en tant qu’object JPEG.

N’oubliez pas d’appeler Dispose sur votre bitmap temporaire!

Vous trouverez ci-dessous un exemple de code, vous pouvez modifier les formats de pixels et diverses options ci-dessous. Consultez la documentation 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(); } } 

Tout d’abord, sur le dessin, vous pouvez soit:

  • Utilisez la classe Graphics pour utiliser ce que GDI vous donne
  • Verrouiller bitmap et dessiner dessus manuellement

En ce qui concerne la sauvegarde, vous pouvez utiliser la classe MemoryStream qui conserve vos octets, puis en extrait un tableau.

Le code exemple pourrait ressembler à ceci (en supposant que vous souhaitiez utiliser un object Graphics pour dessiner sur un bitmap:

 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,

Voici un autre moyen d’utiliser le contrôle DataGridView de WindowsForm pour dessiner la grid.

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

=== Dans le client app.config (remplacez cette ligne):

===

Bon codage!