Qwen Image Edit Multiple Angles
Playground
Try it on WaveSpeedAI!Generate specific camera angles from a single image using a 96-pose camera system. Control horizontal rotation, vertical tilt, and zoom to create front, side, back views and more. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.
Features
Qwen-Image-Edit Multiple Angles transforms a single input image into any camera angle using an advanced 96-pose camera system. Generate front views, side profiles, back views, bird’s-eye shots, and dramatic low angles — all from one photo.
Perfect for e-commerce product photography, 3D asset creation, character design, virtual try-on, and creative content generation.
Why Choose Multiple Angles?
-
Single Image to Multi-View Upload one photo and generate any angle — no need for multiple photo shoots or 3D modeling.
-
96-Pose Camera System 8 horizontal angles × 4 vertical angles × 3 distance levels = comprehensive viewpoint coverage.
-
Intuitive Angle Control Specify angles in degrees — the system automatically optimizes for the best results.
-
Production-Ready API No cold starts, fast inference, and predictable pricing for seamless integration.
Camera System Reference
Horizontal Angle (Azimuth) — Rotate Around Subject
| Angle | View |
|---|---|
| 0° | Front view |
| 45° | Front-right quarter |
| 90° | Right side profile |
| 135° | Back-right quarter |
| 180° | Back view |
| 225° | Back-left quarter |
| 270° | Left side profile |
| 315° | Front-left quarter |
Accepts any value 0-359° and rounds to the nearest optimal angle.
Vertical Angle (Elevation) — Camera Height
| Angle | Shot Type |
|---|---|
| -30° | Low-angle (looking up) |
| 0° | Eye-level (standard) |
| 30° | Elevated (slightly above) |
| 60° | High-angle (looking down) |
Accepts any value -30° to 60° and rounds to the nearest optimal angle.
Distance — Zoom Level
| Value | Shot Type |
|---|---|
| 0 | Close-up |
| 1 | Medium shot |
| 2 | Wide shot |
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| images | array | Yes | - | Input image(s). Up to 3 images. |
| horizontal_angle | integer | No | 0 | Rotation around subject (0-359°). |
| vertical_angle | integer | No | 0 | Camera height (-30° to 60°). |
| distance | integer | No | 1 | Zoom level (0, 1, or 2). |
| prompt | string | No | - | Optional guidance prompt. |
| seed | integer | No | -1 | Random seed (-1 for random). |
| output_format | string | No | ”jpeg" | "jpeg”, “png”, or “webp”. |
Use Cases
E-Commerce Product Views
Generate 360° product views from a single photo for online stores.
{
"images": ["https://example.com/product.jpg"],
"horizontal_angle": 90,
"vertical_angle": 0,
"distance": 1
}Character Design & Concept Art
Create character turnarounds for animation and game development.
{
"images": ["https://example.com/character.jpg"],
"horizontal_angle": 180,
"vertical_angle": 0,
"distance": 1
}Dramatic Photography Effects
Generate cinematic angles for creative content.
{
"images": ["https://example.com/portrait.jpg"],
"horizontal_angle": 45,
"vertical_angle": -30,
"distance": 0
}Aerial & Bird’s-Eye Views
Create top-down perspectives for real estate or product layouts.
{
"images": ["https://example.com/scene.jpg"],
"horizontal_angle": 0,
"vertical_angle": 60,
"distance": 2
}Best Practices
- Use clear, well-lit input images for best multi-angle results.
- Start with eye-level (0°) vertical angle for natural-looking outputs.
- Use medium distance (1) as baseline, then adjust for tighter or wider framing.
- Add prompts for additional style guidance beyond angle transformation.
- Test with 90° or 180° horizontal rotations first to understand subject handling.
Pricing
$0.025 per generated image
Related Models
- Qwen Image Edit 2511 — General-purpose AI image editing.
- Qwen Image Edit Plus — High-fidelity image editing with enhanced detail retention.
Authentication
For authentication details, please refer to the Authentication Guide.
API Endpoints
Submit Task & Query Result
set -euo pipefail
export WAVESPEED_API_KEY="your-api-key"
REQUEST_BODY=$(cat <<'JSON'
{
"images": [
"https://interactive-examples.mdn.mozilla.net/media/cc0-images/painted-hand-298-332.jpg"
],
"horizontal_angle": 0,
"vertical_angle": 0,
"distance": 1,
"seed": -1,
"output_format": "jpeg"
}
JSON
)
# 1. Submit the prediction.
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
-X POST "https://api.wavespeed.ai/api/v3/wavespeed-ai/qwen-image/edit-multiple-angles" \
-H "Authorization: Bearer ${WAVESPEED_API_KEY}" \
-H "Content-Type: application/json" \
-d "${REQUEST_BODY}")
TASK=$(printf '%s' "${SUBMIT_RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
PREDICTION_ID=$(printf '%s' "${TASK}" | jq -r '.id // empty')
if [ -z "${PREDICTION_ID}" ]; then
printf 'Submission response did not contain a prediction id
' >&2
exit 1
fi
RESULT_URL=$(printf '%s' "${TASK}" | jq -r '.urls.get // empty')
if [ -z "${RESULT_URL}" ]; then RESULT_URL="https://api.wavespeed.ai/api/v3/predictions/${PREDICTION_ID}/result"; fi
# 2. Poll until the prediction finishes.
while true; do
RESPONSE=$(curl --silent --show-error --fail-with-body \
"${RESULT_URL}" \
-H "Authorization: Bearer ${WAVESPEED_API_KEY}")
RESULT=$(printf '%s' "${RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
STATUS=$(printf '%s' "${RESULT}" | jq -r '.status // empty')
case "${STATUS}" in
completed) printf '%s\n' "${RESULT}" | jq '.outputs'; break ;;
failed|cancelled|timeout) printf '%s\n' "${RESULT}" | jq . >&2; exit 1 ;;
created|processing) sleep 2 ;;
*) printf 'Unexpected status: %s
' "${STATUS}" >&2; exit 1 ;;
esac
doneParameters
Task Submission Parameters
Request Parameters
| Parameter | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
| images | array<string> | Yes | - | 1 ~ 3 items | The input images. A maximum of 3 reference images can be uploaded. |
| horizontal_angle | integer | No | 0 | 0 ~ 359 | Horizontal rotation angle (azimuth) in degrees. Controls the camera's horizontal position around the subject. Values are rounded to the nearest valid angle: 0 (front), 45 (front-right), 90 (right), 135 (back-right), 180 (back), 225 (back-left), 270 (left), 315 (front-left). |
| vertical_angle | integer | No | 0 | -30 ~ 60 | Vertical tilt angle (elevation) in degrees. Controls the camera's vertical position. Values are rounded to the nearest valid angle: -30 (low angle), 0 (eye level), 30 (elevated), 60 (high angle). |
| distance | integer | No | 1 | 0 ~ 2 | Camera distance/zoom level. 0 = close-up, 1 = medium shot, 2 = wide shot. |
| prompt | string | No | - | Optional additional prompt to guide the generation. This is appended to the angle prompt. | |
| seed | integer | No | -1 | - | The random seed to use for the generation. -1 means a random seed will be used. |
| output_format | string | No | jpeg | jpeg, png, webp | The format of the output image. |
| enable_base64_output | boolean | No | false | - | If set to `true`, the prediction's `output` strings are returned as **naked base64** (no `data:<mime>;base64,` prefix). When `false` (default), outputs are returned as URLs pointing to our CDN. |
| enable_sync_mode | boolean | No | false | - | If set to `true`, the request attempts to wait for the generated result and return outputs in the same response. If the result is not ready within the sync wait window, the API can return a timeout body while the task continues processing. This option is only available via the API and is supported only by some models. |
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| code | integer | HTTP status code (e.g., 200 for success) |
| message | string | Status message (e.g., “success”) |
| data.id | string | Unique identifier for the prediction, Task Id |
| data.model | string | Model ID used for the prediction |
| data.outputs | array | Output values, usually URL strings; some models return text strings or structured result objects (empty when status is not completed) |
| data.urls | object | Object containing related API endpoints |
| data.urls.get | string | URL to retrieve the prediction result |
| data.status | string | Status of the task: created, processing, completed, or failed |
| data.created_at | string | ISO timestamp of when the request was created (e.g., “2023-04-01T12:34:56.789Z”) |
| data.error | string | Error message (empty if no error occurred) |
| data.timings | object | Object containing timing details |
| data.timings.inference | integer | Inference time in milliseconds |
Result Request Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | string | Yes | - | Task ID |
Result Response Parameters
| Parameter | Type | Description |
|---|---|---|
| code | integer | HTTP status code (e.g., 200 for success) |
| message | string | Status message (e.g., “success”) |
| data | object | The prediction data object containing all details |
| data.id | string | Unique identifier for the prediction |
| data.model | string | Model ID used for the prediction |
| data.outputs | array<string | object> | Array of generated outputs (empty when status is not completed). Items are usually URL strings, but may be text strings or structured result objects, depending on the model. |
| data.urls | object | Object containing related API endpoints |
| data.urls.get | string | URL to poll for the prediction result |
| data.status | string | Status: created, processing, completed, or failed |
| data.created_at | string | ISO timestamp of when the request was created |
| data.error | string | Error message (empty if no error occurred) |
| data.timings | object | Object containing timing details |
| data.timings.inference | integer | Inference time in milliseconds |