fal-ai/patina/material/extract

Extract seamless tiling textures with PBR attribute maps from images
Inference
Commercial use

Input

Type # to reference inputs.

Additional Settings

Customize your input with more control.

Result

Idle

What would you like to do next?

Your request will cost $0.10 plus $0.02 per megapixel plus $0.01 per megapixel per map type. When using 2x upscaling, an additional $0.004 per (pre-upscaling) megapixel per map will be charged, and when using 4x upscaling, an additional $0.016 per (pre-upscaling) megapixel per map will be charged. For example, A 1024x1024 material with all 5 maps and no upscaling (1K) will cost $0.17, and a 2048x2048 material with all 5 maps and 4x upscaling (8K) will cost $0.70.

Logs

PATINA Material Extract - Photo to PBR Material

Endpoint: fal-ai/patina/material/extract

Category: Image-to-image

Pricing: $0.10 base + $0.02 per megapixel + $0.01 per megapixel per map. Upscaling adds $0.004 (2x) or $0.016 (4x) per megapixel per map.

Point at a material in a photo and PATINA will extract it into a clean, seamlessly tiling PBR texture. It first flattens and normalizes the material from the image, then generates a tileable texture with full PBR maps.


When to use this

Use this endpoint when you have a photo that contains a material you want, but the photo itself isn't a clean texture. For example, a photo of a brick wall taken at an angle, with shadows and perspective. Extract will isolate the material, flatten it, make it seamless, and generate PBR maps.

Good for:

  • Extracting a material from a real-world photo (a wall, a floor, a surface)
  • Turning reference photos into production-ready seamless textures
  • Using the prompt to tell the model which material in the image to focus on

Use a different endpoint if:

  • You already have a clean, flat texture and just want PBR maps - use /patina
  • You want to generate a material from text only, with no reference image - use /patina/material
  • You want to create variations of an existing texture - use /patina/material with image_url

How it works

  1. An editing model extracts the chosen material from the image and renders it flat and uniform
  2. The flattened result is run through image-to-image to make it seamlessly tileable
  3. PBR maps are predicted from the final texture

This is different from /patina (which does not modify the image) and /patina/material with image_url (which does pure image-to-image without the extraction step).


Quick start

javascript
import { fal } from "@fal-ai/client";

const result = await fal.subscribe("fal-ai/patina/material/extract", {
  input: {
    prompt: "the brick wall",
    image_url: "https://example.com/photo-of-building.jpg"
  }
});

// result.data.images - extracted seamless texture + PBR maps

Input

ParameterTypeRequiredDefaultDescription
promptstringYes-Describe which texture to extract from the image (e.g. "the wall", "the wooden floor")
image_urlstringYes-URL of the image to extract a texture from
image_sizestring or objectNosquare_hdA named size, or an object like {"width": 1024, "height": 2048}
num_inference_stepsintegerNo8Number of denoising steps (1-8)
seedintegerNoRandomSeed for reproducible generation
num_imagesintegerNo1Number of texture images to generate (1-4)
strengthfloatNo0.75How much to transform the input image
enable_prompt_expansionbooleanNotrueExpand prompt with an LLM for richer detail. Adds ~$0.0025.
enable_safety_checkerbooleanNotrueEnable safety filtering on outputs
tiling_modestringNo"both"Tiling direction: both, horizontal, or vertical
tile_sizeintegerNo128Tile size in latent space (64 = 512px, 128 = 1024px). Range: 32-256
tile_strideintegerNo64Tile stride in latent space. Range: 16-128
mapsstring[]NoAll fiveWhich PBR maps to predict: basecolor, normal, roughness, metalness, height. Deselect all to skip PBR estimation.
upscale_factorintegerNo0Upscale via SeedVR seamless: 0 (none), 2 (2x), or 4 (4x)
output_formatstringNo"png"Output format: jpeg, png, or webp
Example request
json
{
  "prompt": "the brick wall",
  "image_url": "https://example.com/photo-of-building.jpg",
  "image_size": "square_hd",
  "maps": ["basecolor", "normal", "roughness", "metalness", "height"]
}

Output

FieldTypeDescription
images(ImageFile | MapImageFile)[]The extracted seamless texture (no map_type) followed by PBR maps (each with map_type).
seedintegerSeed used for generation
promptstringThe prompt used (may differ from input if prompt expansion was enabled)
timingsobjectTiming breakdown in seconds
Example response
json
{
  "images": [
    { "url": "https://fal.media/files/..." },
    { "url": "https://fal.media/files/...", "map_type": "basecolor" },
    { "url": "https://fal.media/files/...", "map_type": "height" },
    { "url": "https://fal.media/files/...", "map_type": "normal" },
    { "url": "https://fal.media/files/...", "map_type": "roughness" },
    { "url": "https://fal.media/files/...", "map_type": "metalness" }
  ],
  "seed": 42,
  "prompt": "the brick wall"
}

The first image (without map_type) is the extracted seamless texture. The rest are the PBR maps.


Output maps explained

MapWhat it represents
Base ColorThe surface color (albedo). What the material looks like without lighting effects.
NormalPer-pixel surface orientation. Adds fine detail and bumps without changing geometry.
RoughnessHow rough or smooth each point is. Controls reflection sharpness.
MetalnessWhether each point is metallic or dielectric. Affects how light reflects and refracts.
HeightElevation data. Can be used for parallax mapping or actual mesh displacement.

Code examples

JavaScript
javascript
import { fal } from "@fal-ai/client";

const result = await fal.subscribe("fal-ai/patina/material/extract", {
  input: {
    prompt: "the brick wall",
    image_url: "https://example.com/photo-of-building.jpg"
  },
  logs: true,
  onQueueUpdate: (update) => {
    if (update.status === "IN_PROGRESS") {
      update.logs.map((log) => log.message).forEach(console.log);
    }
  },
});
console.log(result.data);
Python
python
import fal_client

result = fal_client.subscribe(
    "fal-ai/patina/material/extract",
    arguments={
        "prompt": "the brick wall",
        "image_url": "https://example.com/photo-of-building.jpg"
    },
    with_logs=True,
)
print(result)
cURL
bash
curl -X POST https://fal.run/fal-ai/patina/material/extract \
  -H "Authorization: Key $FAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "the brick wall",
    "image_url": "https://example.com/photo-of-building.jpg"
  }'