Generating Images from Text with C# and Open AI DALL-E
Tags: ai, csharp, machinelearning, openai
Published: 2023-04-16 19:05:30

With the use of .NET C#, we can develop a POC (Proof of Concept) that uses the **Open AI DALL-E** model to generate images from text input.

In this blog post, we will explore the steps to develop a C# `Console Application` using Open AI's DALL-E model to generate images from text.

Also, check out my blog with other articles --> https://rmauro.dev

## 💬 What is DALL-E from Open AI

DALL-E can generate images of almost anything, from a yellow submarine to a pig with wings. It has been trained on a massive dataset of images and textual descriptions, allowing it to learn how to generate images from natural language input. In this article, we will explore how to integrate C# with DALL-E to generate images using code.

![Generating Images from Text with C# and Open AI DALL-E](https://res-4.cloudinary.com/dgoa5llvh/image/upload/q_auto/DALL-Sample-webp.webp)

> DALL-E Generated

## 🧵 Development with C#

In this project we're going to use Visual Studio and C# with .NET 6 to create a Console Application.

> 💡 You may need to do some tweaks if you intend to use **another**.NET version.

### Step 1: Console Application and dependencies

Let's create our Console Application with C# and .NET 6 let's install the dependencies.  
**Project Name** : ConsoleAppOpenAI.DALL_E

```bash
dotnet add Microsoft.Extensions.Http

👇 these are for loading configuration from JSON files
dotnet add Microsoft.Extensions.Configuration
dotnet add Microsoft.Extensions.Configuration.Json

👇 this is optional
dotnet add Microsoft.Extensions.Configuration.UserSecrets
```

> Commands to install the dependencies

![Generating Images from Text with C# and Open AI DALL-E](https://res-3.cloudinary.com/dgoa5llvh/image/upload/q_auto/dependencies-installed.png)

> Installed Dependencies

### Step 2: IOpenAIProxy Interface

Within this interface, we'll expose only the methods to Generate and Download the images from Open AI.

```csharp
namespace ConsoleAppOpenAI.DALL_E.HttpServices;

public interface IOpenAIProxy
{
    //👇 Send the Prompt Text with and return a list of image URLs
    Task<GenerateImageResponse> GenerateImages(
    	GenerateImageRequest prompt, 
        CancellationToken cancellation = default);

    //👇 Download the Image as byte array
    Task<byte[]> DownloadImage(string url);
}
```

> IOpenAIProxy.cs File

### Step 3: Generate Image Models

Let's define our models using records. Records simplify the reading since they are only POCO classes.

```csharp
namespace ConsoleAppOpenAI.DALL_E.HttpServices
{
    public record class GenerateImageRequest(
    	string Prompt, 
        int N, 
        string Size);

    public record class GenerateImageResponse(
    	long Created, 
        GeneratedImageData[] Data);

    public record class GeneratedImageData(string Url);
}

```

> Generate Image Models DTO

### Step 4: Create an Open AI Account

To use the OpenAI API, we need to create an account on the OpenAI platform. The registration process is straightforward and can be completed in a few minutes.

- We just need to visit the OpenAI website at [https://platform.openai.com/overview](https://platform.openai.com/overview?ref=rmauro.dev).
- Then click on the "Sign Up" button in the top right corner.
- Click on the button to start the registration process.

### Step 5: Set up the Configuration File / _appsettings.json_

To access the DALL-E model, we'll need to set up the Subscription Id and API key for our application.

Collect them from these menus:

![Generating Images from Text with C# and Open AI DALL-E](https://res-5.cloudinary.com/dgoa5llvh/image/upload/q_auto/dall-api-keys.png)

Update the `appsettings.json` or `secrets.json` file with the values.

```json
{
  "OpenAi": {
    
    "OrganizationId": "{Subscription Id goes here}",
    "ApiKey": "{API Key goes here}",

	"Url": "https://api.openai.com",
    "DALL-E": {
      "Size": "1024x1024",
      "N": 1
    }
  }
}
```

> appsettings.json file

> 💡 Don't forget to set **Copy to Output Directory** as **Copy if newer** for appsettings.json.

### Step 6: Open AI HTTP Service Implementation

Create a class named `OpenAIHttpService` with a single constructor receiving `IConfiguration` and read the configuration we just set in place.

```csharp
using ConsoleAppOpenAI.DALL_E.HttpServices;
using Microsoft.Extensions.Configuration;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;

namespace ConsoleAppOpenAI.DALL_E.Services;

public class OpenAIHttpService : IOpenAIProxy
{
    readonly HttpClient _httpClient;

    readonly string _subscriptionId;

    readonly string _apiKey;

    public OpenAIHttpService(IConfiguration configuration)
    {
    	//👇 reading settings from the configuration file
        var openApiUrl = configuration["OpenAi:Url"] ?? throw new ArgumentException(nameof(configuration));
        _httpClient = new HttpClient { BaseAddress = new Uri(openApiUrl) };

        _subscriptionId = configuration["OpenAi:SubscriptionId"];
        _apiKey = configuration["OpenAi:ApiKey"];
    }
    
	public async Task<GenerateImageResponse> GenerateImages(GenerateImageRequest prompt, CancellationToken cancellation = default)
    {
    	throw new NotImplementedException();
    }
    
    public async Task<byte[]> DownloadImage(string url)
    {
    	throw new NotImplementedException();
    }
}

```

Next should be the implementation of the `GenerateImages()` method:

```csharp
public async Task<GenerateImageResponse> GenerateImages(GenerateImageRequest prompt, CancellationToken cancellation = default)
{
    using var rq = new HttpRequestMessage(HttpMethod.Post, "/v1/images/generations");
	
    var jsonRequest = JsonSerializer.Serialize(prompt, new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    });

	//serialize the content to JSON and set the correct content type
    rq.Content = new StringContent(jsonRequest);
    rq.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

	//👇 Including the Authorization Header with API Key
    var apiKey = _apiKey;
    rq.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);

	//👇 Including the Subscription Id Header
    var subscriptionId = _subscriptionId;
    rq.Headers.TryAddWithoutValidation("OpenAI-Organization", subscriptionId);

    var response = await _httpClient.SendAsync(rq, HttpCompletionOption.ResponseHeadersRead, cancellation);

    response.EnsureSuccessStatusCode();

    var content = response.Content;

    var jsonResponse = await content.ReadFromJsonAsync<GenerateImageResponse>(cancellationToken: cancellation);

    return jsonResponse;
}
```

Last the `DownloadImage()` method implementation:

```csharp
public async Task<byte[]> DownloadImage(string url)
{
    var buffer = await _httpClient.GetByteArrayAsync(url);

    return buffer;
}
```

### Step 7: Consuming the APIs

Back to `Program.cs` file let's wire everything together and start calling the APIs to generate images.

```csharp
using ConsoleAppOpenAI.DALL_E.HttpServices;
using ConsoleAppOpenAI.DALL_E.Services;
using Microsoft.Extensions.Configuration;
using System.Reflection;

Console.WriteLine("Starting commandline for DALL-E [Open AI]");

var config = BuildConfig();

IOpenAIProxy aiClient = new OpenAIHttpService(config);

Console.WriteLine("Type your first Prompt");
var msg = Console.ReadLine();

var nImages = int.Parse(config["OpenAi:DALL-E:N"]);
var imageSize = config["OpenAi:DALL-E:Size"];
var prompt = new GenerateImageRequest(msg, nImages, imageSize);

var result = await aiClient.GenerateImages(prompt);

foreach (var item in result.Data)
{
	Console.WriteLine(item.Url);

	var fullPath = Path.Combine(Directory.GetCurrentDirectory(), $"{Guid.NewGuid()}.png");
	var img = await aiClient.DownloadImage(item.Url);

	await File.WriteAllBytesAsync(fullPath, img);
    
    Console.WriteLine("New image saved at {0}", fullPath);
}

Console.WriteLine("Press any key to exit");
Console.ReadKey();

static IConfiguration BuildConfig()
{
    var dir = Directory.GetCurrentDirectory();
    var configBuilder = new ConfigurationBuilder()
        .AddJsonFile(Path.Combine(dir, "appsettings.json"), optional: false)
        .AddUserSecrets(Assembly.GetExecutingAssembly());

    return configBuilder.Build();
}
```

With all of this, we should have a running POC integrating with DALL-E model.

## Generate our very first Image

Here is the output of my first try.

```bash
Prompt: Wide and green garden with a lot of flowers, with sunflowers, and a small dog running around
```

Take a look at this beautiful image generated by our application and DALL-E.

![Generating Images from Text with C# and Open AI DALL-E](https://res-4.cloudinary.com/dgoa5llvh/image/upload/q_auto/DALL-Sample-webp.webp)
_DALL-E Generated_

## Conclusion

Integrating C# with DALL-E is a straightforward process that allows us to generate images programmatically.

By using Open AI's API, we can easily send textual descriptions and receive high-quality images in response.

This integration opens up many possibilities, such as generating images for data visualization, creating custom artwork, or automating image creation tasks. As DALL-E continues to improve, we can expect even more exciting applications in the future.

Source code at: [https://github.com/ricardodemauro/OpenAILabs.Console](https://github.com/ricardodemauro/OpenAILabs.Console?ref=rmauro.dev)

Posted at: https://rmauro.dev/generating-images-from-text-with-csharp-and-open-ai-dall-e/