Project 09 · Applied · Kontoor Brands, Inc. · 2026
Automating product-photo prep on a locked-down machine
Every product photo headed for Walmart.com has to be cropped, compressed, renamed, and filed into its own folder before it can be uploaded. Done by hand, across dozens of styles a season, that's hours of careful clicking — and one transposed digit away from putting the wrong image on the wrong product. I built a tool that turns the whole job into a paste-and-run.
A note on scope: I built this on the job during my internship. I've kept the description to my own process and the engineering problems I solved; actual product data (GTINs and style numbers), internal file conventions, and anything proprietary are left out to respect Kontoor and Walmart confidentiality. This sits alongside my main internship work, building the digital shelf for Wrangler & Lee.
The bottleneck
Part of getting a product live on Walmart.com is its photos, and the portal we upload through (Supplier One) wants them to an exact spec. Each image has to be a 2:3 crop at 2200×3000 pixels, under the file-size cap, and — this is the fussy part — sorted so that every product variant has its own folder named after its 14-digit GTIN, with the correctly renamed image inside. The folder you hand the portal has to contain only those GTIN folders; a single stray file breaks the upload.
By hand, that's the same loop for every style: crop and compress each image, make a folder for every GTIN, copy the right photo in, rename it, repeat. The photos arrive as plain square files, so none of the naming is done for you. Across a seasonal assortment it's a few hours of repetitive work, and the failure mode is ugly — one mistyped digit in a fourteen-digit number lands a photo on the wrong product, which is exactly the kind of error a retailer sees before you do.
The hard part wasn't the script
Writing a script to push images around is easy on your own laptop. The catch was the machine it had to run on. Corporate laptops here are locked down, and the tool had to work on any teammate's machine with zero setup — so I was working against a real list of constraints:
- No installs, no admin rights, no Excel macros. VBA is disabled, so the obvious “just write a macro” answer was off the table.
- PowerShell is in Constrained Language Mode. That blocks
Add-Type,System.Drawing, and most of the normal ways you'd touch an image from .NET. - No hardcoded paths. I couldn't bake in a username or an absolute path, because the same file had to run on someone else's account untouched.
So the real problem was delivering reliable batch automation inside an environment built specifically to keep people from running automation. That constraint shaped every decision that followed.
What I built
A single Excel workbook with four tabs. There's no macro in it — it doesn't run anything. It writes the thing that runs:
- Styles & GTINs. Paste the product reference: style number in one column, its GTINs in the next.
- Photo Input. Paste the image file paths straight from Explorer (“Copy as path”).
- Run Script. Formulas assemble a finished PowerShell script from those two inputs. You copy it out and paste it into a PowerShell window.
- Rename Reference. A plain lookup table for the odd manual edge case, kept on its own tab.
The generated script does three things in order — compress, copy, rename — dropping each photo into its correctly named GTIN folder. It also writes a small manifest (<style#>_GTINs.txt) one level up in the season folder, so there's a record of what ran without leaving a stray file inside the upload folder. The whole user workflow collapses to: paste the data, paste the paths, copy the script, paste it into PowerShell, done.
The image step leans on a portable build of ImageMagick — the no-install kind that runs from a folder — with one tuned command:
mogrify -resize 2200x3000^ -gravity center -extent 2200x3000 \
-quality 95 -define jpeg:extent=4700kb *.jpgIt resizes and center-crops to the exact spec, and the jpeg:extent cap keeps files under the portal's size limit without bloating the small ones. Compression has to happen before the copy step, while the images are still loose in the top-level folder.
Three walls I hit
Most of the actual work was in the gap between “this should work” and “this works when a teammate pastes it on a Tuesday.” A few of the problems were worth the scars.
Constrained Language Mode broke my functions
My first version was clean PowerShell — a couple of functions, an if/elseif to route each image. Pasted into a locked-down interactive session, it fell apart: function definitions pasted line by line aren't defined before they get called, and an elseif on its own line breaks when it's pasted in interactively. So I threw out the structure entirely. The workbook now generates flat, literal commands — one explicit Copy-Item line per image — with no functions and no branching, because there's nothing left to break. Excel does the “logic” up front and emits dumb, reliable lines.
Calling a program with no install and no path
I couldn't cd anywhere or assume where ImageMagick lived, so the script finds it at run time and calls it where it stands:
& ((Get-ChildItem "$HOME\Downloads" -Recurse -Filter magick.exe `
-ErrorAction SilentlyContinue | Select-Object -First 1).FullName) mogrify ...$HOME is the one path I could trust, because it's set when the session starts; variables I'd set mid-script weren't reliable in this mode. The quoting matters too — single quotes stop $HOME from expanding, so the workbook bakes real double quotes into the generated text with Excel's CHAR(34) so the paths actually resolve.
Excel kept eating the GTINs
GTINs have leading zeros, and Excel deletes those by default — it sees a number and helpfully trims it, which silently corrupts the one field that absolutely cannot be wrong. Forcing the cells to text and formatting through TEXT(value,"00000000000000") preserves all fourteen digits. Style-number matching goes through TRIM(""&value) so it works whether a code is purely numeric or alphanumeric, without throwing a type mismatch. One more quiet gotcha: the script output has to stay the rightmost column on its tab, so “select to the end” never grabs a wider block and corrupts the commands — which is why the reference tables live on their own tab.
What it saved
I used it across two seasonal assortments — about 43 styles in all. At the team's rough baseline of twelve minutes of prep per style, that's on the order of eight to nine hours of manual clicking it took off the table, but the time was never really the point. The bigger win is that it removes an entire class of error: with the folders and names generated from the source data, nobody is hand-typing a fourteen-digit number anymore, so the wrong-image-on-the-wrong-product mistake just stops happening.
And because it needs no install, it isn't tied to me. Any teammate can open the workbook on their own laptop and run it, so the value stays with the team after my internship ends, not in a tool only I can operate.
What I took away
I came into this internship to learn the sales-operations side of a big retail partnership, not to write code. But I kept noticing the same manual loop eating afternoons, and I'd rather fix that than keep paying for it. Working the problem inside a locked-down machine taught me more than an open one would have — it forced me to understand exactly why each thing was failing instead of reaching for the easy library. Mostly it reminded me that the useful skill isn't the scripting; it's spotting the repetitive, error-prone task in the first place and being stubborn enough to engineer it down to a paste-and-run.
Tools & method
- Excel (Microsoft 365) — the no-code front end and script generator, built on
INDEX/MATCHand helper columns for maximum compatibility - PowerShell (Windows, Constrained Language Mode) — the execution layer, generated as flat, literal commands
- ImageMagick (portable) — batch resize and compress, run with no install
- No frameworks, no installs, no macros — that was the whole constraint
Want to see how it's wired? Here's a scrubbed sample of the workbook (.xlsx, 88 KB) — the same four tabs and the same generated PowerShell, with the real GTINs and style numbers swapped out for placeholders. Open the Run Script tab to see the commands the formulas assemble.
← Back to all work