Skip to main content

pictomancer

Python SDK for Pictomancer.ai — a thin httpx wrapper around the REST API at https://api.pictomancer.ai.

Install

pip install .

From PyPI (when published):

pip install pictomancer

Sources

Every operation takes a source: an image URL, a base64 string, or a data: URI. For local files or in-memory bytes use the helpers:

from pictomancer import Client, source_from_bytes, source_from_path

with Client() as client:
    out = client.compress(source_from_path("photo.jpg"), q=80)

    with open("photo.jpg", "rb") as f:
        out = client.compress(source_from_bytes(f.read()), q=80)

Configuration

  • api_key — optional Bearer token (Authorization: Bearer …).
  • base_url — defaults to https://api.pictomancer.ai.
  • timeout — request timeout in seconds (default 30.0).

JSON helpers return dict; image operations return bytes (response body).

Synchronous client

from pictomancer import Client

with Client(api_key="your-api-key") as client:
    info = client.info()
    usage = client.usage()

    meta = client.analyze("https://example.com/image.jpg")

    out = client.resize("https://example.com/image.jpg", scale=0.5, format="webp")
    out = client.compress("https://example.com/image.jpg", q=85, format="jpeg")
    out = client.convert("https://example.com/image.jpg", "png", q=90)
    out = client.crop("https://example.com/image.jpg", 0, 0, 100, 100, format="webp")
    out = client.pipeline(
        "https://example.com/image.jpg",
        [
            {"type": "resize", "params": {"scale": "0.5"}},
            {"type": "convert", "params": {"format": "webp"}},
        ],
    )

    with open("out.webp", "wb") as f:
        f.write(out)

Async client

import asyncio
from pictomancer import AsyncClient


async def main():
    async with AsyncClient(api_key="your-api-key") as client:
        info = await client.info()
        usage = await client.usage()
        meta = await client.analyze("https://example.com/image.jpg")
        out = await client.resize("https://example.com/image.jpg", scale=0.5, format="webp")
        return info, usage, meta, out


asyncio.run(main())

Geometry ops: smart crop, trim, fill, autorot

crop has three mutually exclusive modes:

with Client(api_key="your-api-key") as client:
    # Manual: exact rectangle.
    out = client.crop("https://example.com/image.jpg", 0, 0, 100, 100)

    # Smart: gravity picks the window. One of 'attention', 'entropy', 'centre'.
    out = client.crop("https://example.com/image.jpg", gravity="attention", width=200, height=200)

    # Trim: removes a uniform background border. threshold defaults to 10.0 server-side.
    out = client.crop("https://example.com/image.jpg", trim=True, threshold=5.0)

resize gains a fill mode: pass width + height (instead of scale/scale_x/scale_y) to resize and smart-crop to exact dimensions in one call; gravity defaults to attention.

out = client.resize("https://example.com/image.jpg", width=200, height=150, gravity="entropy")

All four ops (resize, compress, convert, crop) accept autorot=True to apply EXIF orientation before processing.

When a crop actually trims, the response carries X-Pictomancer-Trim-Left/-Top/-Width/-Height headers (inspect them with your own httpx client or event hooks).

Quality target (SSIM)

Instead of guessing a q value, ask for the smallest file that still scores at least a given SSIM. Pass quality_target (float, 0 < v <= 1) to compress or convert; the server binary-searches the encoder quality for you.

with Client(api_key="your-api-key") as client:
    out = client.compress("https://example.com/image.jpg", format="webp", quality_target=0.95)
    out = client.convert("https://example.com/image.jpg", "avif", quality_target=0.9)

Constraints (validated server-side, violations return 422):

  • Mutually exclusive with q, and with lossless=True on convert.
  • Only for jpeg, webp and avif outputs; compress requires an explicit format.
  • Not supported inside pipeline operations.
  • Carries a flat surcharge for the extra encodes.

The search outcome is reported in response headers (the SDK returns the body only; inspect them with your own httpx client or event hooks if you need them):

  • X-Pictomancer-Quality-Target - the target you asked for.
  • X-Pictomancer-Quality-Achieved - SSIM of the returned encode, e.g. 0.9530.
  • X-Pictomancer-Quality-Q-Final - encoder quality the search settled on.
  • X-Pictomancer-Quality-Encodes - encode cycles spent.

Headers are absent when no search ran. X-Pig-Billed is 0 when the input came back untouched (already within target at its current size).

Delivery: write the result somewhere else

By default an operation returns the optimized bytes. Pass a delivery target to have Pictomancer write the result directly to your storage or endpoint instead — the operation then returns a dict (etag, sha256, bytes written, ...). No cloud credentials ever reach Pictomancer.

from pictomancer import Client, PutUrl, Callback

with Client(api_key="your-api-key") as client:
    # Upload to a customer-signed presigned PUT URL (S3/R2/GCS/Azure).
    res = client.resize(
        "https://example.com/image.jpg",
        scale=0.5,
        delivery=PutUrl("https://bucket.s3.amazonaws.com/key?X-Amz-Signature=..."),
    )
    print(res["sha256"], res["bytes_written"])

    # Or POST the bytes to your own callback endpoint (async/large jobs).
    res = client.compress(
        "https://example.com/image.jpg",
        delivery=Callback("https://hooks.example.com/pig?token=secret"),
    )
    print(res["status"], res["sha256"])

PutUrl and Callback accept optional headers= (whitelisted storage headers, e.g. Content-Type, Cache-Control, x-amz-*). The returned sha256 is the digest of exactly the bytes delivered, so you can verify the stored object.

Authenticating a callback

Pass secret= to Callback to have the POST body signed. We send X-Pig-Signature: sha256=<hex> (HMAC-SHA256 of the body, GitHub-webhook style). The secret is used per request and never stored. Verify it on your endpoint:

res = client.resize(
    "https://example.com/image.jpg",
    scale=0.5,
    delivery=Callback("https://hooks.example.com/pig", secret="shared-secret"),
)

# On your endpoint (any framework), recompute and constant-time compare:
import hashlib, hmac
expected = "sha256=" + hmac.new(b"shared-secret", request_body, hashlib.sha256).hexdigest()
assert hmac.compare_digest(expected, request.headers["X-Pig-Signature"])

Errors use httpx behavior: non-2xx responses raise httpx.HTTPStatusError after raise_for_status().

API documentation

Interactive docs: https://api.pictomancer.ai/docs

OpenAPI: https://api.pictomancer.ai/openapi.json

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pictomancer-0.5.0.tar.gz (17.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pictomancer-0.5.0-py3-none-any.whl (6.5 kB view details)

Uploaded Python 3

File details

Details for the file pictomancer-0.5.0.tar.gz.

File metadata

  • Download URL: pictomancer-0.5.0.tar.gz
  • Upload date:
  • Size: 17.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pictomancer-0.5.0.tar.gz
Algorithm Hash digest
SHA256 d3f2ca45d9bb18d711f660f1749e5b190efb6d9381bd6ad3245dcd35ac392028
MD5 4ceaf6febb318d91020b014191067562
BLAKE2b-256 a2f8b4ede5cded7551fb12b525f26ecd97738af27b6cbc36e5dc75027a17774a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pictomancer-0.5.0.tar.gz:

Publisher: publish.yml on pictomancer/python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pictomancer-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: pictomancer-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 6.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pictomancer-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6c02d2a5c7db58d75f60f1f5aac8f5ab0bb47f916bb762f78aebb81ea3af9237
MD5 b756aeac23505677d286b40927e46663
BLAKE2b-256 aca038bb74600e17cee18ddc8639799921f73b857c91b19e35da6059edc9d516

See more details on using hashes here.

Provenance

The following attestation bundles were made for pictomancer-0.5.0-py3-none-any.whl:

Publisher: publish.yml on pictomancer/python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.7.0

2 files

0.6.0

2 files

This release

0.5.0 This release

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page