130 comments

[ 3.6 ms ] story [ 162 ms ] thread
Very cool. I like the idea of using a text editor as an image editor.
I am really surprised that there haven't been more efforts in this direction. As a programmer who's recently been dabbling more in graphics, I hate having to fiddle with knobs and redo my work when I often know exactly what needs to be done and how to do it. If I need to draw an oval 10 times, I shouldn't have to copy and paste it, forcing me to redo the entire thing if I decide to make a change; I should be able to define the oval in script and use a loop to position it exactly how I want!

I wish there was an editor with an interface as great as (say) Pixelmator's, but with an optional script window that let you write and edit the code for your vector graphics if you need to. Something PostScript powered, maybe? (PaintCode does something like this, but it's more of a one-way, vector-to-code mapping. Bloom promises to do a lot of this, but I haven't used it in a while.[1])

[1]: http://thebloomapp.com/features/

> If I need to draw an oval 10 times, I shouldn't have to copy and paste it, forcing me to redo the entire thing if I decide to make a change

Indeed you shouldn't! That's why all serious image manipulation programs have this capability built in.

Most of them also let you write your own plugins for those cases where you need more than what the interface provides.

I think going to all-code drawing is more limiting than freeing. It seems more like a case of having a hammer and seeing that everything can be made to look like a nail.

Well, I'm not advocating all-code drawing! What I'm suggesting is a WYSIWYG editor like any other, but with a 1-to-1 script mapping for all the commands under the hood. If you want to generate an oval in code, go for it; but you can also create one using the oval tool (and edit it later in script if you change your mind).

As for plugins, that's not really integrated into the workflow in the way I'm envisioning. I shouldn't have to write heavy code just to experiment with a quick artistic idea! Think web development. It should be as simple as editing a JS file and refreshing the page.

You can use JavaScript in Photoshop.
Shameless plug - Monodraw [1] is perfectly suited to create the ASCII diagrams for this. I'm planning to add special support for ASCII Image if there's enough demand - so definitely let me know.

[1] http://monodraw.helftone.com

Wow. That looks like a dream come true. (if only it worked on my computer)

I guess a Windows or Linux version is never going to happen? I'd love to be able to run this.

Unfortunately, it's very unlikely. I'm a Mac developer and that's why Monodraw is written for OS X (in Obj-C).

I'm a supporter of all platforms but I do not have any cross-platform desktop GUI skills.

Wow, monodraw is a really polished app. That's a fascinating business model, too - your own idea, or inspired by another? Are you planning on giving users notice when the beta period is about to end?

I'm not 100% sure I'll really get regular use out of it, but I'm tempted to buy a copy anyway, mainly because I think you deserve reward for the effort that's obviously gone into it.

If I could wish for anything it would be this: is it even remotely possible for shapes from a plain text file to be interpreted as monodraw objects, rather than just one big text field?

> Wow, monodraw is a really polished app. That's a fascinating business model, too - your own idea, or inspired by another? Are you planning on giving users notice when the beta period is about to end?

Thank you for your kind words :) I think the business model has been inspired from the indie scene over the years. Simply put, I do not want to charge customers before the product is of quality that I deem adequate. That's why the beta is freely available without any restrictions. If anyone feels generous enough to support us before v1 ships, they get 40% off in return.

Yes, I plan to provide ample warning over email, Twitter + our blog.

> I'm not 100% sure I'll really get regular use out of it, but I'm tempted to buy a copy anyway, mainly because I think you deserve reward for the effort that's obviously gone into it.

I greatly appreciate the support. Even if you don't purchase it, knowing that you like the app is enough to motivate me to further work on it. From a financial perspective, every purchase counts - as an indie, my livelihood depends on the apps I make, I don't have any other income.

> If I could wish for anything it would be this: is it even remotely possible for shapes from a plain text file to be interpreted as monodraw objects, rather than just one big text field?

That has been requested a few times and it's something that I'm considering. It's not very high on my list but if I receive enough requests for it, I'll bump up it. I don't have a roadmap that is set in stone and I'm pretty flexible when it comes to the development of Monodraw - I'm willing to listen to the users.

I am slightly confused:

> Once the beta period ends, your copy of Monodraw would expire and you would not longer be able to use it.

Does this apply when you purchase the beta?

No, if you purchase the beta (and register it with the serial key), it will never expire.
a) This is a remarkably neat idea. b) It probably shouldn't have to exist.

... which just about sums up the Objective-C experience

I'm going to join you here in the grey. Objective-C is a disaster of a language on many levels. Portable C++ is the smarter and better choice(and those few cases where it isn't is solely because of intentional and unethical design decisions by apple to lock you into their platform).
I know you & the parent have both been down-voted, but it would be great if you could explain some rationale behind why Objective C is such a disaster in your opinion(s)?

When I first started learning it, I absolutely _hated_ it. With a burning passion.

It is probably now my current favourite and most productive language.

I seem to very rarely write buggy/poor/badly structured code and almost never hit compiler errors/hard crashes unless they are something relatively obscure. It's quite common for me to write 1k+ lines of code, hit build and have exactly what I wanted compile & work pretty much first time.

Not OP, and I agree that Objective-C is great. However, it is potentially troubling, from a performance standpoint, that practically everything is allocated on the heap. There's no support in the language for stack-allocated objects, for example. Now that I've used Swift in production, I also really miss generics. Casting to and from containers gets really annoying and unsafe!
"that practically everything is allocated on the heap"

That's kind of the point though. If you want something on the stack, you write plain old C structs or work with primitives. There's plenty of this happening throughout the cocoa frameworks. On the other hand, if you find yourself writing C structures to the heap in objc, you're probably wasting your effort.

I think that's just the natural consequence of knowing a language. I can do the same with a JS and a linter. I don't think that necessarily speaks to the bug-free nature of JS!
Whether or not that is the case, it is completely irrelevant to the topic of the article, unless C++ would help with the "shouldn't have to exist" part. I imagine that a language like Racket which can embed (vector) images directly into source files might help, but C++ has nothing like that, nor do most languages. You could argue that making icon sets for iOS is harder than it has to be, but that would be an IDE and/or tooling problem, not an Objective-C issue specifically.
What on earth are you talking about ?

You do realise that Objective-C was used because iOS is effectively OSX. And OSX is effectively NextStep. Apple is a big company sure but rewriting your entire SDK is never a quick or simple endeavour. So of course when the iPhone came out Objective-C was going to be used.

And for those who aren't keeping track of the timeline, NeXTSTEP predates C++ templates. Large portions of this could have been done with 1989's Objective-C and the graphics capabilities NeXTSTEP had at the time, though this tool does benefit significantly from some newer syntax.
If Objective-C was such the disaster of a language you're making it out to be, it wouldn't be part of the billion dollar industry it powers.

Productivity wise (i.e. making something and shipping it), it's a fantastic language.

I fail to see what Objective-C has to do with any of this.
It'd be interesting to combine this with monodraw:

http://monodraw.helftone.com/

Guess we can expect a full NSImage export feature in the full version. I just started using Monodraw and this was the first thing that came to mind as well.
This is a work of art in of its self, never mind the icons made.

It is also inspiring for ascii to graphics representation utilities as well. I wonder if this could be extended to make shape holder content, where in the art you can specify the stretch locations and protected zones. (kinda like how you can do a boxy like configuration on images for dynamic content inside via CSS3)

I imagine it could work like Android 9-patch PNG drawables, which have an extra ring of pixels around the perimeter that mark content zones and stretching zones.
Actually, something very like this has been done for a long time (the XPM): https://en.wikipedia.org/wiki/X_PixMap

All the best,

XPM is only for resolution-specific rasters. His technique allows for bezier paths, arbitrary fills, etc and is resolution-independent. It's pretty clever, IMO.
I didn't say what the author did was bad, uncool or not clever. But it certainly isn't a revolutionary thing that's never been done before.

Additionally, XPM sucks (I'm aware), and I've been wishing for a significant update to it for a long while :P

Did you read the article at all? It's hardly even comparable.
I'm confused; how is this not comparable? It's creating a pixmap directly from strings. I'm not saying this project is bad or uncool, I'm just saying this isn't a completely new idea.
The ASCIImage rendering code described in the post we're discussing is actually resolution independent vector graphics. You can draw neatly pixel aligned stuff with it, as is shown in the screenshots, but it's vector graphics.
I'm not saying the author didn't make something far more advanced or cool; but the beginning of the article makes it seem like ey thinks ey is the first to ever come up with such an idea, which is false. I was never trying to say that the project is a knock-off.
Exactly. The core concept here is defining images for icons in the code itself, rather than loading them from external resources. XPM was one early way of doing that, allowing you to define bitmapped images in a static array of characters representing the pixel colours, and was a very neat hack. Now this extends and improves the idea, allowing you to define images for icons in your code, using an array of characters to represent the lines in an image, and define a vector graphic. It's definitely in the same conceptual space, although there doesn't seem to have been any direct inspiration from the earlier format. Both are very cool ideas...
Fair enough. I certainly did not mean to pretend anything like this.
I'll never understand all the down-votes; this wasn't a criticism of the project, it was just mentioning that the beginning of the article suggests nothing like it had ever been done before.
(comment deleted)
Hi, all. I am the blog post author, blown away by the attention this 1-day hack is getting! I am the author of Findings, a lab notebook app for scientists. Check it out and show it to others: http://findingsapp.com

I also created this page: http://asciimage.org, with my friend @mz2. There is a simple editor as well called ASCIImage Super Studio.

And check out Monodraw, I love it!! http://monodraw.helftone.com

(see comment here: https://news.ycombinator.com/item?id=9240942)

Really cool concept. Well done.

I didn't quite understand how the single points worked. It seemed to me that your definition for, say, 3 single points was the same as a triangle. How does it know which is which? Or do the curves have to be closed?

When you skip a character, you move on to next shape.

So, 1-2-3 5-6-7 = 2 triangles

But 1 3 5 = 3 points

I think I was thrown off by the example which used 1,1,1,1 for the sphere and 2, 3 to represent isolated points. But they're consecutive. Unless I'm missing something?
(comment deleted)
(comment deleted)
This looks vaguely like xpm, but monochrome and vectorized. xpm is an image format that is also valid C code, so you can #include "image.xpm" in your C source code.

https://en.wikipedia.org/wiki/X_PixMap#Comparison_with_other...

This isn't monochrome. Stroke and fill colors can be specified per-shape, just not in the diagram itself.
XPM isn't monochrome either, though. I always thought XPM was an elegant hack, since I could just #include my icons into the C source for my Xt or Motif applications. I don't miss the rest of Xt and Motif, particularly the pseudo-object-oriented C style code, or the twenty kilograms of O'Reilly books containing the documentation!
So, you're a straight Xlib via man pages person?
(comment deleted)
I use the same trick to include icons in my wxWidgets/C++ applications.
What if you allowed composing multiple "layers" into a single output to make different parts of an otherwise busy diagrams more clear? For example, I found the bug one particularly obfuscated:

    · · · · 3 · · · · · · · · · · · · · 
    · · · · · · · · · 7 · · · · · · · · 
    · · · · · · · · · · · · · · · · · · 
    · · · 1 3 · · 1 · · · · · · · · · · 
    5 · · 5 · · · · · · · · · · · B · · 
    · · · · · 2 · · · 7 · · · · 2 · · · 
    · · · · · · · · · · · · · · · · · · 
    · · · 1 · · · 1 · · · · · · · · · · 
    · · · · · · · · · · · B · 9 · · · · 
    · 8 · · · 8 · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · · 
    · · · · · · · · C · · · · · · · · · 
    · · · · · · · · · · · · · · · · · 9 
    · · · · · · · · A · · · · · · · · · 
    · · · · · 2 · · · · · · · · 2 · · · 
    · · · · C · · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · · 
    · · · · · · · · · · · · A · · · · · 

But if you split it into two diagrams it becomes much more clear what's going on:

    · · · · · · · · · · · · · · · · · ·     · · · · 3 · · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · · 7 · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · · · · · · · · · · · 
    · · · 1 · · · 1 · · · · · · · · · ·     · · · · 3 · · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     5 · · 5 · · · · · · · · · · · B · · 
    · · · · · 2 · · · · · · · · 2 · · ·     · · · · · · · · · 7 · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · · · · · · · · · · · 
    · · · 1 · · · 1 · · · · · · · · · ·     · · · · · · · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · · · · B · 9 · · · · 
    · · · · · · · · · · · · · · · · · ·     · 8 · · · 8 · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · C · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · · · · · · · · · · 9 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · A · · · · · · · · · 
    · · · · · 2 · · · · · · · · 2 · · ·     · · · · · · · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · C · · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · · · · · · · · · · · 
    · · · · · · · · · · · · · · · · · ·     · · · · · · · · · · · · A · · · · ·  
Especially if you name them. Here, "body" and "legs". Edit: add spaces for clarity. Edit2: use cdot.
TBH, the bug is an example of where this hack should not be used :D
I agree, the bug is mostly a worst-case complexity scenario, but it seems to help with the other slightly more complex examples like the lock as well, by separating the keyhole from the rest of the shape:

    · · · · · · · · · · · · · ·    · · · · · · · · · · · · · ·
    · · · 1 · · · · · · 1 · · ·    · · · · · · · · · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · · · · · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · · · · · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · · · · · · · · · ·
    · 3 · 1 · · · · · · 1 · 4 ·    · · · · · · · · · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · · · · · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · A · · A · · · · ·
    · · · 1 · · · · · · 1 · · ·    · · · · · · · · · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · · C D · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · A · · A · · · · ·
    · · · · · · · · · · · · · ·    · · · · · · · · · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · · B E · · · · · ·
    · · · · · · · · · · · · · ·    · · · · · · · · · · · · · ·
    · 6 · · · · · · · · · · 5 ·    · · · · · · · · · · · · · ·
You are totally right, and I actually also considered doing just that initially in my code.
Is it really slow to draw these waiting for compile each time?
Judging by the first example, I'd guess it's probably creating an NSBezierPath and then letting OSX actually do the rasterisation later.
This reminds me of the sprites I made in QuickBasic with 2-digit color codes. Very cool!
Yeah I was going to say the same thing. I did that well over 20 years ago when I was a kid.
Yeah, the chevron in the article would just be:

    DRAW "BM+3,+1 R1 F4 D1 G4 L1 U1 E3 U1 H3 U1"
You could change the scale with "Sn" so you could draw any size, and there were commands to fill shapes etc.

There was a similar language for music as well, they were both nice little DSLs.

It would be awesome to extend this into a library based on FontAwesome; create an abstraction layer which would allow easy reference like CSS.
It sure would... fontAwesome ios libraries (mostly using NSImage) are all awful and broken
I don't wish to sound rude, because this is great work by the author, but isn't this reinventing the wheel? Why not just use SVG? It might be somewhat less efficient for the very simplest images, but doing raster layers in code and including things like bezier handling seems perversely complex.
Because this lets you 'code' the icon visually , rather than describing the steps to draw.

It's a brilliantly simple but effective ideas. Very tempted to use it in my next project.

But why not just draw it instead of, well, typing it in ASCII? Once you start doing layers and blending and so on, you're just asking for misalignment errors, surprises when your bezier paths turn out to generate little unwanted loops and so on...

It seemed like the author's original problem was having to do so over and over to deal with different pixel densities, but this is exactly the sort of problem SVG exists to solve. I do admire the technical skill, I just don't get the attraction of compiling ascii art into a vector image for anything practical, for much the same reason that I wouldn't want to use Photoshop or Illustrator to write code.

I only use it for very simple icons (square, couple of lines, etc)
That makes sense. I apologize for coming off as so negative, I really do think it's very clever.
> But why not just draw it instead of, well, typing it in ASCII?

Maybe because it is (or at least can be, the more advanced usages become less so) tolerably self-describing in that you can readily see what it is producing, in a way that SVG isn't, while still being source-control and diffing-tool friendly text?

For small things like its intended uses, it fits well within coding tools and workflows, and avoids separately documenting and coding the art.

Um, graphic files are also self-describing.

This kind of reeks of "If your only tool is a text editor, every problem looks like text".

Way off topic but this is one reason I was excited about Atom the text editor. Given its running inside a browser you should, theoretically, be able to show svg inline, even allow visual editing inline.
Emacs has supported inline SVGs in org-mode since 2007 or so.
Graphics files are not both self-describing and inline.

For some applications, having something be both can be helpful.

It's more "if your primary tool is a text editor, there is a complexity cost to context shifting, and for some simple tasks that cost isn't justified if you have a suitable method of representing what you want in text."

Just as with programming, polyglot programming has value, but switching languages within a project had a complexity cost that isn't always justified even when for dinner task taken alone a different language is marginally superior.

>But why not just draw it instead of, well, typing it in ASCII?

Because programmers typically prefer typing in ASCII to drawing :-)

I agree with you, I find this program fun and suitable for one man shops. Not practical for teams with graphic artists. Imagine if coder had to switch icon resources by hand from ASCII files?

There has to be something wrong with SVG when people even thinks drawing icons in this day and age in ASCII is a must do.

I think it's more to do with lack of knowledge than any huge problems with SVG. At least I found it very easy to draw stuff in Inkscape, at least for simple drawings like icons.
I know SVG very well, even have used it a few times for automatic generation of various graphics for bioinformatic projects. I use a lot of different graphic editors, and I am very familiar with them, e.g. Illustrator, Sketch, Acorn, Photoshop, Omnigraffle. I am also very familiar with e.g. Bezier paths manipulations, linear transforms, linear algebra, etc. I love maths.

Pixel alignment, asset management and being a one-man shop allowed more excentricities is what justifies this, for small icons with simple features (a few straight lines or rects).

This is really impressive!

For the actual drawing, I'm wondering if the cairo library and drawing model would help. It effectively gives you the move-to line-to curve-to drawing, with some additional capabilities. A simple script around cairo seems like it would cover many more cases, and then this ASCIImage mechanism will help generate those scripts.

What extra capabilities do you think cairo would provide that could be exposed through the ASCII-art mechanism without overly complicating it? This thing is already choosing to not expose the full functionality of the NSBezierPath drawing APIs.
I'm not suggesting extending the ASCII art mechanism. I'm just suggesting that compared to the API shown in the first example, cairo makes simple line-art quite trivial to write as code.

Specific features that would make sense to have available rather than drawing art in an image editor:

Line width, to draw the chevron without having to draw two adjacent lines.

Dotted/dashed lines.

What a powerful way to represent graphics in code. I am definitely using this. Thank you!
It would be nice to have an html5 version that draws into a Canvas.
Be my guest :-)

I added the js port on asciimage.org. There is a Go version as well I will link to.

Nice. I was half considering doing it myself, but it looks like it's already done :)

I'm considering using this to redesign the UI on one of my products. Hiring a designer is a huge pain, but this is a viable alternative.

This is how we did DOS VGA fonts ~1990. Draw the pixels right in the code (everything was monospace) and write that array directly to video memory. Mode 13 (320x200x256) video memory was sequential, easy to animate. Also you could do palette scrolling. Consequently, Mode 13 was the best video mode for games http://en.wikipedia.org/wiki/Mode_13h
In the 80s I made most of my games by using the Amstrad's font support to draw sprites in a similar fashion. :)
I wonder what's better from the point of final user (app size, app starting speed, app performance, memory usage): png or this drawing code? I suspect that PNG should work better. And programmer can easily generate multiple PNG from single hand-written SVG.
Yes, PNG is probably using less memory. For a few small icons, though, it's negligible either way.
If speed / memory is of essence, it's simple enough to pre-render this .asciimage kind of data with the code @cparnot has made available at https://github.com/cparnot/ASCIImage. I whipped up a quick commandline tool for the purpose as part of https://github.com/mz2/ASCIImage-Super-Studio:

https://twitter.com/mz2/status/579283430858465280

It could of course be rendered to a PDF or TIFF or other Cocoa supported image file format, consider that just a 5-minute hack to demonstrate the idea.

Not speaking about processing costs, this could be nice format for storing the data. Consider the example from page:

    1 2 3 4 5 6 7
  a · 1 2 · · · · 
  b · A # # · · ·
  c · · # # # · ·
  e · · · 9 # 3 ·
  f · · · 8 # 4 ·
  h · · # # # · ·
  i · 7 # # · · ·
  j · 6 5 · · · ·
It is textually 58 characters of data:

  7 ·12·····A···············9·3····8·4·········7······65····
(Axis headers and whitespace ommited, two characters added to keep the row width information.)

It is almost the same size of the smallest possible SVG polygon of similar shape consisting of 59 characters:

  data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"><polygon points="0,0 2,0 5,3 5,5 2,8 0,8 0,6 2,5 2,3 0,2"/></svg>
Using even the simplest coordinates notation it could look like 24 characters:

  a2a3e6f4j5j6i7f6e9b2f cf
(Three characters added to keep "Close and fill" information.)

Smallest 7×8 px PNG with the same image is 96 bytes large:

  data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAIAQMAAAAPyndFAAAABlBMVEX///8AAABVwtN+AAAAFUlEQVQI12NIYChgsGCQAUILICsBABJQAkm4hriIAAAAAElFTkSuQmCC
Nice to see the actual comparison of the binary size (and there is the 2x and 3x png). On the other hand, to be fair, the memory footprint will be more with the ASCII version (text + final NSImage loaded as bitmap in memory) compared to png (only the bitmap in memory, directly loaded from disk). The size of the bitmap is big anyway: there is no compression.
> Because of “retina”, you also have to create separate files for 1x, 2x, and now 3x-scale

OT but why do you need three different and not just go with the 3x which you scale down?

Designers have more possibilities with 3x and 2x than with 1x as you can draw small details. If you scale them to 1x, the icon will look blurry, because the details doesn't scale well. If you want high level of polish, you typically make at least some touches to the scaled down icons.

Of course, in the context of the original ascii art icons, that level of polish doesn't matter.