<?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: Subhadeep Paul</title>
    <description>The latest articles on DEV Community by Subhadeep Paul (@devsensei404).</description>
    <link>https://dev.to/devsensei404</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%2F3842754%2F4d14d513-19d8-404c-97ff-210557eec309.png</url>
      <title>DEV Community: Subhadeep Paul</title>
      <link>https://dev.to/devsensei404</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devsensei404"/>
    <language>en</language>
    <item>
      <title>GlyphX: turning photos into ASCII art</title>
      <dc:creator>Subhadeep Paul</dc:creator>
      <pubDate>Fri, 16 Oct 2026 03:10:43 +0000</pubDate>
      <link>https://dev.to/devsensei404/glyphx-turning-photos-into-ascii-art-487i</link>
      <guid>https://dev.to/devsensei404/glyphx-turning-photos-into-ascii-art-487i</guid>
      <description>&lt;h1&gt;
  
  
  GlyphX: turning photos into ASCII art
&lt;/h1&gt;

&lt;p&gt;Brightness alone makes mushy ASCII art. That's the main thing to know about image-to-ASCII converters, and it's why I built GlyphX the way I did.&lt;/p&gt;

&lt;p&gt;A few months ago I watched a reel on customizing your GitHub profile. It pointed to a README generator that turned my profile picture into ASCII art. I pasted it in and moved on. But I kept wondering what it would take to build one myself. So I did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://glyph-x.vercel.app/" rel="noopener noreferrer"&gt;glyph-x.vercel.app&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Code:&lt;/strong&gt; &lt;a href="https://github.com/devsensei404/GlyphX" rel="noopener noreferrer"&gt;github.com/devsensei404/GlyphX&lt;/a&gt;&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%2F6mrj4jsf26p883qnxyhn.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%2F6mrj4jsf26p883qnxyhn.png" alt="Original photo next to its 120-column mono ASCII conversion" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Upload a photo, paste one, drag it in, or snap one with your camera. Pick a width from 20 to 300 columns, choose mono or color, and download the result as a PNG or JPEG. More columns means more detail. It's that simple.&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%2F4lw9zl40l1h2ab2onrsm.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%2F4lw9zl40l1h2ab2onrsm.png" alt="The same photo converted at 40, 120 and 300 columns, showing increasing detail" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Resize the image, measure the brightness of each cell, and map that to a character. GlyphX uses a 70-character ramp ordered by how much ink each glyph puts on screen. &lt;code&gt;$&lt;/code&gt; and &lt;code&gt;@&lt;/code&gt; sit at the dense end, a plain space at the other. On a dark page, bright pixels get the dense characters. Before any of that, the image gets an auto-contrast stretch. Flat, hazy photos turn to mush otherwise.&lt;/p&gt;

&lt;p&gt;Characters are roughly twice as tall as they are wide, so each cell has to cover a block twice as tall as it is wide. Skip that and everything comes out stretched.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edges are the hard part.&lt;/strong&gt; Brightness gets you something recognizable. Outlines still dissolve into whatever character happens to be nearby. So GlyphX runs a Sobel filter over the image, works out which way each edge runs, and swaps in &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt; or &lt;code&gt;\&lt;/code&gt; wherever an edge is strong enough. Finding &lt;em&gt;where&lt;/em&gt; an edge is takes one filter. Finding which &lt;em&gt;direction&lt;/em&gt; it points took me real reading. It's also what takes the output from "recognizable" to "actually looks good."&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%2Fxngb7pgvscqpe474zvnj.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%2Fxngb7pgvscqpe474zvnj.png" alt="Zoomed-in crop of the ASCII output showing diagonal and vertical characters tracing facial edges" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Color mode is simpler. Each cell keeps the average color of its block from the original photo. Characters come from brightness and edges, color comes straight from the source.&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%2F18rp9jbb6v6o4k3lbf95.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%2F18rp9jbb6v6o4k3lbf95.png" alt="Original photo next to its 300-column color ASCII conversion, with character color sampled from the source image" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Things I cared about
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy.&lt;/strong&gt; Flask normally spills larger uploads into temp files on disk. GlyphX keeps them in memory instead, and nothing about your image gets logged. When the request ends, the image is gone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limits.&lt;/strong&gt; 4 MB per image, a cap on total pixels, and two conversions at a time. Extra requests wait up to 10 seconds, then get a polite "server busy."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No copy-as-text button, on purpose.&lt;/strong&gt; 300 columns of ASCII pasted into a chat is a mess. You get a PNG or JPEG instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Nothing. It's live, it does what I wanted, and I'm not adding features. If you try it, I'd like to hear whether you liked the output. That's all I'm after.&lt;/p&gt;

&lt;p&gt;This is my first post like this, so go easy on me.&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>flask</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
