A behind-the-scenes walkthrough of building print-ready 10 by 10 foot posters with code: the pixel arithmetic, HTML and CSS layout, trigonometry, SVG drawing, AI image upscaling, PDF rendering and how to check the result honestly.
A poster looks like a design problem, and it is. But the moment it has to be printed ten feet wide, it also becomes an arithmetic problem, a programming problem and an image-quality problem, all at once. Almost every idea in this chapter is something you meet in first-year computer science and maths, just wearing a different hat: units, ratios, trigonometry, algorithms, abstraction, automation and testing.
This chapter walks through exactly how a set of ten Brahma Kumaris posters was built for a 10 by 10 foot print, step by step, including the mistakes. It is a real project, not a tidy textbook one, so you get the dead ends too.
How to turn "10 feet" into numbers a computer can use, why code can be a better layout tool than a paint program, where trigonometry and ratios show up in a poster, how AI image enlargement works and where it stops working, how the final PDF and 12000-pixel image were produced, and how to check your own work without fooling yourself.
The request was: make each poster square (1:1) and print it at 10 feet by 10 feet, in very high quality. Before drawing a single box, convert that into numbers.
That last number explains the whole project. A photograph or painting that looks fine on a phone has maybe 1 to 2 million pixels. The print needs roughly a hundred times more, so something has to give: either the content is naturally vector (sharp at any size) or the pixels have to come from somewhere.
Why 100 PPI is enough. Your eye can separate two dots only if they are more than about one arcminute (1/60 of a degree) apart. For a pixel of size p seen from distance d, the pixel is invisible when p / d is below about 0.00029. At 100 PPI the pixel pitch is 0.01 inch, so you stop seeing individual pixels beyond roughly 34 inches, a little under one metre. A poster this size is viewed from further away than that, so 100 PPI looks smooth. A 37 PPI picture (the first version of one portrait) stays smooth only beyond roughly 2.4 metres. This is the same reasoning behind "billboards can be low resolution".
Each poster is a small program that produces an HTML page. The page is 1200 x 1200 CSS pixels, laid out with ordinary HTML and CSS: absolutely-positioned boxes, cards, headers and footers, fonts loaded from packages (Mukta for Hindi, Poppins and Cormorant Garamond for English).
Why code instead of a paint program?
The posters that came from the center's earlier tall (2:3) designs had to be rebuilt, not stretched. Changing from 900 x 1350 to 1200 x 1200 changes the shape of the available space, so content has to be re-arranged: two columns where there was one, images cropped to a new ratio, paragraphs reflowed. Stretching would distort faces and symbols.
Fitting a picture into a box of a different shape is the same ratio problem every time. A picture 1280 x 720 has ratio 1.78. A box that is 534 x 300 has ratio 1.78, so it fits exactly. A 600 x 673 portrait going into a 540 x 674 arch has a slightly different ratio, so some of the picture must be cut. CSS calls this object-fit: cover, and a position such as 50% 18% chooses which part to keep.
Another place ratios appear: on the first poster, a composite illustration contained baked-in text labels that had to be covered with live (sharp) text, and red arrows had to be placed on top. Those arrows were placed using fractions of the image's width and height (for example x = 0.42, y = 0.31) instead of pixel positions. Because a fraction is the same at any size, the arrows stay in the right place whether the image is 600 pixels wide or 6000.
Circles and rays are where school trigonometry earns its place.
cx + r cos(a) and cy + r sin(a). A ring of 40 beads on a gold medallion is just that formula run for a = 0, 9, 18 degrees and so on up to 351.repeating-conic-gradient that alternates a colour every 5 degrees around a centre point.The three deity medallions on one poster were drawn in code as SVG, a vector drawing format. SVG shapes are built from points, straight lines and Bezier curves. A cubic Bezier curve is defined by four points: where it starts, where it ends, and two "handle" points that pull the curve towards them. A face, a crown or a beard is a handful of such curves.
Useful ideas used here:
Later, the center supplied its own traditional Brahma-Vishnu-Shankar picture, and the hand-drawn version was replaced by it. That is the right outcome: code is good for geometry, but for sacred imagery the community's own artwork is the better source.
Some pictures arrived small: a 600-pixel portrait, 1280-pixel video stills, a wheel chart. Enlarging them the old way (bicubic or Lanczos resampling) just spreads the same information over more pixels, which looks blurry. Lanczos resampling computes each new pixel as a weighted average of nearby old pixels using a windowed sinc curve, which is mathematically the best simple interpolation, but it cannot invent detail.
Super-resolution networks are trained on millions of pairs of sharp and blurred pictures. They learn what edges, hair, text strokes and skin texture usually look like, and they paint that detail in. Two models were used:
Practical tricks that made it work:
INTER_AREA) to a target of 5600 pixels wide.A command like this is how the heavy model's tiles are run:
python3 up_face.py # x4plus, tile 200 px with 20 px padding
python3 up_face2.py # second pass, then resize to 5600 px wide
This is the single most important idea in the chapter. A picture can have a nominal resolution (the number of pixels in the file) and a real resolution (how much true detail was captured). The portrait was only 500 pixels wide when captured. After two AI passes the file is 5600 pixels wide, so the nominal resolution is over 10 pixels per CSS pixel. But the real detail is about one pixel per CSS pixel. Everything finer than that was invented by the network. It looks convincing, but it is a plausible guess, not a recording of her face.
So up close, at 10 feet, that portrait can still look a bit soft and slightly painterly. The only real fix is a better original photo. This is why photographers shoot at high resolution even when the final use looks small. Whenever you can, fix the problem at the source instead of the output.
Where the original was good, AI was safe to use. The Kalpa Vriksha chart arrived at 2259 x 3200 pixels, and the Srishti-chakra picture at the same size, so enlarging them mostly sharpened real detail. The portrait was the weak link.
A headless browser (Chromium, driven by Playwright) loads the HTML page and prints it. Because the page is built with a scale factor of 9.6, a 1200 CSS-pixel canvas becomes exactly 120 inches. The call looks like this:
page.pdf(width='120in', height='120in', print_background=True,
margin={'top':'0','bottom':'0','left':'0','right':'0'})
The result is a one-page PDF measuring 8640 x 8640 points, with live vector text and the embedded pictures.
The big JPG is then made from that PDF with Poppler's pdftoppm:
pdftoppm -r 100 -jpeg -jpegopt quality=92 -singlefile poster.pdf poster_12000x12000
-r 100 means 100 PPI, which over 120 inches gives 12,000 pixels per side. JPEG quality 92 is a good balance: nearly invisible compression, much smaller than PNG.
Two practical limits surfaced:
zip -0 (store only, no recompression, because a JPG does not compress further).The technical work only matters if the poster is what the center needs. The real workflow looked like this:
Two habits worth copying: show a cheap preview before the expensive final, and never invent facts. Every statement on the welcome poster came from the page the center supplied. Also, use only photographs and artwork you have the right to use.
After every change, the page was rendered to an image and actually looked at. The checks that caught real problems:
pdfinfo and from the file itself, not assumed.Seen from a distance, the work is a small build pipeline, very much like the one in What Is a CI/CD Pipeline, Really:
And the build scripts follow the habits in Writing Idempotent Deployment Scripts: they can be re-run safely, they write outputs to new, clearly named files, and a failed step stops the sequence before anything is delivered.
A short exercise that locks in the maths:
The scripts behind this chapter are small enough to read in one sitting. Download the poster pipeline source (zip, about 20 KB). Read its README first: the artwork and the AI model weights are not included, and the folder paths need changing for your machine.
If any of the terms above (abstraction, layers, build steps) felt unfamiliar, start with What Computer Science Actually Is. To see how the same "trigger, build, test, deliver" idea runs a real website, read What Is a CI/CD Pipeline, Really.
An honest picture of what a computer science degree really is before you start — problem-solving over memorization, why it's not just 'learning to code', and how to set the right expectations for four years.
CI/CD explained without the buzzwords — what continuous integration and continuous deployment actually automate, and what a real pipeline looks like end to end.
What idempotent actually means for a deployment or automation script, why it matters when a script might be run twice by accident, and concrete patterns for writing scripts that are safe to re-run.