Gerador de folha de contato
Planejar uma folha de contato não deveria exigir várias tentativas de redimensionamento.
Executar grátis
Informe a largura e a altura em pixels de cada imagem, além da maior largura permitida, e esta calculadora retornará uma grade prática com uma caixa uniforme para miniaturas. O resultado apresenta colunas, linhas, tamanho da miniatura e dimensões finais da folha. O layout acomoda todas as proporções das origens, respeita o limite de largura e usa cálculos determinísticos que sempre geram o mesmo resultado.
Prepare as dimensões e o limite de largura
Comece com um registro para cada imagem que aparecerá na folha de contato. Cada registro precisa de largura e altura em pixels, ambas como números inteiros positivos. Os arquivos não são enviados nem decodificados: somente suas dimensões são necessárias. Inclua todas as imagens, pois a quantidade de registros determina quantas células a grade deve oferecer, enquanto a maior largura e a maior altura das origens definem uma caixa comum capaz de conter toda a coleção sem cortes. Em seguida, defina max_sheet_width como a largura em pixels disponível no documento, na exportação, no painel da galeria ou no fluxo de impressão. A calculadora considera esse valor um limite rígido. Ela não reserva espaço para margens externas, legendas, intervalos, bordas ou sangria; desconte essas áreas antes se outro sistema for acrescentá-las. Uma lista vazia é rejeitada porque colunas, linhas e tamanho de miniatura não têm significado útil sem itens. Dimensões fracionárias, nulas, negativas ou inválidas também são recusadas para manter previsíveis os processos automatizados.
Entenda como a grade é escolhida
O algoritmo avalia todas as quantidades viáveis de colunas, de uma até o número de imagens. Para cada opção, ele calcula as linhas necessárias com arredondamento para cima, divide a largura máxima da folha em células uniformes de largura inteira e deriva a altura correspondente a partir do envelope das dimensões originais. Isso cria uma caixa uniforme adequada ao posicionamento contain: o renderizador escala cada imagem proporcionalmente até que ela caiba, talvez deixando espaço livre em um eixo, mas sem exigir corte. Depois, o algoritmo compara a largura e a altura da folha resultante e escolhe a opção mais próxima de um quadrado. Uma folha compacta e equilibrada costuma ser mais fácil de examinar e evita a faixa extrema de uma única coluna que surgiria ao apenas maximizar miniaturas. Se duas opções forem igualmente quadradas, vence a que oferece maior área de miniatura. Persistindo o empate, menos colunas são preferidas. A largura da miniatura também não ultrapassa a origem mais larga, evitando ampliação desnecessária. Todos os cálculos usam pixels inteiros e critérios determinísticos de desempate.
Use o resultado em um renderizador
A resposta fornece count, columns, rows, thumbnail_size, sheet_size, max_sheet_width e o modo fit. Crie uma tela com sheet_size.width e sheet_size.height; depois, posicione o item de índice i na coluna equivalente a i módulo columns e na linha correspondente à parte inteira de i dividida por columns. Cada célula usa a largura e a altura de miniatura retornadas. Redimensione a origem com uma operação contain, centralize-a na célula se desejar e preserve sua proporção original. Como a última linha pode ficar incompleta, o renderizador pode deixar as células finais vazias ou centralizar essa linha; a tela calculada mantém deliberadamente uma geometria retangular simples. O resultado não inclui intervalos nem legendas. Para acrescentar, por exemplo, dez pixels entre células, reserve previamente a largura total desses espaços ou reduza uniformemente as dimensões retornadas. O endpoint atende tanto ao uso interativo quanto a lotes repetíveis: entradas idênticas produzem saídas idênticas, nenhuma solicitação de rede é feita e o conteúdo visual nunca é examinado. O uso da API custa US$ 0,002 por solicitação, enquanto o navegador pode executar localmente o mesmo cálculo puro.
Casos de uso
Planejar uma folha de provas fotográficas
Escolha uma grade equilibrada que caiba em uma largura fixa antes de carregar ou redimensionar as fotos originais.
Criar a prévia de uma biblioteca
Converta metadados de imagens armazenadas em colunas, linhas e dimensões de célula determinísticas para uma galeria.
Preparar páginas de amostras de dados
Organize exemplos verticais, horizontais e quadrados em caixas contain uniformes sem recortes.
Perguntas frequentes
Quanto custa?
A execução pela API custa US$ 0,002 por solicitação. O cálculo também pode ser executado gratuitamente e de forma local no navegador.
Minhas imagens são redimensionadas ou combinadas?
Não. Apenas os números do layout são retornados; seu renderizador realiza o redimensionamento e a composição.
As imagens verticais e horizontais serão cortadas?
Nenhum corte é necessário. O tamanho da miniatura é uma caixa destinada ao posicionamento contain com proporção preservada.
Intervalos, legendas ou margens estão incluídos?
Não. Reserve espaço para intervalos, rótulos, bordas, margens ou sangria antes de definir a largura máxima.
Por que uma lista vazia gera erro?
Uma grade sem itens não possui quantidade útil de linhas nem tamanho de miniatura, portanto a entrada é rejeitada explicitamente.
Para desenvolvedores — acesso via API
Tudo nesta página está disponível via API. Esta seção é para equipes que querem integrar a ferramenta aos próprios sistemas; quem não precisa disso pode simplesmente usar a ferramenta acima.
Endpoint
Autenticação por token Bearer. Um único POST coloca a tarefa na fila; o resultado chega por webhook ou link assinado.
Chame do seu código
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)Exemplo de requisição
{
"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
}Exemplo de resposta
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "image.contact_sheet_layout",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}A API é assíncrona: cada chamada devolve um task_id na hora. Se preferir polling, consulte o status a até 1 requisição por segundo.
Preço
Preço publicado, sem tokens nem créditos escondidos. Tarefa que falha não é cobrada.
Limites
max_mb | 15 |
max_megapixels | 12 |
Erros
| HTTP | Código | O que significa |
|---|---|---|
401 | unauthorized | Token ausente ou inválido. Confira o header Authorization. |
402 | insufficient_balance | Saldo insuficiente para esta tarefa. Faça uma recarga e tente de novo. |
404 | unknown_type | Esse tipo de tarefa não existe. Confira o campo type no catálogo. |
429 | rate_limited | Muitas requisições em pouco tempo. Espere um instante e tente de novo. |