Generate images in Sitecore with OpenAI’s DALL·E API

OpenAI’s DALL·E API allows us to generate AI images based on a textual descripton. In this post I’ll show how we can use the API to create an image and store it in Sitecore.

To use the API you must sign up for an API key on openai.com.
Copy that API key and use it in your code. Then we can make a request to the API with a description of the image you want to generate.

With the Free trial usage you get $18 worth of credits to use the API. Generating one image is only a few cents. So it should be enough for a POC or just testing it out.

Using the HttpClient, we’ll send a POST request to the API endpoint with a JSON payload containing the description. Parse the JSON response to get the URL of the generated image, then use memorystream to save it in the media library.

Here’s an example how we can use it:

Custom dialog

I followed this great guide to setup a custom popup dialog
https://sbhatiablogs.wordpress.com/2019/07/07/custom-sitecore-menu-button-with-custom-popup-dialog/

With my own modifications it looks like this:

First the command that I’ve created in Sitecore. Follow steps in above guide for creating the Command and Sitecore Ribbon Button.

<configuration>
  <sitecore>
      <commands>
          <command name="item:generateimage" type="MyProject.Tasks.GenerateImageCommand, MyProject"/>
      </commands>
  </sitecore>
</configuration>
public class GenerateImageCommand : Sitecore.Shell.Framework.Commands.Command
  {
    public override void Execute(CommandContext context)
    {
      Sitecore.Context.ClientPage.Start(this, "Run", context.Parameters);
    }

    protected static void Run(ClientPipelineArgs args)
    {
      if (!args.IsPostBack)
      {
        UrlString urlString = new UrlString(UIUtil.GetUri("control:GenerateAiImage"));
        SheerResponse.ShowModalDialog(urlString.ToString(), "500", "300", "", true);
        args.WaitForPostBack();
      }
      else
      {
        if (args.HasResult)
        {
          if (Sitecore.Context.Item.Name == "Content Editor")
          {
           Sitecore.Context.ClientPage.ClientResponse.SetLocation(Sitecore.Links.LinkManager.GetItemUrl(Sitecore.Context.Item));
          }
        }
      }
    }
  }

Then the dialog that looks like this

The xml created under <webroot>/sitecore/shell/Application/Content Manager/Dialogs to make the dialog appearance.

<?xml version="1.0" encoding="utf-8" ?>
<control xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense" xmlns:def="Definition">
  <GenerateAiImage>
    <FormDialog Icon="Network/32x32/link.png" Style="height: 200%" Header="Generate AI image" Text="Enter filename and description" OKButton="Insert">
      <CodeBeside Type="MyProject.Tasks.GenerateImage, MyProject"/>
      <div class="scStretch" >
        <div class="col2">
          <Border Background="transparent" Border="none" GridPanel.VAlign="top" Padding="4px 0px 0px 0px">
            <GridPanel Class="scFormTable" CellPadding="2" Columns="2" Width="100%" GridPanel.Height="100%">
              <Label For="Filename" GridPanel.NoWrap="true">
                <Literal Text="Filename:" />
              </Label>
              <Edit ID="Filename" Width="100%"/>
              <Label for="Description" GridPanel.NoWrap="true">
                <Literal Text="Description:" />
              </Label>
              <Edit ID="Description" Width="100%"/>
            </GridPanel>
          </Border>
        </div>
      </div>
    </FormDialog>
  </GenerateAiImage>
</control>


With the CodeBeside in above XML I can catch the OnOk event which will generate the image from the API. From there I can grab the input texts from my dialog window. That code looks like this:

public class GenerateImage : Sitecore.Web.UI.Pages.DialogForm
  {
    protected override void OnOK(object sender, EventArgs e)
    {
      Sitecore.Web.UI.HtmlControls.Button senderB = sender as Sitecore.Web.UI.HtmlControls.Button;
      string apiKey = "<Your_API_key>";
      string apiEndpoint = "https://api.openai.com/v1/images/generations";

      var filename = senderB.Page.Request.Form.Get("Filename");
      var description = senderB.Page.Request.Form.Get("Description");

      HttpClient client = new HttpClient();
      client.DefaultRequestHeaders.Authorization = 
        new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", apiKey);

      string jsonPayload = JsonConvert.SerializeObject(new
      {
        prompt = description,
        n = 1, //how many images to generate
        size = "512x512"
      });

      StringContent content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
      HttpResponseMessage response = client.PostAsync(apiEndpoint, content).Result;

      if (response.IsSuccessStatusCode)
      {
        string jsonResponse = response.Content.ReadAsStringAsync().Result;
        dynamic result = JsonConvert.DeserializeObject(jsonResponse);

        // Get the generated image URL
        string imageUrl = result.data[0].url;

        // Download the image
        using (var imageResponse = new HttpClient().GetAsync(imageUrl).Result)
        {
          if (imageResponse.IsSuccessStatusCode)
          {
            using (var stream = new MemoryStream())
            {
              imageResponse.Content.CopyToAsync(stream).Wait();
              stream.Seek(0, SeekOrigin.Begin);

              var mediaCreator = new MediaCreator();
              var options = new MediaCreatorOptions
              {
                Versioned = false,
                IncludeExtensionInItemName = false,
                Database = Factory.GetDatabase("master"),
                Destination = "/sitecore/media library/AI-generated-images/"
              };

              using (new SecurityDisabler())
                mediaCreator.CreateFromStream(stream, $"{filename}.png", options);
            }
          }
        }
      }
    }
  }

Sources:
https://sbhatiablogs.wordpress.com/2019/07/07/custom-sitecore-menu-button-with-custom-popup-dialog/

3 thoughts on “Generate images in Sitecore with OpenAI’s DALL·E API

    • Filip Jönsson February 15, 2023 / 9:53 am

      That was a interesting read and well put together! Thank you for sharing.

      Like

Leave a comment