<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: IC ice</title>
    <description>The latest articles on DEV Community by IC ice (@ic_ice_b3cc3125720dfdabac).</description>
    <link>https://dev.to/ic_ice_b3cc3125720dfdabac</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4028886%2F7a33ac6f-1316-4ef2-9937-29b886f2517e.jpg</url>
      <title>DEV Community: IC ice</title>
      <link>https://dev.to/ic_ice_b3cc3125720dfdabac</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ic_ice_b3cc3125720dfdabac"/>
    <language>en</language>
    <item>
      <title>I Kept Getting Bad AI Images Until I Found Wisk AI</title>
      <dc:creator>IC ice</dc:creator>
      <pubDate>Mon, 27 Jul 2026 15:24:30 +0000</pubDate>
      <link>https://dev.to/ic_ice_b3cc3125720dfdabac/i-kept-getting-bad-ai-images-until-i-found-wisk-ai-1723</link>
      <guid>https://dev.to/ic_ice_b3cc3125720dfdabac/i-kept-getting-bad-ai-images-until-i-found-wisk-ai-1723</guid>
      <description>&lt;p&gt;So here's the thing about AI image generation in 2026: everyone has access to powerful models, but almost nobody knows how to &lt;em&gt;talk&lt;/em&gt; to them. You type "a cool robot," you get something generic, and you have no idea why the image in that Twitter thread looks 10x better than yours.&lt;/p&gt;

&lt;p&gt;The gap isn't the model. It's the prompt.&lt;/p&gt;

&lt;p&gt;That's the exact problem I was trying to solve when I started digging into &lt;a href="https://wiskai.net" rel="noopener noreferrer"&gt;Wisk AI&lt;/a&gt; — an AI image prompt gallery + generator combo that basically treats prompting as a skill you can study, not guess at.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Idea
&lt;/h2&gt;

&lt;p&gt;Instead of separating "learn how to prompt" from "generate an image," Wisk AI puts them in the same interface. You browse a searchable gallery of real prompt examples (built for models like Nano Banana and GPT Image), see exactly how lighting, composition, and style choices affect the output, and then generate your own image right there without switching tabs or tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmv8ot159d43bmy9b5bl1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmv8ot159d43bmy9b5bl1.png" alt="Wisk AI homepage" width="799" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Actually Get
&lt;/h2&gt;

&lt;p&gt;A few things stood out to me while poking around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A real prompt gallery, not just a feed.&lt;/strong&gt; You can filter by model, category, popularity, or recency, and actually study why a prompt works instead of copy-pasting blindly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text prompts &lt;em&gt;and&lt;/em&gt; reference images.&lt;/strong&gt; You can write a description from scratch, or upload up to five reference images if you're trying to guide an edit/transformation instead of starting cold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A choice of current models.&lt;/strong&gt; Nano Banana 2, Nano Banana Pro, and GPT Image 2 are all available, so you can trade off speed vs. quality depending on what you're doing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real output control.&lt;/strong&gt; Seven aspect ratios, resolution up to 4K depending on plan, plus extra quality settings for GPT Image 2.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session history + downloads.&lt;/strong&gt; Nothing disappears after you generate it — you can look back at everything from your session and pull the files you want.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commercial rights on paid plans.&lt;/strong&gt; Worth flagging if you're building this into client or marketing work — free-tier images are personal use only.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Actual Workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Search the gallery for a style/subject/mood close to your idea (or skip it and write your own prompt).&lt;/li&gt;
&lt;li&gt;Pick a model — Nano Banana 2, Nano Banana Pro, or GPT Image 2 — based on the speed/quality you need.&lt;/li&gt;
&lt;li&gt;Set aspect ratio and resolution, and optionally drop in up to five reference images.&lt;/li&gt;
&lt;li&gt;Generate, compare against your session history, download what you like.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp5orvo8pachjv80t42hr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp5orvo8pachjv80t42hr.png" alt="Wisk AI image generation page" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Who This Is Actually Useful For
&lt;/h2&gt;

&lt;p&gt;If you're any of these, it's worth ten minutes of your time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digital artists/illustrators looking for new prompt angles&lt;/li&gt;
&lt;li&gt;Designers who need fast visual concepts without a full creative pipeline&lt;/li&gt;
&lt;li&gt;Marketers/brand teams producing campaign or social content&lt;/li&gt;
&lt;li&gt;Product photographers who want reference-guided transformations&lt;/li&gt;
&lt;li&gt;Anyone new to AI image generation who learns better from working examples than blank-page trial and error&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pricing Breakdown
&lt;/h2&gt;

&lt;p&gt;It's a freemium setup with four tiers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Credits/mo&lt;/th&gt;
&lt;th&gt;Images/mo&lt;/th&gt;
&lt;th&gt;Max Resolution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;10 (one-time)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Starter&lt;/td&gt;
&lt;td&gt;$9.99/mo ($99.90/yr)&lt;/td&gt;
&lt;td&gt;900&lt;/td&gt;
&lt;td&gt;225&lt;/td&gt;
&lt;td&gt;2K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$39.99/mo ($399.90/yr)&lt;/td&gt;
&lt;td&gt;3,000&lt;/td&gt;
&lt;td&gt;750&lt;/td&gt;
&lt;td&gt;4K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ultimate&lt;/td&gt;
&lt;td&gt;$49.99/mo ($499.90/yr)&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;1,250&lt;/td&gt;
&lt;td&gt;4K&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Higher tiers also add concurrent generations (up to 8 on Ultimate), priority queueing, and commercial usage rights.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxt7h208g36qo3njlr765.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxt7h208g36qo3njlr765.png" alt="Wisk AI pricing page" width="799" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Takeaway
&lt;/h2&gt;

&lt;p&gt;Most AI image tools assume you already know what a good prompt looks like. Wisk AI is one of the few that treats prompt literacy as part of the product — you learn by browsing real, working examples, then immediately apply that in the same generator. The free tier is enough to test the workflow before you commit to anything, and the paid tiers scale reasonably well if you end up needing 4K output or commercial rights.&lt;/p&gt;

&lt;p&gt;If you've ever stared at a blank prompt box unsure where to start, it's worth checking out.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built a Browser-Only Pixel Art Converter — Here's How It Works Under the Hood</title>
      <dc:creator>IC ice</dc:creator>
      <pubDate>Tue, 14 Jul 2026 14:25:32 +0000</pubDate>
      <link>https://dev.to/ic_ice_b3cc3125720dfdabac/turn-any-photo-into-pixel-art-in-seconds-right-in-your-browser-2d5d</link>
      <guid>https://dev.to/ic_ice_b3cc3125720dfdabac/turn-any-photo-into-pixel-art-in-seconds-right-in-your-browser-2d5d</guid>
      <description>&lt;p&gt;A while back, I got tired of explaining to people how to convert images to pixel art using Photoshop, Aseprite, or some obscure command-line tool. The friction was real — install this, export that, tweak the palette manually.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://pixelcrafts.art/" rel="noopener noreferrer"&gt;PixelCrafts&lt;/a&gt; — a fully client-side pixel art converter that runs entirely in the browser using the Canvas API. No backend, no file uploads, no account required.&lt;/p&gt;

&lt;p&gt;Here's how it works and why I made certain technical decisions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core: Canvas API + Pixel Downsampling
&lt;/h2&gt;

&lt;p&gt;The fundamental operation is simple: take an image, downsample it to a low resolution, then scale it back up with &lt;code&gt;imageSmoothingEnabled = false&lt;/code&gt; to get that hard-edged pixel look.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;offscreen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;offscreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;pixelSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;offscreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;pixelSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;offscreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageSmoothingEnabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;offscreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;offscreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Scale back up — pixels stay sharp&lt;/span&gt;
&lt;span class="nx"&gt;outputCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageSmoothingEnabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;outputCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offscreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;outputCanvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;outputCanvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;pixelSize&lt;/code&gt; slider controls the block size — higher values = chunkier pixels, lower = finer detail. Everything is computed in-memory, frame by frame as you drag the slider.&lt;/p&gt;




&lt;h2&gt;
  
  
  Color Palette Quantization
&lt;/h2&gt;

&lt;p&gt;This was the trickiest part. Retro hardware had strict color limits (NES: 54 colors, Game Boy: 4 shades of green), so I needed palette quantization — mapping every pixel to the nearest color in a fixed set.&lt;/p&gt;

&lt;p&gt;The approach I use is nearest-neighbor in RGB space:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nearestColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;palette&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;minDist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nearest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;palette&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pb&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;palette&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;pb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;minDist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;minDist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;nearest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pb&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nearest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For best results with photos, I also implemented an adaptive palette generator that clusters the image's dominant colors using a median-cut algorithm — so if you don't want to pick a retro preset, you can auto-extract a palette directly from the image.&lt;/p&gt;

&lt;p&gt;You can also import palettes from &lt;a href="https://lospec.com/" rel="noopener noreferrer"&gt;Lospec&lt;/a&gt; or PixilArt by slug or URL — the palette data is fetched client-side and parsed into HEX arrays.&lt;/p&gt;




&lt;h2&gt;
  
  
  Style Presets
&lt;/h2&gt;

&lt;p&gt;PixelCrafts ships with 10 retro presets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Preset&lt;/th&gt;
&lt;th&gt;Palette&lt;/th&gt;
&lt;th&gt;Vibe&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NES&lt;/td&gt;
&lt;td&gt;54-color hardware palette&lt;/td&gt;
&lt;td&gt;Classic platformer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Game Boy&lt;/td&gt;
&lt;td&gt;4-tone greenscale&lt;/td&gt;
&lt;td&gt;Handheld nostalgia&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PICO-8&lt;/td&gt;
&lt;td&gt;16-color&lt;/td&gt;
&lt;td&gt;Fantasy console&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vaporwave&lt;/td&gt;
&lt;td&gt;Purples, pinks, teals&lt;/td&gt;
&lt;td&gt;Aesthetic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Matrix&lt;/td&gt;
&lt;td&gt;Green-on-black&lt;/td&gt;
&lt;td&gt;Terminal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glitch Art&lt;/td&gt;
&lt;td&gt;Distorted + chromatic&lt;/td&gt;
&lt;td&gt;Experimental&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thermal&lt;/td&gt;
&lt;td&gt;Heat map tones&lt;/td&gt;
&lt;td&gt;Infrared look&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Old Movie&lt;/td&gt;
&lt;td&gt;Sepia + grain&lt;/td&gt;
&lt;td&gt;Silent film era&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anime&lt;/td&gt;
&lt;td&gt;High contrast + clean&lt;/td&gt;
&lt;td&gt;Cel-shaded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SNES&lt;/td&gt;
&lt;td&gt;Extended 256-color&lt;/td&gt;
&lt;td&gt;16-bit era&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each preset sets the palette, pixel size default, and enables relevant post-processing effects automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Post-Processing Effects (All on Canvas)
&lt;/h2&gt;

&lt;p&gt;Beyond pixelation, I layered several real-time visual effects — all implemented as canvas compositing passes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scanlines&lt;/strong&gt; — overlays alternating dark horizontal lines to mimic CRT rows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bloom&lt;/strong&gt; — a Gaussian blur blended additively over bright areas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CRT mask&lt;/strong&gt; — RGB sub-pixel dot pattern overlay&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chromatic aberration&lt;/strong&gt; — offsets the R and B channels by a few pixels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Noise / grain&lt;/strong&gt; — per-pixel random alpha overlay&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outline&lt;/strong&gt; — edge detection pass using a simple Sobel-like kernel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hue shift / temperature / tint&lt;/strong&gt; — pixel-level HSL adjustments via &lt;code&gt;getImageData&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All effects run after the quantization step, so the pixelated palette stays intact while the CRT effects sit on top.&lt;/p&gt;




&lt;h2&gt;
  
  
  Privacy by Default: Zero Uploads
&lt;/h2&gt;

&lt;p&gt;Everything runs locally. When you drag an image into PixelCrafts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The browser reads it via &lt;code&gt;FileReader&lt;/code&gt; or &lt;code&gt;createObjectURL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It's drawn onto an offscreen &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;All transformations happen in-memory&lt;/li&gt;
&lt;li&gt;You download the result via &lt;code&gt;canvas.toBlob()&lt;/code&gt; → &lt;code&gt;URL.createObjectURL()&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your image data never leaves your device. There's no server, no S3 bucket, no logs. This was a deliberate choice — many of the use cases (profile photos, game assets in development, client work) involve images people reasonably don't want uploaded to a stranger's server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Minecraft Mode
&lt;/h2&gt;

&lt;p&gt;One of the more fun features: a dedicated Minecraft Pixel Art mode. Instead of color palette quantization with arbitrary HEX values, it maps each pixel to the nearest Minecraft block by color (using a pre-built block → average color lookup table). The output includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A pixelated block-by-block preview&lt;/li&gt;
&lt;li&gt;A full material list with block counts&lt;/li&gt;
&lt;li&gt;Scale controls for the final structure size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Useful for Minecraft map art builders who want to turn a photo into a buildable plan.&lt;/p&gt;




&lt;h2&gt;
  
  
  Batch Conversion
&lt;/h2&gt;

&lt;p&gt;For indie devs converting sprite sheets or icon sets, there's also a batch mode — upload multiple images, apply the same style settings to all of them, and download individually or as a zip.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://pixelcrafts.art/" rel="noopener noreferrer"&gt;PixelCrafts&lt;/a&gt;&lt;/strong&gt; is free, no account needed, and works on mobile too.&lt;/p&gt;

&lt;p&gt;If you're building something similar or have thoughts on the palette quantization approach, drop a comment — I'm always looking to improve the algorithm, especially for edge cases like skin tones and gradients.&lt;/p&gt;

&lt;p&gt;Feedback and feature requests welcome: &lt;a href="mailto:support@pixelcrafts.art"&gt;support@pixelcrafts.art&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascriptwebdev</category>
      <category>canvas</category>
      <category>showdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
