# Common Patterns ## URL Transform Options ``` width= height= fit=scale-down|contain|cover|crop|pad quality=85 format=auto|webp|avif|jpeg|png dpr=2 gravity=auto|face|left|right|top|bottom sharpen=2 blur=10 rotate=90|180|270 background=white metadata=none|copyright|keep ``` ## Responsive Images (srcset) ```html ``` ## Format Negotiation ```typescript async fetch(request: Request, env: Env): Promise { const accept = request.headers.get('Accept') || ''; const format = /image\/avif/.test(accept) ? 'avif' : /image\/webp/.test(accept) ? 'webp' : 'jpeg'; return env.IMAGES.input(buffer).transform({ format, quality: 85 }).output().response(); } ``` ## Direct Creator Upload ```typescript // Backend: Generate upload URL const response = await fetch( `https://api.cloudflare.com/client/v4/accounts/${env.ACCOUNT_ID}/images/v2/direct_upload`, { method: 'POST', headers: { 'Authorization': `Bearer ${env.API_TOKEN}` }, body: JSON.stringify({ requireSignedURLs: false, metadata: { userId } }) } ); // Frontend: Upload to returned uploadURL const formData = new FormData(); formData.append('file', file); await fetch(result.uploadURL, { method: 'POST', body: formData }); // Use: https://imagedelivery.net/{hash}/${result.id}/public ``` ## Transform & Store to R2 ```typescript async fetch(request: Request, env: Env): Promise { const file = (await request.formData()).get('image') as File; const transformed = await env.IMAGES .input(await file.arrayBuffer()) .transform({ width: 800, format: 'avif', quality: 80 }) .output(); await env.R2.put(`images/${Date.now()}.avif`, transformed.response().body); return Response.json({ success: true }); } ``` ## Watermarking ```typescript const watermark = await env.ASSETS.fetch(new URL('/watermark.png', request.url)); const result = await env.IMAGES .input(await image.arrayBuffer()) .draw(env.IMAGES.input(watermark.body).transform({ width: 100 }), { bottom: 20, right: 20, opacity: 0.7 }) .transform({ format: 'avif' }) .output(); return result.response(); ``` ## Device-Based Transforms ```typescript const ua = request.headers.get('User-Agent') || ''; const isMobile = /Mobile|Android|iPhone/i.test(ua); return env.IMAGES.input(buffer) .transform({ width: isMobile ? 400 : 1200, quality: isMobile ? 75 : 85, format: 'avif' }) .output().response(); ``` ## Caching Strategy ```typescript async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { const cache = caches.default; let response = await cache.match(request); if (!response) { response = await env.IMAGES.input(buffer).transform({ width: 800, format: 'avif' }).output().response(); response = new Response(response.body, { headers: { ...response.headers, 'Cache-Control': 'public, max-age=86400' } }); ctx.waitUntil(cache.put(request, response.clone())); } return response; } ``` ## Batch Processing ```typescript const results = await Promise.all(images.map(buffer => env.IMAGES.input(buffer).transform({ width: 800, fit: 'cover', format: 'avif' }).output() )); ``` ## Error Handling ```typescript try { return (await env.IMAGES.input(buffer).transform({ width: 800 }).output()).response(); } catch (error) { console.error('Transform failed:', error); return new Response('Image processing failed', { status: 500 }); } ```