Ben Crowder

Blog

Some WIP experimentation with art.

Brief backstory: when I’m doing my minimalist religious art, I usually sketch an idea out first by hand or in Paper on my phone, then mock them up in Illustrator to iterate on the concept. Once it’s satisfactory, I move to execution, either painting the piece in Procreate or using some of the brushes in Illustrator to get a more organic look. And finally I texture the image in Photoshop.

A couple months ago I got interested in exploring alternatives to Illustrator and Photoshop for both execution and texturing processes. And me being me, I wanted to try doing it in code, just to see what it was like. (Some things are easier in code, though I don’t know how often that would actually be the case with these.)

Note: this is still very much a WIP, and who knows if I’ll end up using any of it or not. But here’s the current state of things.

SVG

After reading somewhere that SVG has turbulence and displacement filters, I realized I could potentially use those for the execution part of the process, to distress the edges enough to make things more interesting. (And hopefully to be less repetitious than the Illustrator brushes I use.)

I put together an initial test using a few different settings, and it turned out a bit better than I expected. A sample of the code:

<filter id="person1Filter">
    <feTurbulence type="turbulence" baseFrequency="0.5" numOctaves="2" result="turb1" />
    <feDisplacementMap in2="turb1" in="SourceGraphic" scale="3" xChannelSelector="R" yChannelSelector="G" result="result1" />
    <feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turb2" />
    <feDisplacementMap in2="turb2" in="result1" scale="3" xChannelSelector="R" yChannelSelector="G" />
</filter>

<style type="text/css">
    .person1 {
        fill: #a34130;
        filter: url(#person1Filter);
    }
</style>

<g id="person-1">
    <circle class="person1" cx="200" cy="250" r="30" />
    <polygon class="person1" points="225,270 205,500 350,500" />
</g>

And this is what it looks like:

svg-test.png

The background rectangle, the red figure, and the white figure all have different turbulence and displacement values. The red figure uses two sets of turbulence and displacement filters, which worked out fairly well, I think.

I used Inkscape render it out to a high-res PNG, since Illustrator wasn’t able to handle the filters. Eventually, if I keep going down this path, I’d hopefully be able to find a command-line tool that can do the rendering. (Maybe Inkscape has a headless option.)

Overall, this path seems promising. I don’t know that I’d use it all the time, but for certain things it may be handy. I still need to look into sane ways to round corners, and it seems that the other filters (dilation/erosion, convolution, etc.) may be helpful, too.

Grain

I’ve begun writing a Python script called Grain for texturing the final art image. The goal here is to see if I can streamline the process at all, and to see if this idea even works. Grain takes as input a text-based input file that looks like this:

:image test1-texture.jpg
:blend screen
:opacity 0.05
:x -100

:image textures#random
:blend soft-light
:opacity 0.1

:pattern roughdots
:blend soft-light
:opacity 0.2

:image textures#2019-05-21 17.28.14.jpg
:blend soft-light
:opacity 0.01

:image test1-base.png

Each block is a layer. Grain starts with the bottom layer (the executed base image) and goes up from there, adding each layer on top with the specified blending mode and opacity.

The :pattern roughdots command would generate procedural dots (not implemented yet), and the textures# bit in the :image command calls is a shortcut to my folder with texture photos.

So far, the results are disappointing. While the layering does currently work, it isn’t yet producing anything remotely publishable. I think there might be some discrepancies between blending modes in pyvips and in Photoshop. Hard to tell.

And, less importantly, it’s a little slow — partially from using high-res images, partially from Python. If the idea ends up working, I’ll most likely port this to Rust or Go, and probably also have scale things down for the exploration phase of texturing (with a final high-res export at the end).

I’ll keep tinkering with it from time to time and we’ll see how it goes.


Reply via email

I’m going to try batching links into groups of five from now on, since solitary links often feel a little too insubstantial for a post. Links often won’t be related.


Reply via email

Slash intro

Another entry in the patience-testing series talking about my personal productivity tools.

Slash is the engine that runs this blog. It’s just a Python app running Django, but calling it an engine is too satisfying for me to stop anytime soon. The name comes from the ubiquitous forward slash in URLs.

Overview

Slash has an internal frontend with some post management pages (see below) along with a small API which is used by Blackbullet (my current website engine, separate from the blog) to pull posts into my site template. The API also publishes the RSS and JSON feeds, which Blackbullet passes right through.

The dashboard lists current drafts and, lower on the page where you can’t see it in this screenshot, recently published posts:

slash-1.png

Disclaimer: there’s no guarantee that these particular post drafts will ever see the light of day. I often put ideas in and then decide later that they’re not worth blogging about.

Here’s the post edit page, which is very much a work in progress (last week I added the visual tag controls, since adding tags via the metadata textbox made it impossible to tell whether I’d used a tag before or not):

slash-2.png

It’s spartan but works for me.

Payload syntax

Other than the notebook specifier, the syntax is pretty much the same as Vinci’s. Posts are written in Markdown. Metadata is specified with the initial-colon syntax.

One thing I realize I forgot to mention in the Vinci post is that in both apps I have a shortcut syntax for including images that looks like this:

(( readers-edition.png | class=border | url=/book-of-mormon-readers-edition/ ))

I have a page for uploading images to a date-named folder — year and month — and this syntax relies on the image being in the matching folder for the post. A small bit of convention to make things simpler.

How I use Slash

On my laptop, I open Slash when needed. On my phone, I have it saved to my homescreen as a PWA.

Other than that, I use it the way you’d expect — I write blog posts (usually directly in Slash, but occasionally in Gate or Quill), I edit them, I publish them. Months later I finally notice the typos. It’s not too exciting.

The future

As of now, the plan is to replace both Blackbullet and Slash with a new, simpler, consolidated Slash, using plain text for the backend and probably moving to FastAPI. Since I’m in the middle of planning the rewrite right now (and since I’m now working in public), you’ll see posts about it soon.


Reply via email

Ditto intro

Another entry in the tedious series about my personal productivity tools.

Ditto is my transcription app. It’s a Python app using FastAPI for the web parts.

Overview

The goal with Ditto is to take scans (usually of journals) and make it easy to transcribe them a page at a time. Same idea as Unbindery, though scaled way, way down: single-user instead of crowdsourced, a simplified workflow, and it only supports one project at a time so I don’t spread my limited transcription time too thin. It looks like this:

ditto-1.png

And there’s an inverted mode, which initially seemed like a great idea (dark mode, basically) but I never actually use it, I think because it’s harder to read:

ditto-2.png

The transcriptions are stored as plain text files in the same directory as the corresponding images.

How I use Ditto

I spend a few minutes transcribing journals each morning as part of my daily routine. (As I finish each volume, I pull the transcribed text files off my server, concatenate them, do some minor formatting, and then import them into Vinci.)

The future

When I made Ditto, one of my goals was to make it work well on mobile so I could have a portable transcription station anywhere I went. It has a responsive design that does work on a phone, but the experience is currently slightly awkward (lots of panning), so I tend to only use it on my laptop. At some point I’d like to try to fix that.

Other than that, though, I’m happy with it. It works well. And it’s small — 340 lines of code. (Which makes me inordinately happy. Small tools are the best.)


Reply via email

Vinci intro

Another entry in the snore-inducing series talking about my personal productivity tools.

Vinci is my journal/log app, a private blog of sorts. It’s a Python app running in Django.

Overview

Vinci has notebooks which contain entries. Like most blogs, entries are displayed in reverse chronological order. It looks like this, except I usually write in English, har har:

vinci-1.png

Editing an entry is a modal fullscreen panel, with the main textbox at top, the metadata textbox under that, and some controls at the bottom.

vinci-2.png

On save, Vinci splices the metadata and the text together and runs it through the payload processor.

Payload syntax

Vinci uses the text-based payload idea like Liszt. Its payload syntax looks like this:

/projects
:tags foo, bar

Worked on the [foo project](/leaf/3290) for a while. Ran into a few issues.

The first line is the notebook specifier. The second line (and this could have been anywhere, didn’t have to be at the top) has a command with some parameters. And the rest is Markdown.

There’s also a variant syntax where the first line can look like this: /projects/tag/tag2/tag3. I’ve started using that a little more often.

Because of how I like to write in my journal, I’ve also set up a special case for my /journal notebook, where adding an entry will either create a new entry for the day (if there isn’t one yet) or append to the existing entry, so there’s just one entry for each day. (I use Gate or Quill to jot down a paragraph and then append it quickly and easily.)

How I use Vinci

I use Vinci a lot. I maintain my personal journal in it, along with logs for most areas of my life — work, school, writing, projects, church, etc. Sometimes I create notebooks for specific projects, other times I use a higher-level notebook (like /projects) and use tags instead. At some point I’ll probably consolidate.

I have a /thinking notebook where once each morning I think through my current tasks/projects and write out what I need to do for each. Writing things down makes a world of difference for me, across the board.

Each morning I also spend a few minutes reading one of my past journal entries, as mentioned earlier today. (A while back I scanned all my paper journals and I’ve been slowly transcribing them — we’ll get to Ditto soon — and importing them into Vinci.) Lately I’ve been reading through my 2004 college entries. My undergraduate years were great, but I am very, very glad I’m not in that phase of life anymore.

Lastly, I reference these notebooks fairly frequently. (When did we replace our dishwasher, what did I last work on for that project I haven’t worked on in months, etc.)

The future

Vinci currently uses Whoosh for full-text indexing, but it’s unsupported and hasn’t been working as well for me lately. Several months ago I realized that if all my notebook entries are stored in plain text files, I can just use ripgrep or ag for fast and accurate searching, with the further benefit that in the event of my untimely demise, everything would be fairly easy for my family to copy out and preserve. (I really like plain text, can you tell?)

To that end, I started writing a new, smaller app in Go called Leaf. It’s going well, but I’m tempted to switch to FastAPI. Not sure yet if I will or not. (I’ve enjoyed learning Go and have used it on several small projects now, but I’m also thinking more about long-term maintenance across all these apps, and using a single stack would simplify things for me.)

I’m also thinking about adding a small CLI (in the web interface) that would make entry management easier — moving all entries with a specific tag to their own notebook, for example. Truth be told, I don’t know that entry management happens frequently enough to warrant a CLI, but I’m intrigued by the idea of putting a CLI in the interface, and if it goes as well as I hope it will, I see myself doing that in more of my tools. (Right now I see it as an extension of the search interface. Where right now I type dishwasher to search for that keyword, I’d eventually also be able to type something like :move /projects#cardiff /cardiff.)

As with Liszt, I’m also looking forward to moving to a lighter, simpler codebase. Vinci has a moderate amount of vestigial functionality that needs to go.


Reply via email

For the last year or so I’ve been rereading some of my old journals each day, to remind myself of my past. My memory tends to focus almost entirely on recent personal history — the last year or so — and if it weren’t for this ritual, I honestly don’t know that I would really ever think about my life before that, except for when my kids ask me stories about my childhood.

I’m learning some things about myself I’d completely forgotten about — apparently I was very interested in art right after my mission, for example, and even almost majored in it. (I’d thought I didn’t really get into art until ten years ago. Whoops.)

The other thing I’ve noticed is that the parts of my journal that mean the most to me now are the little bits about the other people in my life, friends and family, particularly those I don’t much interact with anymore and those who’ve passed on. It’s almost magical to me how fondness from the long ago past can be resurrected with a mere word or a phrase.


Reply via email

Two quick thoughts on reading:

Over the last few years I’ve wanted to get back into reading classics (“back into” referring to high school and college lit classes), but…it’s a struggle. I’ve DNFed pretty much all the classic novels I’ve tried to read — Oliver Twist, Madame Bovary, War & Peace, and Scaramouche, among others. What I suspect is probably at fault here: my fiction tastes skew heavily toward genre (primarily sf&f with occasional forays into mystery and thrillers), with realistic/literary fiction (basically all those aforementioned classics falling into this category) usually boring me out of my mind. Not entirely sure what to do about it yet, other than to try reading something like Dracula to see if the same thing happens.

Also, from the flip side of the coin: I’ve been reading a fair amount of more contemporary sf&f lately (the last several years) and goodness, there’s a lot of great fantasy and science fiction being published these days.


Reply via email