[{"data":1,"prerenderedAt":316},["ShallowReactive",2],{"blog-\u002Fblog\u002Fcodex-img-0-5-0":3,"mp-\u002Fblog\u002Fcodex-img-0-5-0":289,"more-posts-\u002Fblog\u002Fcodex-img-0-5-0":294},{"id":4,"title":5,"body":6,"category":271,"date":272,"description":273,"draft":274,"extension":275,"meta":276,"navigation":277,"path":278,"project":279,"seo":280,"stem":282,"tags":283,"__hash__":288},"blog\u002Fblog\u002Fcodex-img-0-5-0.md","codex-img 0.5.0 turns generated images into game sprites",{"type":7,"value":8,"toc":262},"minimark",[9,20,28,33,74,77,84,95,99,102,108,111,114,118,124,130,133,137,140,150,154,203,212,219,228,232,239,243,258],[10,11,12,19],"p",{},[13,14,18],"a",{"href":15,"rel":16},"https:\u002F\u002Fgithub.com\u002Ffoksa\u002Fcodex-img\u002Freleases\u002Ftag\u002Fv0.5.0",[17],"nofollow","codex-img 0.5.0"," is out, together with 0.4.0 from earlier today. Both releases come from one project: I used codex-img to make the art for a small racing game, with Claude Code writing the prompts and running the tool.",[10,21,22,23,27],{},"Generating went well. Every image was usable on the first try, and editing with a reference image (",[24,25,26],"code",{},"-i",") let me change one part of a picture without touching the rest. The work came after generating: every sprite needed cropping to its visible content, resizing, and cleaning up, and that happened in a separate Python script. These two releases move that script into codex-img.",[29,30,32],"h2",{"id":31},"one-command-from-prompt-to-sprite","One command, from prompt to sprite",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-sh shiki shiki-themes github-light github-dark","codex-img - -b transparent --hard-alpha --trim=4 --resize 400x300 --no-enlarge -c 160 -o kart.png \u003C\u003C'EOF'\nGame asset sprite for a retro racing game: a small red go-kart with a driver\nin a white helmet and blue suit, seen from the side... 16-bit arcade pixel art...\nIsolated on a transparent background, no ground, no shadow, no text.\nEOF\n","sh","",[24,41,42,50,56,62,68],{"__ignoreMap":39},[43,44,47],"span",{"class":45,"line":46},"line",1,[43,48,49],{},"codex-img - -b transparent --hard-alpha --trim=4 --resize 400x300 --no-enlarge -c 160 -o kart.png \u003C\u003C'EOF'\n",[43,51,53],{"class":45,"line":52},2,[43,54,55],{},"Game asset sprite for a retro racing game: a small red go-kart with a driver\n",[43,57,59],{"class":45,"line":58},3,[43,60,61],{},"in a white helmet and blue suit, seen from the side... 16-bit arcade pixel art...\n",[43,63,65],{"class":45,"line":64},4,[43,66,67],{},"Isolated on a transparent background, no ground, no shadow, no text.\n",[43,69,71],{"class":45,"line":70},5,[43,72,73],{},"EOF\n",[10,75,76],{},"This took 29 seconds. The backend returned a 1536x1024 PNG of 1.1 MB, and codex-img saved this 400x215 sprite of 13.7 KB:",[10,78,79],{},[80,81],"img",{"alt":82,"src":83},"A pixel-art sprite of a red go-kart with a driver in a white and red helmet and a blue suit, puffing smoke from its exhaust, on a transparent background","\u002Fimg\u002Fblog\u002Fcodex-img-0-5-0\u002Fkart.png",[10,85,86,87,90,91,94],{},"It also kept the untouched original as ",[24,88,89],{},"kart.raw.png",". The quota for it is already spent, and the backend has no seed, so an image can't be generated again exactly. ",[24,92,93],{},"--json"," reports both files, the size of each, and where the crop sat in the original, so a game can keep a sprite's anchor point.",[29,96,98],{"id":97},"whats-hidden-under-the-transparent-pixels","What's hidden under the transparent pixels",[10,100,101],{},"A transparent pixel has an alpha of 0, but it still stores a colour, and nothing shows it. Generated images store a dark vignette with coloured glows there. On the left is the raw kart as it looks; on the right is the same file with the alpha channel ignored:",[10,103,104],{},[80,105],{"alt":106,"src":107},"Two versions of the raw go-kart image. On the left it sits on a checkerboard, as an image viewer shows transparency. On the right the transparency is ignored, revealing a black background with red and blue-white glows around the kart and its smoke","\u002Fimg\u002Fblog\u002Fcodex-img-0-5-0\u002Fhidden.webp",[10,109,110],{},"It stays invisible until something resizes or filters the image without taking alpha into account. Then the hidden colour mixes into the edge pixels and the sprite gets a dark outline. Game engines do exactly this kind of filtering when they draw a scaled texture.",[10,112,113],{},"Setting those pixels to transparent black doesn't help, because black is also a colour that bleeds in. codex-img handles it in two places. Its own resize works with premultiplied alpha, so a transparent pixel contributes nothing, whatever colour it stores. And PNG output gets the colour of the nearest visible pixel written under every fully transparent one, which is what texture tools call edge bleed. On a test sprite, a plain downscale afterwards left its edge colour intact (a green channel of 200, as in the sprite) with bleed, and dragged it down to 50 without. As a side effect, the file shrank from 58 KB to 6 KB, because the hidden glows compress badly.",[29,115,117],{"id":116},"the-trim-bug-that-only-real-art-found","The trim bug that only real art found",[10,119,120,123],{},[24,121,122],{},"--trim"," crops an image to its visible pixels. In 0.4.0, visible meant an alpha above 0. My test images had clean alpha, so it worked, but when I ran it on the game's actual art, it barely cropped anything. Generated images scatter faint specks, with an alpha of 1 to 16, all over the transparent background. Here they are in yellow on the kart:",[10,125,126],{},[80,127],{"alt":128,"src":129},"The raw go-kart on a checkerboard, with faint specks marked in yellow along the edges and near the bottom. A grey box around almost the whole canvas shows the crop that counts the specks; a tighter red box around the kart shows the crop 0.5.0 makes","\u002Fimg\u002Fblog\u002Fcodex-img-0-5-0\u002Ftrim.webp",[10,131,132],{},"The grey box is the 0.4.0 crop, stretched out to reach the specks. On one of the game's sprites, a row of tyres, it came out at more than twice the area it should have. 0.5.0 ignores alpha of 16 or less when trimming, which gives the red box, and matches the game script's crops on every sprite I checked.",[29,134,136],{"id":135},"hard-edges-for-pixel-art","Hard edges for pixel art",[10,138,139],{},"Looking at that art more closely showed something else: the backend never returns a fully solid pixel. The body of a sprite comes back at an alpha of 250 to 254, so it's very slightly see-through, and the edges fade out softly. That doesn't suit pixel art, and the game script made every pixel either fully solid or fully transparent.",[10,141,142,145,146,149],{},[24,143,144],{},"--hard-alpha"," does the same. Every pixel with an alpha above 16 becomes solid, and the rest becomes transparent. It runs again after resizing, because resampling softens edges, and palette reduction (",[24,147,148],{},"-c",") keeps the result hard. For art with soft edges, like a glow or a painted style, leave it off.",[29,151,153],{"id":152},"sizes","Sizes",[10,155,156,159,160,163,164,167,168,171,172,175,176,179,180,183,184,187,188,191,192,194,195,198,199,202],{},[24,157,158],{},"--resize"," takes ",[24,161,162],{},"400x",", ",[24,165,166],{},"x300"," or ",[24,169,170],{},"400x300",". With both sides given, ",[24,173,174],{},"--fit"," decides what happens when the aspect ratio differs: ",[24,177,178],{},"inside"," fits the image in the box, ",[24,181,182],{},"cover"," fills the box and crops the centre, ",[24,185,186],{},"contain"," pads with transparency, and ",[24,189,190],{},"fill"," stretches. ",[24,193,182],{}," also solves a problem from the first post: ",[24,196,197],{},"-s 1536x1024"," is only a hint, and it has come back as 1672x941. ",[24,200,201],{},"--resize 1536x1024 --fit cover"," gives exactly 1536x1024.",[10,204,205,208,209,211],{},[24,206,207],{},"--no-enlarge"," makes ",[24,210,158],{}," a maximum: an image that's already smaller keeps its size instead of being scaled up.",[10,213,214,215,218],{},"All of this works both when generating and in ",[24,216,217],{},"codex-img convert",", which uses no login and no quota:",[34,220,222],{"className":36,"code":221,"language":38,"meta":39,"style":39},"codex-img convert raw\u002Fcar.png --hard-alpha --trim --resize 400x300 --no-enlarge -c 160 -o assets\u002F\n",[24,223,224],{"__ignoreMap":39},[43,225,226],{"class":45,"line":46},[43,227,221],{},[29,229,231],{"id":230},"replacing-the-script","Replacing the script",[10,233,234,235,238],{},"As a check, I rebuilt all 35 of the game's assets from the raw images with codex-img instead of the Python script: sprites with the command above, the full-screen cockpit overlay with ",[24,236,237],{},"--fit fill",", and the sky backgrounds as WebP. All 35 came out at exactly the script's dimensions. The files are about 11% bigger in total, because codex-img uses a different colour quantizer. The one step that stays in Python is specific to the game: finding the screen inside the cockpit image, so the answer buttons can go there.",[29,240,242],{"id":241},"try-it","Try it",[10,244,245,246,250,251,254,255,257],{},"Download the binary for macOS or Linux from the ",[13,247,249],{"href":15,"rel":248},[17],"release page",", and log in once with ",[24,252,253],{},"codex login"," using your ChatGPT account. The Agent Skill in the repository now tells Claude Code and Codex when to use these options, including to compare a sprite with the project's existing art before choosing ",[24,256,144],{},".",[259,260,261],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":39,"searchDepth":52,"depth":52,"links":263},[264,265,266,267,268,269,270],{"id":31,"depth":52,"text":32},{"id":97,"depth":52,"text":98},{"id":116,"depth":52,"text":117},{"id":135,"depth":52,"text":136},{"id":152,"depth":52,"text":153},{"id":230,"depth":52,"text":231},{"id":241,"depth":52,"text":242},"release","2026-09-29","Trim, resize and hard-edged alpha in the same command that generates the image, a fix for the dark colour hidden under transparent pixels, and a trim bug that only showed up on real art.",false,"md",{},true,"\u002Fblog\u002Fcodex-img-0-5-0","codex-img",{"title":5,"description":281},"codex-img can now trim, resize and harden the alpha of a generated sprite in one command, and it removes the dark halo hidden under transparent pixels.","blog\u002Fcodex-img-0-5-0",[284,285,286,287],"ai","codex","claude","open source","EfBNud5z91ZmlvQqAyrV1UpexP1XRDkKCbTV2ABYzP4",{"path":290,"title":279,"description":291,"image":292,"detailImage":293,"imageFit":293,"coverLabel":293},"\u002Fprojects\u002Fcodex-img","Generate and edit images from the command line with your ChatGPT\u002FCodex subscription. No API key, and no agent in between.","\u002Fimg\u002Fproducts\u002Fcodex-img.webp",null,[295,296,300,304,308,312],{"path":278,"title":5,"date":272},{"path":297,"title":298,"date":299},"\u002Fblog\u002Fcodex-img","codex-img generates images from the terminal with your ChatGPT subscription","2026-09-28",{"path":301,"title":302,"date":303},"\u002Fblog\u002Fusage-window-starter","Usage Window Starter activates your next Claude and Codex session the minute the old one resets","2026-09-24",{"path":305,"title":306,"date":307},"\u002Fblog\u002Fdocument-iteration-skill-6-0","document-iteration-skill 6.0 rewrites the skill in positive terms","2026-09-23",{"path":309,"title":310,"date":311},"\u002Fblog\u002Fopen-claude-agent-sdk-0-50-0","open-claude-agent-sdk 0.50.0 fixes broken clean installs","2026-09-22",{"path":313,"title":314,"date":315},"\u002Fblog\u002Fcamera-video-converter-is-on-play-store","Camera Video Converter is on the Play Store","2026-09-02",1790712559833]