Générateur de planche-contact
La préparation d’une planche-contact ne devrait pas imposer plusieurs essais de redimensionnement.
Lancer gratuitement
Indiquez la largeur et la hauteur en pixels de chaque image ainsi que la largeur maximale disponible : ce calculateur renvoie une grille pratique dotée d’un cadre uniforme pour les miniatures. Le résultat précise les colonnes, les lignes, la taille des miniatures et les dimensions finales de la planche. La mise en page accueille tous les formats d’origine, respecte la largeur limite et repose sur un calcul déterministe qui produit toujours le même résultat.
Préparez les dimensions et la largeur limite
Commencez par créer un enregistrement pour chaque image destinée à la planche-contact. Chaque enregistrement doit comporter une largeur et une hauteur en pixels, toutes deux exprimées sous forme d’entiers positifs. Les fichiers ne sont ni transmis ni décodés : seules leurs dimensions sont nécessaires. Incluez toutes les images, car leur nombre détermine la quantité de cellules requises, tandis que la plus grande largeur et la plus grande hauteur des sources définissent un cadre commun capable d’accueillir toute la collection sans recadrage. Définissez ensuite max_sheet_width selon la largeur en pixels disponible dans votre document, votre exportation, votre galerie ou votre processus d’impression. Le calculateur considère cette valeur comme une limite absolue. Il ne réserve aucune place pour les marges externes, légendes, gouttières, bordures ou fonds perdus ; retranchez donc ces espaces au préalable si un autre système doit les ajouter. Une liste vide est refusée, car les colonnes, les lignes et la taille des miniatures n’ont aucun sens sans élément. Les dimensions fractionnaires, nulles, négatives ou incorrectes sont également rejetées afin de préserver la fiabilité des traitements automatisés.
Comprenez la sélection de la grille
Le solveur examine tous les nombres de colonnes réalisables, de un jusqu’au nombre total d’images. Pour chaque possibilité, il calcule le nombre de lignes requis par arrondi supérieur, divise la largeur maximale de la planche en cellules uniformes d’une largeur entière, puis déduit la hauteur correspondante de l’enveloppe des dimensions sources. Il obtient ainsi un cadre homogène adapté à un placement de type contain : le moteur réduit chaque image proportionnellement jusqu’à ce qu’elle tienne dans le cadre, quitte à laisser un espace libre sur un axe, mais sans imposer de recadrage. Le solveur compare ensuite la largeur et la hauteur de la planche produite et retient la configuration la plus proche d’un carré. Une planche compacte et équilibrée est généralement plus facile à parcourir et évite la longue bande d’une seule colonne que créerait la seule maximisation des miniatures. À égalité, la plus grande surface de miniature l’emporte, puis le plus petit nombre de colonnes. La largeur ne dépasse pas non plus celle de la source la plus large, afin d’éviter tout agrandissement inutile. Tous les calculs utilisent des pixels entiers et des règles de départage déterministes.
Exploitez le résultat dans un moteur de rendu
La réponse fournit count, columns, rows, thumbnail_size, sheet_size, max_sheet_width et le mode fit. Créez une toile selon sheet_size.width et sheet_size.height, puis placez l’élément d’indice i dans la colonne égale à i modulo columns et dans la ligne égale à la partie entière de i divisée par columns. Chaque cellule reprend la largeur et la hauteur de miniature indiquées. Redimensionnez la source avec une opération contain, centrez-la dans sa cellule si nécessaire et conservez ses proportions d’origine. La dernière ligne pouvant être incomplète, votre moteur peut laisser les dernières cellules vides ou centrer cette ligne ; la toile calculée conserve volontairement une géométrie rectangulaire simple. Le résultat n’intègre ni gouttières ni légendes. Pour ajouter, par exemple, dix pixels d’espacement, réservez leur largeur totale avant le calcul ou réduisez uniformément les dimensions obtenues. Le service convient aux usages interactifs comme aux traitements répétables : une entrée identique donne une sortie identique, aucune requête réseau n’est effectuée et le contenu visuel n’est jamais analysé. L’usage de l’API coûte $0.002 par requête, tandis que le navigateur peut exécuter localement le même calcul pur.
Cas d’usage
Préparer une planche d’épreuves photo
Choisissez une grille équilibrée respectant une largeur d’exportation fixe avant de charger ou redimensionner les originaux.
Créer l’aperçu d’une médiathèque
Transformez les métadonnées enregistrées en colonnes, lignes et dimensions de cellule déterministes pour une galerie.
Composer des pages d’aperçu de données
Disposez des échantillons portrait, paysage et carrés dans des cadres contain uniformes sans les recadrer.
Questions fréquentes
Quel est le tarif ?
L’exécution par API coûte $0.002 par requête. Le calcul peut aussi être effectué gratuitement et localement dans le navigateur.
Mes images sont-elles redimensionnées ou assemblées ?
Non. Seules les mesures de mise en page sont renvoyées ; votre moteur réalise le redimensionnement et l’assemblage.
Les images portrait et paysage seront-elles recadrées ?
Aucun recadrage n’est nécessaire. La taille de miniature est un cadre prévu pour un placement contain respectant les proportions.
Les espacements, légendes et marges sont-ils inclus ?
Non. Réservez la place des gouttières, étiquettes, bordures, marges ou fonds perdus avant de fixer la largeur maximale.
Pourquoi une liste d’images vide provoque-t-elle une erreur ?
Une grille sans élément ne possède ni nombre de lignes ni taille de miniature utiles ; cette entrée est donc explicitement refusée.
Pour les développeurs — accès API
Tout sur cette page est disponible par programmation. Cette section s'adresse aux équipes qui veulent l'intégrer à leurs systèmes ; les autres peuvent simplement utiliser l'outil ci-dessus.
Endpoint
Authentification par jeton Bearer : un seul POST met la tâche en file d’attente, et le résultat vous parvient par webhook ou lien signé.
Appeler depuis votre stack
curl -X POST https://api.kit.forhosting.com/image/contact-sheet-layout \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"images":[{"width":1600,"height":900},{"width":1200,"height":1600},{"width":2048,"height":1365},{"width":800,"height":800},{"width":1920,"height":1080}],"max_sheet_width":1200}'const res = await fetch("https://api.kit.forhosting.com/image/contact-sheet-layout", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"images": [
{
"width": 1600,
"height": 900
},
{
"width": 1200,
"height": 1600
},
{
"width": 2048,
"height": 1365
},
{
"width": 800,
"height": 800
},
{
"width": 1920,
"height": 1080
}
],
"max_sheet_width": 1200
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/image/contact-sheet-layout",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"images": [
{
"width": 1600,
"height": 900
},
{
"width": 1200,
"height": 1600
},
{
"width": 2048,
"height": 1365
},
{
"width": 800,
"height": 800
},
{
"width": 1920,
"height": 1080
}
],
"max_sheet_width": 1200
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/image/contact-sheet-layout", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"images":[{"width":1600,"height":900},{"width":1200,"height":1600},{"width":2048,"height":1365},{"width":800,"height":800},{"width":1920,"height":1080}],"max_sheet_width":1200}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"images":[{"width":1600,"height":900},{"width":1200,"height":1600},{"width":2048,"height":1365},{"width":800,"height":800},{"width":1920,"height":1080}],"max_sheet_width":1200}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/image/contact-sheet-layout", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Exemple de requête
{
"images": [
{
"width": 1600,
"height": 900
},
{
"width": 1200,
"height": 1600
},
{
"width": 2048,
"height": 1365
},
{
"width": 800,
"height": 800
},
{
"width": 1920,
"height": 1080
}
],
"max_sheet_width": 1200
}Exemple de réponse
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "image.contact_sheet_layout",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}L’API est asynchrone : chaque appel renvoie un task_id immédiatement, puis vous interrogez l’état à raison d’une requête par seconde.
Tarifs
Le prix est publié, sans tokens ni crédits. Une tâche qui échoue n’est pas facturée.
Limites
max_mb | 15 |
max_megapixels | 12 |
Erreurs
| HTTP | Code | Signification |
|---|---|---|
401 | unauthorized | Clé API absente ou invalide : vérifiez l’en-tête Authorization. |
402 | insufficient_balance | Solde insuffisant : rechargez votre compte pour lancer cette tâche. |
404 | unknown_type | Type de tâche inconnu : vérifiez le champ type de votre requête. |
429 | rate_limited | Trop de requêtes : ralentissez la cadence, puis réessayez. |