Consequest

The Elixir Experiment

Consequest

I'm not great at painting a picture with words and I'm even worse at actually painting, regardless of how clearly I can see something in my head. This can make game-mastering challenging, since that's an awful lot of what the job is. But with some time, I can usually get MidJourney to create something close to what I had envisioned.

In my current game, I've been using an impasto oil painting theme for the imagery I hand out to my players, and while I was generating some portraits for other items they had found, I decided to create a palette of differently colored and shaped potions for kicks.

The bottles come in four shapes: cylinders, cubes, orbs and pyramids. You'll find your standard color wheel options here, some precious metal potions, as well as some exotic varieties, like pearlescent, crystalline and the illusive eighth color, the color of magic itself, octarine.

You can jump down below to the project notes for some commentary on the prompting process, some scriptfu I used to batch-convert this pile of images and building this page. Now, without further adieu...

red red round red square red orb red pyramid
orange orange round orange square orange orb orange pyramid
brown brown round brown square brown orb brown pyramid
yellow yellow round yellow square yellow orb yellow pyramid
green green round green square green orb green pyramid
cyan cyan round cyan square cyan orb cyan pyramid
blue blue round blue square blue orb blue pyramid
purple purple round purple square purple orb purple pyramid
magenta magenta round magenta square magenta orb magenta pyramid
white white round white square white orb white pyramid
gray gray round gray square gray orb gray pyramid
black black round black square black orb black pyramid
gold gold round gold square gold orb gold pyramid
silver silver round silver square silver orb silver pyramid
copper copper round copper square copper orb copper pyramid
pearlescent pearlescent round pearlescent square pearlescent orb pearlescent pyramid
crystalline crystalline round crystalline square crystalline orb crystalline pyramid
octarine octarine round octarine square octarine orb octarine pyramid

Project Notes

MidJourney Prompting

The images were generated using the alpha version of MidJourney v6 and started with a simple prompt.

/imagine a {color} potion in a {shape} bottle. painted in the style of an impasto oil painting, indistinct background. --v 6.0 --style raw

The {shape} was one of cylindrical, spherical, square or pyramid-shaped, while {color} is usually from the table below.

Some colors, especially the metallic ones, would paint bottles made of the metal rather than make a potion that looked like it was filled with liquid metal, forcing me to add some detail to the prompt to make sure I got a glass bottle.

/imagine a {color} potion in a {shape}, clear-glass bottle. the bottle is uncolored and transparent. painted in the style of an impasto oil painting, indistinct background. --v 6.0 --style raw

The exotic potion colors required more creativity and lots of iterating.

Pearlescent potions often turned out too transparent, forcing me to modify the prompt to get a more opaque liquid, more reminiscent of the color you'd find inside of shellfish, like oily milk.

The crystalline potions initially tended to look like water, rainbowish at best. While adding the word "fractured" produced something closer to what I was looking for, with light catching the broken edges of glass, but this often resulted in the bottle looking like it was full of hairline cracks instead of creating the strange liquid I was looking for.

For octarine, I settled on "fluorescent greenish-yellow purple" after iterating on some variations of Pterry's definition, but still could only manage something that looked like the color was changing because of some shift in light refracting through the potion.

One other unexpected detail was the stopper for the bottle. Most often, you end up with a cork for cylindrical and square shaped bottles. But for spherical bottles, it seemed like every generation produced at least one image with an orb-shaped glass stopper The pyramid-shaped bottles almost always came with pyramid-shaped glass stoppers. I wonder what bias in the training data resulted in that behavior?

Having a differently shaped stopper was nice, from time to time, but I wanted to stick mostly with corks, and sometimes, requiring a cork in the prompt was the only way to convince MidJourney to draw one.

/imagine a {color} potion in a {shape}, clear-glass bottle with cork. the bottle is uncolored and transparent. painted in the style of an impasto oil painting, indistinct background. --v 6.0 --style raw

Batch Image Processing

MidJourney outputs PNG images, which, especially after v6 upscaling to 2048x2048, can produce some very large files. The raw output for all of the images in this post totaled more than 550MB - a pretty heavy lift up front. To mitigate your bandwidth usage, I've converted all of the images to JPG, and scaled the individual potions to 25% of their original size; you can view full-size JPG versions by clicking any of them.

I didn't convert these by hand - that would be madness. A little ImageMagick and some shell scripting made converting the raw images dead-simple.

# convert to full-size JPGs
for i in raw/*.png; do o=${i##*/}; o=jpg/${o%.*}.jpg; convert $i $o; done

# create JPG thumbnails
for i in raw/*.png; do o=${i##*/}; o=thumb/${o%.*}.jpg; convert $i -resize 25% $o; done

Creating the Tables

If I need to build a gallery again, I will need to refine this process with a full-blown script. It could have been worse, by building the table by hand, but this was still painful enough. The gallery table will hold the thumbnails of the potions, which link to full-size versions of the same image; there will be a row for each color, and a column for each bottle shape.

Confession: this is actually slightly refined from the way I originally built the table, because I found a few issues in the result, imagine that.

This all depends on how I uploaded the images and how bearblog decides to name them, which I am not altogether sure I understand. I may have gotten very lucky in picking the right batch sizes. I uploaded the images in batches of four (the four bottle shapes for each color). I'm not sure whether it was because I had the file selection dialog sorted on the file name or if the upload process also sorts the file names, but the munged file names I got back always mapped exactly the same way to the images. And since I don't have any direct access to manage files I upload here, I don't really want to do the experiment to find out, not that it would be conclusive anyway.

I say that I am unsure about whether I got very lucky with the protocol because in the past when I had uploaded batches of files, sometimes the timestamp in the file name would change in the middle of the batch and the index would restart. In this case, I never saw that happen.

The original files, in the order I selected them in the file dialog (descending alphabetical order), and the file names bearblog sent back were formatted like this:

{color}-square.jpg      consequest-{time}-0.jpg     # cube bottle
{color}-round.jpg       consequest-{time}-1.jpg     # cylindrical bottle
{color}-pyramid.jpg     consequest-{time}-2.jpg
{color}-orb.jpg         consequest-{time}-3.jpg

For each batch, I added a header for the color, uploaded the images, then stripped out the empty lines bearblog put between each image.

# yellow
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708819693-3.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708819693-2.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708819693-1.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708819693-0.jpg)

I reordered the lines in each group and stripped out the empty lines manually. As uploaded, they were in orb-pyramid-round-square order, but I wanted to present them in round-square-orb-pyramid order, since I decided, knowing nothing about bottle making or glass blowing, that bottles in those shapes would be progressively harder to actually make.

And all of that was done for all 4 shapes of the 17 colors, for the thumbnail and full-size images. It was about at that time that I decided that I was not going to build the table by hand and started working on some regexes.

But to set up for that, there were two more manual steps to complete. First, to group the thumbnails with the full-size images, which left me with something like this for each color:

# yellow
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708809172-1.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708809172-0.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708809172-3.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708809172-2.jpg)

# yellow
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708819693-1.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708819693-0.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708819693-3.jpg)
![Consequest](https://bear-images.sfo2.cdn.digitaloceanspaces.com/consequest-1708819693-2.jpg)

And then to group and sort the colors thematically.

With all of that setup, we've got something that is well structured enough to build some patterns around. First, we'll layout the pattern for each line in the input and output patterns.

The regular expression to match all eight of the images for each color's block looks something like this:

# (\S+)\n                                       # capture the color
!\[Consequest\]\((.+?)-(\d+)-1\.jpg\)\n         # capture base address and thumbnail timestamp
!\[Consequest\]\(\2-\3-0\.jpg\)\n               # match base address and thumbnail timestamp
!\[Consequest\]\(\2-\3-3\.jpg\)\n               # match base address and thumbnail timestamp
!\[Consequest\]\(\2-\3-2\.jpg\)\n               # match base address and thumbnail timestamp
\n
# \1\n                                          # match the color
!\[Consequest\]\(\2-(\d+)-1\.jpg\)\n            # match base address and capture full-size timestamp
!\[Consequest\]\(\2-\4-0\.jpg\)\n               # match base address and full-size timestamp
!\[Consequest\]\(\2-\4-3\.jpg\)\n               # match base address and full-size timestamp
!\[Consequest\]\(\2-\4-2\.jpg\)\n               # match base address and full-size timestamp

And the output pattern for the table row is (with a placeholder <SHAPE> to keep things aligned):

| $1
| [ ![$1 <SHAPE>]($2-$3-1.jpg) ]($2-$4-1.jpg)   # <SHAPE> = round
| [ ![$1 <SHAPE>]($2-$3-0.jpg) ]($2-$4-0.jpg)   # <SHAPE> = square
| [ ![$1 <SHAPE>]($2-$3-3.jpg) ]($2-$4-3.jpg)   # <SHAPE> = orb
| [ ![$1 <SHAPE>]($2-$3-2.jpg) ]($2-$4-2.jpg)   # <SHAPE> = pyramid
|

Filling in the placeholders and collapsing these down to single lines for vscode's search/replace dialog, leaves us with these final patterns:

# (\S+)\n!\[Consequest\]\((.+?)-(\d+)-1\.jpg\)\n!\[Consequest\]\(\2-\3-0\.jpg\)\n!\[Consequest\]\(\2-\3-3\.jpg\)\n!\[Consequest\]\(\2-\3-2\.jpg\)\n\n# \1\n!\[Consequest\]\(\2-(\d+)-1\.jpg\)\n!\[Consequest\]\(\2-\4-0\.jpg\)\n!\[Consequest\]\(\2-\4-3\.jpg\)\n!\[Consequest\]\(\2-\4-2\.jpg\)\n


| $1 | [ ![$1 round]($2-$3-1.jpg) ]($2-$4-1.jpg) | [ ![$1 square]($2-$3-0.jpg) ]($2-$4-0.jpg) | [ ![$1 orb]($2-$3-3.jpg) ]($2-$4-3.jpg) | [ ![$1 pyramid]($2-$3-2.jpg) ]($2-$4-2.jpg) |

Replace all, do some cleanup, and we end up with our table of thumbnails linking to their full-size counterparts.

#imagemagick #items #midjourney #potions #shell