# DALL-E Image Generation for Public Sector

**Last updated:** 2026-02
**Status:** GA (DALL-E 3) / Limited Access Preview (GPT-image-1)
**Category:** Multi-Modal AI

---

## Introduksjon

DALL-E og GPT-image-1 er Azure OpenAI sine bildegenerering-modellar som skapar bilete frå tekstbeskrivelsar. For norsk offentleg sektor opnar desse modellane moglegheiter innanfor visualisering av offentlege planforslag, illustrasjon av informasjonsmateriell, prototyping av brukargrensesnitt, og generering av tilgjengelege bilete for universell utforming.

Azure OpenAI sin bildegenereringsteneste kjem med innebygde Responsible AI-beskyttingar, inkludert innhaldsfiltrering, prompt-transformasjon for redusert bias, og Content Credentials som merkjer bilete som AI-generert. Dette er særleg viktig for offentleg sektor der tillit og truverde er fundamentalt.

Det er viktig å forstå at bildegenereringsmodellar har vesentlege avgrensingar: dei kan produsere faktisk feilaktige bilete, dei har bias frå treningsdata, og dei krev aktiv styring av innhaldskvalitet og etisk bruk. Norsk offentleg sektor må utvise særleg aktsemd knytt til bruk av AI-genererte bilete i offisiell kommunikasjon.

---

## DALL-E Capabilities og Limitations

### Modelloversikt

| Eigenskap | GPT-image-1.5 | GPT-image-1 | GPT-image-1-mini | DALL-E 3 |
|-----------|---------------|-------------|------------------|----------|
| **Status** | Limited Access | Limited Access | Limited Access | GA |
| **Bilete per request** | 1-10 | 1-10 | 1-10 | 1 |
| **Maks prompt-lengde** | 32 000 teikn | 32 000 teikn | 32 000 teikn | 4 000 teikn |
| **Størleikar** | Fleksibel | Fleksibel | Fleksibel | 1024x1024, 1792x1024, 1024x1792 |
| **Kvalitetsval** | auto, high, medium, low | auto, high, medium, low | auto, high, medium, low | hd, standard |
| **Stilval** | Tilpassa | Tilpassa | Tilpassa | vivid, natural |
| **Inpainting/editing** | Ja | Ja | Ja | Ja |
| **Ansiktsbevaring** | Ja (avansert) | Ja (avansert) | Nei | Nei |
| **Streaming** | Ja | Ja | Ja | Nei |
| **Output-format** | PNG, JPEG, WEBP | PNG, JPEG, WEBP | PNG, JPEG, WEBP | URL (24t gyldig) |
| **Transparent bakgrunn** | Ja (PNG) | Ja (PNG) | Ja (PNG) | Nei |

### Regionstilgjengelegheit

| Modell | Regionar |
|--------|---------|
| **DALL-E 3** | East US, Australia East, Sweden Central |
| **GPT-image-1** | West US 3, UAE North, Poland Central (Global Standard) |
| **GPT-image-1-mini** | Sjekk Azure-portalen for oppdatert liste |
| **GPT-image-1.5** | Sjekk Azure-portalen for oppdatert liste |

> **For norsk offentleg sektor:** DALL-E 3 er tilgjengeleg i Sweden Central, som er den næraste EU/EØS-regionen. GPT-image-1 krev Global Standard deployment.

### Kjende avgrensingar

| Avgrensing | Detaljar | Workaround |
|-----------|---------|-----------|
| **Tekst i bilete** | Variabel kvalitet, spesielt for norsk | Legg til tekst i post-prosessering |
| **Nøyaktigheit** | Kan generere faktisk feilaktige bilete | Alltid manuell gjennomgang |
| **Konsistens** | Vanskeleg å oppretthalde stil over bilete | Bruk detaljerte stilprompts |
| **Personar** | Fotorealistiske bilete av mindreårige blokkert | By design |
| **Opphavsrett** | Kan generere innhald som liknar verna materiale | Bruk innhaldsfiltrering |
| **Norske kulturelle referansar** | Avgrensa forståing av norsk kontekst | Detaljerte beskrivelsar |

---

## Content Filtering og Safety

### Innebygde Responsible AI-beskyttingar

Azure OpenAI bildegenereringsmodellar har fleire lag med tryggleiksbeskyttingar:

**Lag 1: Prompt-transformasjon (DALL-E 3)**
- Automatisk omskriving av prompts for betre kvalitet og mangfald
- Reduserer bias i genererte bilete
- Kan ikkje deaktiverast

**Lag 2: Innhaldsfiltrering (Input)**
- Analyserer prompt for skadeleg innhald
- Blokkerer prompts som bryt brukspolicyen
- Konfigurerbare alvorlegheitsgrader

**Lag 3: Innhaldsfiltrering (Output)**
- Analyserer generert bilete etter opprettelse
- Blokkerer bilete som bryt tryggleiksreglane
- Returnerer feilmelding `contentFilter`

**Lag 4: Content Credentials**
- Alle DALL-E-bilete inkluderer digital legitimasjon (C2PA)
- Markerer innhald som AI-generert
- Kan verifiserast med Content Authenticity Initiative SDK

### Innhaldsfilterkategoriar

| Kategori | Standardinnstilling | Kan konfiguerast |
|----------|-------------------|-----------------|
| **Hate** | Medium filtrering | Ja (låg, medium, høg) |
| **Violence** | Medium filtrering | Ja (låg, medium, høg) |
| **Sexual** | Medium filtrering | Ja (låg, medium, høg) |
| **Self-harm** | Medium filtrering | Ja (låg, medium, høg) |
| **Jailbreak risk** | Av (valfri) | Ja |
| **Protected material** | Av (valfri) | Ja |
| **Custom blocklists** | Ingen | Ja |
| **Microsoft profanity** | Tilgjengeleg | Ja |

### Feilhandtering for innhaldsfilteret

```python
from openai import AzureOpenAI

client = AzureOpenAI(
    api_version="2024-06-01",
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"]
)

def generate_image_safe(prompt: str, model: str = "dall-e-3") -> dict:
    """Generer bilete med robust feilhandtering."""
    try:
        response = client.images.generate(
            model=model,
            prompt=prompt,
            size="1024x1024",
            quality="hd",
            style="natural",
            n=1
        )

        return {
            "status": "success",
            "url": response.data[0].url,
            "revised_prompt": response.data[0].revised_prompt
        }

    except Exception as e:
        error_body = getattr(e, 'body', {}) or {}
        error_code = error_body.get('code', 'unknown')

        if error_code == 'contentFilter':
            return {
                "status": "filtered",
                "reason": "Prompt eller generert bilete blei blokkert av innhaldsfilteret",
                "recommendation": "Reformuler prompten med meir nøytralt språk"
            }
        elif error_code == 'rate_limit_exceeded':
            return {
                "status": "rate_limited",
                "reason": "Kvotegrense nådd",
                "recommendation": "Vent og prøv igjen, eller be om høgare kvote"
            }
        else:
            return {
                "status": "error",
                "reason": str(e),
                "recommendation": "Sjekk feilmelding og prøv igjen"
            }
```

### Spesielle omsyn for mindreårige

Fotorealistiske bilete av mindreårige er blokkert som standard. Enterprise-kundar får automatisk godkjenning for denne kapabiliteten, men for offentleg sektor tilrår vi å behalde denne begrensinga aktiv.

---

## Batch Image Generation

### Rate Limits og kvotering

| Modell | Standard kvote | Format |
|--------|---------------|--------|
| **DALL-E 2** | 2 samtidige requests | Concurrent |
| **DALL-E 3** | 6 requests per minutt | RPM |
| **GPT-image-1** | 9 requests per minutt | RPM |
| **GPT-image-1-mini** | 12 requests per minutt | RPM |
| **GPT-image-1.5** | 9 requests per minutt | RPM |

### Batch-prosesseringspattern

```python
import asyncio
from typing import List
from dataclasses import dataclass

@dataclass
class ImageRequest:
    prompt: str
    filename: str
    size: str = "1024x1024"
    quality: str = "hd"
    style: str = "natural"

class BatchImageGenerator:
    """Batch-generering av bilete med rate limiting."""

    def __init__(self, client: AzureOpenAI, model: str = "dall-e-3",
                 max_concurrent: int = 2, requests_per_minute: int = 6):
        self.client = client
        self.model = model
        self.semaphore = asyncio.Semaphore(max_concurrent)
        self.min_interval = 60.0 / requests_per_minute
        self.last_request_time = 0

    async def generate_batch(self, requests: List[ImageRequest]) -> List[dict]:
        """Generer ei batch med bilete med respekt for rate limits."""
        results = []

        for i, request in enumerate(requests):
            async with self.semaphore:
                # Rate limiting
                elapsed = asyncio.get_event_loop().time() - self.last_request_time
                if elapsed < self.min_interval:
                    await asyncio.sleep(self.min_interval - elapsed)

                print(f"Genererer bilete {i+1}/{len(requests)}: {request.filename}")

                result = await self._generate_single(request)
                results.append(result)

                self.last_request_time = asyncio.get_event_loop().time()

        return results

    async def _generate_single(self, request: ImageRequest) -> dict:
        """Generer eit enkelt bilete med retry."""
        for attempt in range(3):
            try:
                response = self.client.images.generate(
                    model=self.model,
                    prompt=request.prompt,
                    size=request.size,
                    quality=request.quality,
                    style=request.style,
                    n=1
                )

                return {
                    "filename": request.filename,
                    "status": "success",
                    "url": response.data[0].url,
                    "revised_prompt": response.data[0].revised_prompt
                }

            except Exception as e:
                if "rate_limit" in str(e).lower() and attempt < 2:
                    await asyncio.sleep(10 * (attempt + 1))
                    continue
                return {
                    "filename": request.filename,
                    "status": "error",
                    "error": str(e)
                }
```

### GPT-image-1 batch med streaming

GPT-image-1 støttar fleire bilete per request (`n`-parameter) og streaming:

```python
# GPT-image-1: Generer fleire bilete i eitt kall
response = client.images.generate(
    model="gpt-image-1",
    prompt="Illustrasjon av norsk fjordlandskap med moderne infrastruktur",
    n=4,  # Opptil 10 bilete per request
    quality="high",
    output_format="png",
    output_compression=90
)

# Streaming for raskare visuell feedback
response = client.images.generate(
    model="gpt-image-1",
    prompt="Arkitekturdiagram for smart bynett",
    n=1,
    stream=True,
    partial_images=3  # 1-3 delbilete under generering
)
```

---

## Integration with Document Pipelines

### Automatisert illustrasjon av offentlege dokument

```
Dokument (tekst) → GPT-4o: Identifiser illustrasjonsbehov
                        ↓
              Generer prompt per seksjon
                        ↓
              DALL-E 3 / GPT-image-1
                        ↓
              Kvalitetskontroll (manuell)
                        ↓
              Sett inn i dokument
              + Content Credentials metadata
                        ↓
              Publiser med AI-generert-markering
```

### Prompt engineering for offentleg sektor

```python
# Mal for offentleg sektorillustrasjon
def create_public_sector_prompt(context: str, style: str = "informativ") -> str:
    base_prompts = {
        "informativ": (
            "Profesjonell, klar illustrasjon i flat design-stil. "
            "Nøytrale fargar (blå, grå, kvit). "
            "Ingen tekst i biletet. "
            "Eigna for offentleg informasjonsmateriell. "
        ),
        "arkitektur": (
            "Teknisk arkitekturdiagram i isometrisk stil. "
            "Azure-blåtonar og -ikoner. "
            "Tydelege boksar og pilar. "
            "Profesjonell og ryddig layout. "
        ),
        "infografikk": (
            "Informasjonsgrafikk-stil med ikon-basert design. "
            "Høgkontrastfargar for tilgjengelegheit. "
            "Tydelege visuelle hierarki. "
            "Universell utforming-venleg. "
        )
    }

    return f"{base_prompts.get(style, base_prompts['informativ'])}{context}"

# Eksempel: Generer illustrasjon for vegsikkerheit
prompt = create_public_sector_prompt(
    "Illustrer konseptet med nullvisjon for trafikksikkerheit. "
    "Vis ein trygg veg med fotgjengarfelt, sykkelsti og bil "
    "i ein moderne norsk bysamanheng med fjell i bakgrunnen.",
    style="informativ"
)
```

### Integrasjon med Power Automate

```json
{
  "trigger": {
    "type": "manual",
    "inputs": {
      "schema": {
        "properties": {
          "document_url": {"type": "string"},
          "illustration_count": {"type": "integer", "default": 3}
        }
      }
    }
  },
  "actions": {
    "Analyze_document": {
      "type": "OpenAI",
      "inputs": {
        "model": "gpt-4o",
        "prompt": "Les dette dokumentet og foreslå 3 illustrasjonar som vil forbetre forståinga. For kvar illustrasjon, skriv ein DALL-E-prompt."
      }
    },
    "Generate_images": {
      "type": "ForEach",
      "foreach": "@body('Analyze_document').illustrations",
      "actions": {
        "Generate_image": {
          "type": "OpenAI_Image",
          "inputs": {
            "model": "dall-e-3",
            "prompt": "@items('Generate_images').prompt",
            "size": "1024x1024",
            "quality": "hd"
          }
        }
      }
    }
  }
}
```

---

## Tilgjengelegheit (Accessibility) Considerations

### WCAG 2.1-krav for AI-genererte bilete

| Krav | Nivå | Implementering |
|------|------|---------------|
| **1.1.1 Non-text Content** | A | Alt-tekst for alle genererte bilete |
| **1.4.1 Use of Color** | A | Ikkje stol berre på farge for å formidle informasjon |
| **1.4.3 Contrast** | AA | Minimum 4.5:1 kontrastforhold |
| **1.4.11 Non-text Contrast** | AA | Minimum 3:1 for grafiske element |

### Automatisk alt-tekst-generering

```python
def generate_accessible_image(prompt: str, context: str) -> dict:
    """Generer bilete med tilgjengelegheitsinformasjon."""

    # Steg 1: Generer biletet
    image_result = generate_image_safe(prompt)

    if image_result["status"] != "success":
        return image_result

    # Steg 2: Generer alt-tekst med GPT-4o
    alt_text_response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": (
                    "Du genererer alt-tekst for bilete i offentlege norske dokument. "
                    "Alt-teksten skal vere kortfatta (maks 125 teikn), beskrivande, "
                    "og formidla det vesentlege innhaldet i biletet. "
                    "Skriv på norsk bokmål."
                )
            },
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": f"Kontekst: {context}\nBeskriv biletet for alt-tekst:"},
                    {"type": "image_url", "image_url": {"url": image_result["url"], "detail": "low"}}
                ]
            }
        ],
        max_tokens=200
    )

    # Steg 3: Generer lang beskriving for complexe bilete
    long_desc = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": (
                    "Skriv ei detaljert beskriving av dette biletet for bruk med "
                    "aria-describedby i HTML. Beskriv layout, fargar, objekt og "
                    "relasjonar mellom element. Norsk bokmål."
                )
            },
            {
                "role": "user",
                "content": [
                    {"type": "image_url", "image_url": {"url": image_result["url"], "detail": "high"}}
                ]
            }
        ],
        max_tokens=500
    )

    return {
        **image_result,
        "alt_text": alt_text_response.choices[0].message.content,
        "long_description": long_desc.choices[0].message.content,
        "ai_generated": True,
        "content_credentials": True
    }
```

### Kontrastsjekk for genererte bilete

```python
from PIL import Image
import numpy as np

def check_image_contrast(image_path: str) -> dict:
    """Sjekk kontrastforhold i eit generert bilete."""
    img = Image.open(image_path).convert('RGB')
    pixels = np.array(img)

    # Berekn gjennomsnittleg luminans
    luminance = 0.2126 * pixels[:,:,0] + 0.7152 * pixels[:,:,1] + 0.0722 * pixels[:,:,2]

    # Finn lys og mørk region
    bright = np.percentile(luminance, 90)
    dark = np.percentile(luminance, 10)

    # Berekn kontrastforhold (WCAG-formel)
    l1 = (bright / 255 + 0.05)
    l2 = (dark / 255 + 0.05)
    contrast_ratio = l1 / l2 if l1 > l2 else l2 / l1

    return {
        "contrast_ratio": round(contrast_ratio, 1),
        "meets_aa": contrast_ratio >= 4.5,
        "meets_aaa": contrast_ratio >= 7.0,
        "recommendation": (
            "OK for WCAG AA" if contrast_ratio >= 4.5
            else "For låg kontrast — vurder å regenerere med høgare kontrast"
        )
    }
```

---

## Merking og transparens

### Content Credentials (C2PA)

Alle DALL-E-bilete inkluderer digitale legitimasjonar som dokumenterer at biletet er AI-generert:

```javascript
// Verifiser Content Credentials med C2PA SDK
import { createC2pa } from '@contentauth/c2pa-node';

const c2pa = await createC2pa();
const result = await c2pa.read('generated-image.png');

if (result.manifests) {
    console.log('AI-generert bilete bekrefta');
    console.log('Generert av:', result.manifests[0].claimGenerator);
}
```

### Tilrådde merkingspraksis for offentleg sektor

| Kontekst | Merking | Plassering |
|----------|---------|-----------|
| **Informasjonsmateriell** | "Illustrasjon: AI-generert" | Under biletet |
| **Presentasjonar** | "AI-generert illustrasjon" | I bildetekst |
| **Nettside** | Alt-tekst + metadata | HTML + C2PA |
| **Rapport/utgreiing** | Fotnote om AI-genererte element | Metodeseksjon |

---

## For Cosmo

- **DALL-E 3 er GA i Sweden Central**, noko som gjer det til det tryggaste valet for norsk offentleg sektor akkurat no. GPT-image-1 gir betre kvalitet og fleksibilitet, men krev Global Standard deployment og limited access-godkjenning.
- **Innhaldsfilteret blokkerer automatisk skadeleg innhald** på både input og output. For offentleg sektor tilrår vi å behalde standardinnstillingane og ikkje søke om unntak utan sterke grunnar.
- **Alle AI-genererte bilete MÅ merkast** tydeleg som AI-genererte i offentleg kommunikasjon. Bruk Content Credentials og synleg merking i bildtekst.
- **Batch-generering krev aktiv rate limiting** — DALL-E 3 har berre 6 RPM som standard. Design pipelines med kø og retry for å unngå throttling.
- **Tilgjengelegheit er ikkje valfritt** i offentleg sektor. Kombiner DALL-E med GPT-4o for automatisk generering av alt-tekst, og utfør kontrastsjekk på genererte bilete for WCAG AA-etterleving.
