Publishing Has an Image Problem
You’ve finished writing the book. The manuscript is done, the layout is set, and the 47 images — diagrams, photos, illustrations — are scattered across a folder in various formats and sizes. Now you need to publish.
KDP (Kindle Direct Publishing) wants interior images at 300 DPI, JPEG or TIFF, and no wider than the trim size minus margins. EPUB readers need images small enough to not bloat the file — a 50MB EPUB with high-res photos won’t download well on a Kindle over cellular. Print-ready PDFs need full resolution at the exact trim dimensions, preferably PNG to avoid JPEG artifacts in diagrams.
That’s three different specs from one set of source images. Multiply by 47 images and you’re spending a day in Photoshop running “Save As” with different settings for each output format.
The Image Transformation API processes images to publishing specs with a single API call per image. Define the pipeline for each format once, and every image in the manuscript gets the same treatment.
The KDP Interior Pipeline
KDP interior images need to fit within the printable area of the page. For a standard 6”x9” book with 0.5” margins, the max image width is 5 inches. At 300 DPI, that’s 1500 pixels. Height depends on the image, but keeping it within the printable height (8 inches = 2400px at 300 DPI) prevents awkward page breaks.
import { IterationLayer } from "iterationlayer";
const client = new IterationLayer({ apiKey: "YOUR_API_KEY" });
const result = await client.transform({
file: { type: "url", name: "diagram-03.png", url: sourceUrl },
operations: [
// Fit within KDP printable area (5"x8" at 300 DPI)
{ type: "resize", width_in_px: 1500, height_in_px: 2400, fit: "inside" },
// Sharpen after resize — important for text in diagrams
{ type: "sharpen", sigma: 0.5 },
// JPEG at high quality for KDP interior
{ type: "convert", format: "jpeg", quality: 95 },
],
});
fit: "inside" constrains the image so neither dimension exceeds the target. A landscape diagram might become 1500x900. A portrait chart might become 1500x2400. The aspect ratio stays intact.
Quality 95 is intentional. KDP interior images are viewed at print resolution — JPEG artifacts that are invisible on screen can show up in print, especially in diagrams with thin lines and small text. Going high on quality keeps file size reasonable while avoiding visible compression artifacts.
The EPUB Pipeline
EPUB has a different constraint: total file size. A bloated EPUB downloads slowly, takes up device storage, and some distributors reject EPUBs over a certain size. Amazon recommends keeping Kindle books under 50MB for optimal delivery.
If your book has 47 images averaging 2MB each in the source, that’s 94MB of images alone. They need to shrink significantly.
const EPUB_MAX_IMAGE_SIZE_IN_BYTES = 300_000;
const epubOperations = [
// EPUB readers are typically 600-800px wide
{ type: "resize", width_in_px: 800, height_in_px: 1200, fit: "inside" },
{ type: "sharpen", sigma: 0.5 },
// JPEG for photos, keeps file size down
{ type: "convert", format: "jpeg" },
// Each image under 300KB — 47 images = ~14MB total
{ type: "compress_to_size", max_file_size_in_bytes: EPUB_MAX_IMAGE_SIZE_IN_BYTES },
];
800px wide is a good target for EPUB. Most e-readers display at 600-800px, and tablets show around 768-1024px. Going beyond that wastes bytes that readers on low-bandwidth connections or small devices won’t benefit from.
compress_to_size at 300KB per image keeps 47 images under 15MB total — well within EPUB size guidelines. The quality-first compression strategy means photos keep their detail as much as possible. Diagrams with fewer colors compress better and will stay at higher quality levels automatically.
For diagrams and illustrations with solid colors and text, PNG might be preferable to avoid JPEG artifacts around sharp edges:
const epubDiagramOperations = [
{ type: "resize", width_in_px: 800, height_in_px: 1200, fit: "inside" },
{ type: "sharpen", sigma: 0.5 },
{ type: "convert", format: "png" },
{ type: "compress_to_size", max_file_size_in_bytes: 300_000 },
];
PNG compresses losslessly, so compress_to_size will reduce dimensions if the PNG at 800px is still over 300KB. For most diagrams, 800px wide in PNG will be well under the limit.
The Print-Ready Pipeline
Print production wants maximum quality. No JPEG artifacts, no dimension reduction beyond what the layout requires. PNG is the safe format — lossless compression preserves every pixel.
const printOperations = [
// Full print dimensions: 6"x9" at 300 DPI, full bleed
{ type: "resize", width_in_px: 1800, height_in_px: 2700, fit: "inside" },
{ type: "sharpen", sigma: 0.3 },
// PNG for lossless quality
{ type: "convert", format: "png" },
];
No compress_to_size here. Print files can be large — the printer handles them fine. What matters is pixel integrity. PNG ensures no generation loss from JPEG re-encoding, which is especially important if the images will go through additional processing in the layout tool.
The sharpen value is lower (0.3 vs 0.5) because print resolution is higher. Over-sharpening at 300 DPI creates visible halos around edges that look fine on screen but bad in print.
Processing an Entire Manuscript
A book’s images typically live in a folder or CMS. Process them all at once by defining the pipeline for each output format and running them in parallel.
import { IterationLayer } from "iterationlayer";
const client = new IterationLayer({ apiKey: "YOUR_API_KEY" });
const OUTPUT_FORMAT_OPERATIONS = {
kdp: [
{ type: "resize", width_in_px: 1500, height_in_px: 2400, fit: "inside" },
{ type: "sharpen", sigma: 0.5 },
{ type: "convert", format: "jpeg", quality: 95 },
],
epub: [
{ type: "resize", width_in_px: 800, height_in_px: 1200, fit: "inside" },
{ type: "sharpen", sigma: 0.5 },
{ type: "convert", format: "jpeg" },
{ type: "compress_to_size", max_file_size_in_bytes: 300_000 },
],
print: [
{ type: "resize", width_in_px: 1800, height_in_px: 2700, fit: "inside" },
{ type: "sharpen", sigma: 0.3 },
{ type: "convert", format: "png" },
],
} as const;
const transformForFormat = async (
imageUrl: string,
fileName: string,
format: keyof typeof OUTPUT_FORMAT_OPERATIONS,
) => {
const { data: { buffer } } = await client.transform({
file: { type: "url", name: fileName, url: imageUrl },
operations: OUTPUT_FORMAT_OPERATIONS[format],
});
return Buffer.from(buffer, "base64");
};
// Process all manuscript images for all formats
const manuscriptImages = [
{ url: "https://storage.example.com/book/chapter-1-diagram.png", name: "chapter-1-diagram.png" },
{ url: "https://storage.example.com/book/chapter-2-photo.jpg", name: "chapter-2-photo.jpg" },
{ url: "https://storage.example.com/book/chapter-3-chart.png", name: "chapter-3-chart.png" },
// ... 44 more images
];
// Generate all three variants for every image
const allVariants = await Promise.all(
manuscriptImages.flatMap(({ url, name }) => [
transformForFormat(url, name, "kdp"),
transformForFormat(url, name, "epub"),
transformForFormat(url, name, "print"),
])
);
47 images across 3 formats is 141 API calls. They run in parallel, so the wall-clock time is roughly the same as processing a single image. No Photoshop, no batch actions, no “Save As” dialogs.
Cover Images
Book covers have their own specifications. KDP covers need exact pixel dimensions based on trim size and page count (spine width varies). A standard 6”x9” cover at 300 DPI with a spine is roughly 3870x2700 pixels for a 200-page book.
Cover processing is usually simpler — the designer delivers a full-resolution file, and you just need format conversion and possibly dimension adjustment:
const kdpCoverOperations = [
// Exact dimensions for KDP cover (6"x9" with spine, 300 DPI)
{ type: "resize", width_in_px: 3870, height_in_px: 2700, fit: "fill" },
{ type: "convert", format: "jpeg", quality: 95 },
];
fit: "fill" stretches to the exact dimensions without preserving aspect ratio. Use this only when you know the source is already at the correct aspect ratio and just needs a dimension adjustment.
Handling Low-Resolution Source Images
Sometimes manuscript images are low resolution — screenshots at 72 DPI, web images the author pulled from a reference, diagrams exported at screen resolution. These look fine in a Word document but fall apart in print.
The upscale operation uses AI to increase resolution:
const upscaleForPrintOperations = [
// Upscale 2x — a 600px image becomes 1200px
{ type: "upscale", factor: 2 },
{ type: "resize", width_in_px: 1500, height_in_px: 2400, fit: "inside" },
{ type: "sharpen", sigma: 0.3 },
{ type: "convert", format: "png" },
];
AI upscaling generates real detail rather than just interpolating pixels. A screenshot upscaled 2x looks noticeably better than the same screenshot resized with bicubic interpolation. It won’t match a natively high-resolution image, but it’s a significant improvement over blurry upscaling.
Get Started
The Image Transformation API is part of Iteration Layer. Sign up for a free account — no credit card required — and get an API key in the dashboard.
The Image Transformation docs cover all 24 operations. For publishing workflows, the combination of resize, convert, sharpen, and compress_to_size handles KDP, EPUB, and print-ready variants from a single set of source images.