Skip to content

Instantly share code, notes, and snippets.

@AldeRoberge
Created March 26, 2026 14:55
Show Gist options
  • Select an option

  • Save AldeRoberge/0ff4738087f8f111db167c77657fa64c to your computer and use it in GitHub Desktop.

Select an option

Save AldeRoberge/0ff4738087f8f111db167c77657fa64c to your computer and use it in GitHub Desktop.
Using Google Cloud Gemini Image API in C#

There's no wrapper for Google Cloud Gemini API in C# as of now.

Here's how to call the rest API using C#.


πŸ”‘ 1. Authentication (OAuth2)

private async Task<string> GetAccessTokenAsync()
{
    var credential = GoogleCredential.FromFile(serviceAccountPath)
        .CreateScoped("https://www.googleapis.com/auth/cloud-platform");

    var accessToken = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();
    return accessToken;
}

Key points:

  • Uses a service account JSON
  • Requests cloud-platform scope
  • Returns a Bearer token for API calls

🧠 2. Building the API Request

Endpoint

var endpoint = $"https://{location}-aiplatform.googleapis.com/v1/projects/{projectId}/locations/{location}/publishers/google/models/gemini-2.5-flash-image:generateContent";

Request Body

var requestBody = new
{
    contents = new[]
    {
        new
        {
            role = "user",
            parts = new object[]
            {
                new { text = $"{prompt}" },
                new
                {
                    inlineData = new
                    {
                        mimeType = "image/png",
                        data = referenceImageBase64
                    }
                }
            }
        }
    },
    generationConfig = new
    {
        candidateCount = 1,
        mediaResolution = "MEDIA_RESOLUTION_MEDIUM"
    }
};

Key concepts:

  • text β†’ your prompt
  • inlineData β†’ reference image (base64)
  • Gemini accepts multi-part input (text + image)

🌐 3. Sending the Request

var request = new HttpRequestMessage(HttpMethod.Post, endpoint);
request.Content = content;
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

var response = await _httpClient.SendAsync(request);

Important:

  • Uses HttpClient
  • Adds Authorization: Bearer <token>
  • Sends JSON body

πŸ–ΌοΈ 4. Parsing the Response (Image Extraction)

if (root.TryGetProperty("candidates", out var candidates))
{
    var candidate = candidates[0];

    foreach (var part in parts.EnumerateArray())
    {
        if (part.TryGetProperty("inlineData", out var inlineData))
        {
            var mimeType = inlineData.GetProperty("mimeType").GetString();
            var dataBase64 = inlineData.GetProperty("data").GetString();

            byte[] imageBytes = Convert.FromBase64String(dataBase64);

            var outputPath = Path.Combine("output", $"{timestamp}.png");
            await File.WriteAllBytesAsync(outputPath, imageBytes);

            return outputPath;
        }
    }
}

What happens here:

  • Extracts candidates
  • Finds inlineData
  • Decodes base64 β†’ image bytes
  • Saves .png file locally

🎨 5. Background Removal (maybe not necessary)

if (pixel.R < 15 && pixel.G < 15 && pixel.B < 15)
{
    pixel.A = 0; // transparent
}

Logic:

  • Detects near-black pixels
  • Converts them to transparent
  • Saves new .transparent.png

πŸ” 6. Main Workflow

var generatedImagePath = await generator.GenerateImageAsync(
    ReferenceImagePath,
    prompt,
    TargetImageSize);

generatedImagePath = await generator.RemoveWhiteBackgroundAsync(generatedImagePath);

Flow:

  1. Generate image via API
  2. Post-process (remove background)
  3. Save final output

🧩 Summary

This system:

  • Uses Gemini Image API
  • Combines prompt + reference image
  • Handles auth, request, parsing
  • Outputs a processed PNG

πŸ’‘ Minimal Flow (TL;DR)

Prompt + Image
     ↓
OAuth2 Token
     ↓
POST β†’ Gemini API
     ↓
Base64 Image Response
     ↓
Decode + Save
     ↓
(Optional) Remove Background
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment