Categories: sharing » drawing

RSS - Atom - Subscribe via email

Recoloring my sketches with Python

| supernote, drawing

The SuperNote lets me draw with black, dark gray (0x9d), gray (0xc9), or white. I wanted to make it easy to recolor them, since a little splash of colour makes sketches more fun and also makes them easier to pick out from thumbnails. Here's the Python script I wrote:

Download recolor.py
#!/usr/bin/python3
# Recolor PNGs
#
# (c) 2022 Sacha Chua (sacha@sachachua.com) - MIT License
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:

# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import numpy as np
import sys
import os
import csv
import argparse
from PIL import Image

DARK_GRAY = 0x9d
GRAY = 0xc9
WHITE = 0xfe

parser = argparse.ArgumentParser(description='Recolor a PNG.',
                                 formatter_class=argparse.RawTextHelpFormatter,
                                 epilog="If neither --colors nor --freq are specified, display the most frequent colours in the image.")
parser.add_argument('--colors', help="""Comma-separated list of RGB hex values in the form of old,new,old,new
Examples:
9d,ffaaaa,c9,ffd2d2 - reddish
c9,ffea96 - yellow highlighter
c9,d2d2ff - light blue
""")
parser.add_argument('--freq', help="Color replacements in order of descending frequency (ex: .,ffea96). .: use original color")
parser.add_argument('--csv', help="CSV of color names to use in the form of colorname,hex")
parser.add_argument('--preview', help="Preview only", action='store_const', const=True)
parser.add_argument('input', help="Input file")
parser.add_argument('output', nargs='?', help="Output file. If not specified, overwrite input file.")

args = parser.parse_args()

def color_to_tuple(color_dict, s):
    if s in color_dict:
        s = color_dict[s]
    s = s.lstrip('#')
    if (s == '.'):
        return (None, None, None)
    elif (len(s) == 2):
        return (int(s, 16), int(s, 16), int(s, 16))
    else:
        return tuple(int(s[i:i + 2], 16) for i in (0, 2, 4))

def load_color_dict(filename):
    dict = {}
    with open(filename, newline='') as csvfile:
        reader = csv.reader(csvfile, delimiter=',', quotechar='"')
        for row in reader:
            dict[row[0]] = row[1]
    return dict

color_dict = load_color_dict(args.csv) if args.csv else {}

input = args.input
output = args.output if args.output else input
if os.path.isdir(output):
    output = os.path.join(output, os.path.basename(input))

im = Image.open(input).convert('RGB')
data = np.array(im)
red, green, blue = data[:, :, 0], data[:, :, 1], data[:, :, 2]

if args.colors:
    colors = iter(args.colors.split(','))
    for from_c in colors:
        to_c = next(colors)
        from_r, from_b, from_g = color_to_tuple(color_dict, from_c)
        to_r, to_b, to_g = color_to_tuple(color_dict, to_c)
        mask = (red == from_r) & (green == from_g) & (blue == from_b)
        data[:, :, :3][mask] = [to_r, to_b, to_g]
else:
    colors = im.getcolors()
    sorted_colors = sorted(colors, key=lambda x: x[0], reverse=True)
    if args.freq:
        freq = iter(args.freq.split(','))
        for i, f in enumerate(freq):
            if f != '.':
                to_r, to_b, to_g = color_to_tuple(color_dict, f)
                by_freq = sorted_colors[i][1]
                if isinstance(by_freq, np.uint8):
                    print(i, '%02x' % by_freq, f)
                    mask = (red == by_freq) & (green == by_freq) & (blue == by_freq)
                else:
                    print(i, ''.join(['%02x' % c for c in by_freq]), f)
                    mask = (red == by_freq[0]) & (green == by_freq[1]) & (blue == by_freq[2])
                data[:, :, :3][mask] = [to_r, to_b, to_g]
    else:
        for x in sorted_colors:
            if isinstance(x[1], np.uint8):
                print('%02x' % x[1])
            else:
                print(''.join(['%02x' % c for c in x[1]]))
        exit(0)
im = Image.fromarray(data)
if args.preview:
    im.thumbnail((700, 700), Image.ANTIALIAS)
    im.show()
else:
    im.save(output)

I don't think in hex colours, so I added a way to refer to colours by names. I converted this list of Copic CSS colours to a CSV by copying the text, pasting it into a file, and doing a little replacement. It's not complete, but I can copy selected colours from this longer list. I can also add my own. The CSV looks a little like this:

darkgray,9d
gray,c9
lightgreen,cfe8d3
lightyellow,f6f396
lightblue,b3e3f1
y02,f6f396
w2,ddddd5
b02,b3e3f1
...

It doesn't do any fuzzing or clustering of similar colours, so it won't work well on antialiased images. For the simple sketches I make with the SuperNote, though, it seems to work well enough.

I can preview my changes with something like ./recolor.py ~/sketches/"2022-08-02-01 Playing with my drawing workflow #supernote #drawing #workflow #sketching #kaizen.png" --csv colors.csv --freq .,lightyellow --preview , and then I can take the --preview flag off to overwrite the PNG.

Here's what the output looks like after recoloring grayscale images:

View or add comments

One month with the SuperNote A5X

| supernote, drawing, tech

I've had my SuperNote A5X for a month now, and I really like it.

Text from my sketch

I use it for:

  • untangling thoughts
  • sketchnoting books
  • planning
  • drafting blog posts
  • drawing

A- uses it for: (she's 6 years old)

  • practising cursive
  • doing mazes and dot-to-dots
  • drawing
  • reading lyrics

Things I'm learning:

  • Exporting PNGs at 200% works well for my workflow. I rename them in Dropbox and upload them to sketches.sachachua.com.
  • Carefully copying & deleting pages lets me preserve page numbers. I use lassoed titles for active thoughts and maintain a manual index for other things.
  • Layouts:
    • Landscape: only easier to review on my laptop
    • Portrait columns: lots of scrolling up and down
    • Portrait rows: a little harder to plan, but easier to review
  • Many books fit into one page each.
  • Google Lens does a decent job of converting my handwriting to text (print or cursive, even with a background). Dropbox β†’ Google Photos β†’ Orgzly β†’ Org
  • Draft blog posts go into new notebooks so that I can delete them once converted.
  • The Super Note helps me reclaim a lot of the time I spend waiting for A-. A digital notebook is really nice. Easy to erase, rearrange, export… It works well for me.
  • Part of my everyday carry kit

Ideas for growth:

  • Settle into monthly pages, bullet journaling techniques
  • Practise drawing; use larger graphic elements & organizers, different shades
  • Integrate into Zettelkasten

I put my visual book notes and visual library notes into a Dropbox shared folder so that you can check them out if you have a Supernote. If you don't have a Supernote, you can find my visual book notes at sketches.sachachua.com. Enjoy!

View or add comments

Trying out the SuperNote A5X

| geek, drawing, supernote

W- was happy with his SuperNote A5X, so I ordered one for myself on July 18. The company was still doing pre-orders because of the lockdowns in China, but it shipped out on July 20 and arrived on July 25, which was pretty fast.

I noticed that the org-epub export makes verse blocks look double-spaced on the SuperNote, probably because <br> tags are getting extra spacing. I couldn't figure out how to fix it with CSS, so I've been hacking around it by exporting it as a different class without the <br> tags and just using { white-space: pre }. I also ended up redoing the templates I made in Inkscape, since the gray I used was too light to see on the SuperNote.

It was very tempting to dive into the rabbithole of interesting layouts on /r/supernote and various journaling resources, but I still don't have much time, so there's no point in getting all fancy about to-do lists or trackers at the moment. I wanted to focus on just a couple of things: untangling my thoughts and sketching. Sketchnoting books would be a nice bonus (and I actually managed to do one on paper during a recent playdate), but that can also wait until I have more focused time.

I've had the A5X for five days and I really like it. Writing with the Lamy pen feels like less work than writing with a pencil or regular pen. It's smooth but not rubbery. I've still been drawing in landscape form because that feels a little handier for reviewing on my tablet or writing about on my blog, but I should probably experiment with portrait form at some point.

So far, I've:

sketched out my thoughts
I used to use folded-over 8x14" to sketch out two thoughts, but scanning them was a bit of a pain. Sometimes I used the backs of our writing practice sheets in order to reduce paper waste, but then scanning wasn't always as clean. I really like using the SuperNote to sketch out thoughts like this one. It's neat, and I can get the note into my archive pretty easily.
sketched stuff from life
This is easier if I take a quick reference picture on my phone. I could probably even figure out some kind of workflow for making that available as a template for tracing.
received many kiddo drawings
A- loves being able to use the eraser and lasso to modify her drawings. Novelty's probably another key attraction, too. She's made quite a few drawings for me, even experimenting with drawing faces from the side like the way she's been seeing me practice doing.
received many kiddo requests
A- likes to ask me to draw things. She enjoys tracing over them in another layer. More drawing practice for both of us!
used it to help A- practise coding, etc.
A- wanted to do some coding puzzles with her favourite characters. I enjoyed being able to quickly sketch it up, drawing large versions and then scaling down as needed.
played a game of chess
I drew chess pieces just to see if I could, and we ended up using those to play chess. I should share these and maybe add other games as well.
referred to EPUBs and PDFs
I put our favourite songs and poems on it. I've also started using org-chef to keep a cookbook.
doodled sketch elements
boxes, borders, little icons, people… Probably should organize these and share them too.

I've figured out how to publish sketches by using my phone to rotate them and sync them with my online sketches. Now I'm playing around with my writing workflow to see if I can easily post them to my blog. At some point, I think I'll experiment with using my phone to record and automatically transcribe some commentary, which I can pull into the blog post via some other Emacs Lisp code I've written. Whee!

View or add comments

Making a menu of activities

| sketchnotes, drawing, parenting, play

A- wants to be with me almost all the time. This can be challenging.

A multiple-choice question is easier than a fill-in-the-blank one, especially when it comes to "What do we do now?" A- seems less grumpy throughout the day when she can go from one activity to another of her choosing. I like letting her take the lead. I also like not having to come up with stuff. During bedtime, I sketched this menu:

View or add comments

Kindergarten means I get to learn how to write, too

| drawing

A- wants to learn cursive, probably because it's extra-fancy and the sort of thing Elizabeth Bennet would have done. There's some support for teaching cursive in kindergarten, so it's not totally crazy. It's a good opportunity for me to improve my lettering skills, too. She usually likes it when we do the same thing at the same time, so working on letters together is a good way to nudge her to practise fine motor skills. We did a brush lettering worksheet for "Aa" from Amy Latta Creations. This one is my worksheet.

I've got lots to learn about controlling a brush pen. Doing lots of drills will probably help me get my up-strokes to be as thin as the samples.

A- often asks me to connect my letters. I think I'll make our own worksheets so that she can connect letters too.

At bedtime, I drew in my sketchbook while she read independently. When she noticed what I was doing, she said she liked the 3D letters and encouraged me to do more. She pointed to blank spaces on the page and suggested things to add.

Not that different compared to my lettering experiments from 2013:

But hey, I'm learning stuff!

View or add comments

Using Org Mode, LaTeX, Beamer, and Medibang Paint to make a children's book

| drawing, emacs, geek, org, publishing

Story

  • It's time to make a smoothie!
  • I pour blueberries into the blender.
  • Mama adds hemp seeds.
  • I add spinach.
  • Mama blends it all with some water.
  • I peel and add a banana.
  • I add some yogurt.
  • Mama blends it again.
  • Yum yum!

Thumbnails

spread0.png spread1.png spread2.png spread3.png spread4.png spread5.png

Process

  • Prerequisites

    • ImageMagick
    • Texlive (probably)
    • latex-beamer
    • Org Mode and Emacs
  • Set up Org Mode export to Beamer

    (eval-after-load "ox-latex"
      ;; update the list of LaTeX classes and associated header (encoding, etc.)
      ;; and structure
      '(add-to-list 'org-latex-classes
                    `("beamer"
                      ,(concat "\\documentclass[presentation]{beamer}\n"
                               "[DEFAULT-PACKAGES]"
                               "[PACKAGES]"
                               "[EXTRA]\n")
                      ("\\section{%s}" . "\\section*{%s}")
                      ("\\subsection{%s}" . "\\subsection*{%s}")
                      ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))
    

  • Set up image directories

    mkdir text-pages blank-spreads drawn drawn-pages
    

    text-pages Will contain one image per page of just the plain text.
    blank-spreads Will contain text spreads ready for drawing
    drawn Export one image per spread (without the text layers) from your drawing program
    drawn-pages Will contain one image per page combining text and drawing
  • Tweak the header.tex

    This file gets included in the LaTeX file for the children's book. Tweak it to change the appearance. In this example, I use black serif text at the bottom of the page.

    \geometry{paperwidth=7in,paperheight=8.5in,left=0.5in,top=0.5in,right=0.5in,bottom=0.5in}
    \setbeamercolor{normal text}{fg=black,bg=white}
    \setbeamercolor{structure}{fg=black,bg=white}
    \usefonttheme{serif}
    \setbeamertemplate{frametitle}
    {
      \begin{center}
      \vspace{0.7\textheight}                    
      \noindent
      \insertframetitle
      \end{center}
    }
    \usepackage[noframe]{showframe}
    \renewcommand{\maketitle}{}
    

  • Write the story

    I used Org Mode to make it easy to write the story.

    Some considerations:

    • Because we're printing this as a saddle-stitched booklet, the number of lines should be a multiple of four. Sixteen is probably a good maximum.
    • The first heading is actually for the last page.
    • The second heading is for the cover page.
    • The third heading is for the first inner page, the fourth heading is for the second inner page, and so on.
    #+OPTIONS:   TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc author:nil date:nil
    #+OPTIONS: H:1
    #+startup: beamer
    #+LaTeX_CLASS: beamer
    #+LaTeX_CLASS_OPTIONS: [20pt]
    #+BEAMER_FRAME_LEVEL: 1
    #+LATEX_HEADER: \input{header.tex}
    #+PROPERTY: header-args :var pages=12
    
    * Story
    
    ** 
    ** 
    ** 
    ** It's time to make a smoothie!
    ** I pour blueberries into the blender.
    ** Mama adds hemp seeds.
    ** I add spinach.
    ** Mama blends it all with some water.
    ** I peel and add a banana.
    ** I add some yogurt. 
    ** Mama blends it again.
    ** Yum yum!
    

  • Make the tex, PDF, page PNGs, and spread PNGs

    1. Go to the subtree for the story and use M-x org-export-dispatch (C-c C-e) with the subtree option (C-s) to export it as a Beamer file (option l b).
    2. Use pdflatex to convert the .tex to PDF.

      pdflatex index.tex
      

    3. Create one PNG per text page with:

      convert -density 300 index.pdf -quality 100 text-pages/page%02d.png
      

    4. Create spreads to draw on with:

      montage text-pages/page*.png -tile 2x1 -mode Concatenate blank-spreads/spread%d.png
      

    5. Optionally, create a layered PSD with:

      convert blank-spreads/spread*.png \( -clone 1,0 -background white -flatten -alpha off \) -reverse spreads-for-drawing.psd
      

  • Draw

    I imported the PNG layers into MediBang Paint on a Samsung Note 8 Android phone, and then:

    • imported photos
    • traced them
    • painted and shaded them
    • hid the text layers
    • exported one PNG per spread to QuickPic, renamed them, and uploaded them to Dropbox, because I couldn't figure out how to export to Dropbox directly

    Layer folders were handy for organizing spread-related images. I couldn't seem to move all of the layers in a layer folder together on Android, but the iPad was able to do so. If I didn't have the iPad handy, I combined the layers by exporting a PNG and then importeing it back into MediBang Paint.

    This was a decent setup that allowed me to draw and paint even when I was in bed nursing A- and waiting for her to fall asleep. I held the phone with one hand and rotated the canvas as needed so that it was easier for me to draw lines with my right. Because of the awkward position and the small screen size, the lines are not as smooth as I might like, but the important thing is that they're there. Whee! =)

    It turns out to be possible to use the free MediBang Pro drawing program under Wine on Linux to import the PSD and save it to the cloud. I was also sometimes able to switch to drawing with iPad Pro with Pencil, but it was harder to find time to do that because that usually made A- want to draw too.

    Anyway, after I drew and exported the PNGs, the next step was to…

  • Convert the drawn spreads back to pages and combine them with the text

    Here's some code that combines the drawing and the text. Keeping the drawing and the text separate until this stage (instead of exporting the PNGs with the text) makes it easier to change the text later by recreating the text PNGs and running this step.

    (defun my/combine-spread-drawing-and-text (page num-pages)
      (let ((gravity (if (= (% page 2) 1) "West" "East"))
            (spread (/ (% page num-pages) 2)))
        (shell-command
          (format 
           (concat "convert \\( "
                   "drawn/spread%d.png -gravity %s "
                   "-chop 50%%x0 +repage \\) "
                   "text-pages/page%02d.png -compose darken "
                   "-composite drawn-pages/page%02d.png")
           spread gravity page page))))
    
    (cl-loop for i from 0 to (1- pages) do
             (my/combine-spread-drawing-and-text i pages))
    

  • Create print spreads for saddle-stitching

    This code pairs up the drawn pages into a PDF that can be printed duplex. Make sure to choose the option to flip along the short edge. I hard-coded the page orders for 4-, 8-, 12-, and 16-page booklets.

    (let* ((page-order
            '((0 1 2 3)   ; hard-coded page sequences
              (0 1 2 7 6 3 4 5)
              (0 1 2 11 10 3 4 9 8 5 6 7)
              (0 1 2 15 14 3 4 13 12 5 6 11 10 7 8 9)))
           (sequence
            (mapconcat (lambda (d) (format "drawn-pages/page%02d.png" d))
                       (elt page-order (1- (/ pages 4))) " ")))
      (shell-command
       (format
        "montage %s -tile 2x1 -mode Concatenate print-duplex-short-edge-flip.pdf"
        sequence)))
    

  • Print and bind

    After printing and folding the book, I used tape to make the book hold together. Tada!

  • Create on-screen PDF for reading

    A little bit of manipulation so that the last page is in the right place:

    (shell-command
      (format "convert %s onscreen.pdf" 
        (mapconcat 'identity (cl-loop for i from 1 to pages 
          collect (format "drawn-pages/page%02d.png" (% i pages))) " ")))
    

  • Create thumbnails of spreads

    (cl-loop
     for i from 0 to (1- (/ pages 2)) do 
     (shell-command
      (format 
       (concat "convert "
               "\\( blank-spreads/spread%d.png "
               "drawn/spread%d.png "
               "-compose darken "
               "-resize %dx -flatten \\) "
               "\\( +clone -background black -shadow 50x1+%d+%d \\) "
               "+swap -compose src-over -composite "
               "thumbnails/spread%d.png")
       i i width shadow shadow i)))
    

  • Ideas for next steps

    • Better thumbnails for easy previews
    • PDF for online reading
    • More layout possibilities (photos, verses, etc.)
    • Smaller books:

      • crop marks on a full-page print, or
      • the right imposition rules to print more pages on a sheet
View or add comments

Making books for A-

| drawing, parenting, publishing, writing

A- loves being read to. She picks up new words and ideas from the books we read, requests both favourites and new books again and again, and can identify objects in photographs and drawings. I borrowed a few children's books from the library in case reading about upcoming changes or challenges helps her understand. The books were okay, but didn't quite fit the words we use or the way we like to handle things. So this week, I decided to make my own books for A-, especially since there are few books that cover things like microphthalmia.

The first book I made was about night weaning, since we might have to do that in preparation for dental surgery under anaesthesia. I sketched it using ZoomNotes on my iPad, exported the SVG, tinkered with it in Inkscape, exported PNGs, combined the PNGs with ImageMagick, and created a 12-page PDF with 7″x8.5″ pages. That let me print the book out on legal-size paper (8.5″x14″), 2 pages per sheet, duplex printing set to flip on the short side, using this page order:
12, 1, 2, 11, 10, 3, 4, 9, 8, 5, 6, 7. I folded each sheet in half. Instead of hand-sewing the binding, I just taped the pages together. And just like that, I had a book that I could page through properly: “No More Nursing, Time to Sleep.”

I read the new book to A-. She asked me to reread it several times. She pointed to the book and said, “A-!” She pointed to the stick figure for me and said, “Mama!” Success!

The next thing I wanted to try was printing in colour. We recently replaced our printer with an HP M277dw colour laser printer that could print duplex, so I was looking forward to giving that a try. I wanted to make a book about the conformer in A-‘s little eye. This time, I drew the pages of the book using layers in Medibang Paint. I drew on the bus home from Riverdale Farm, working around a sleeping A- snuggled in my carrier. I exported each layer as a PNG, used ImageMagick to convert pairs of pages into what I needed to print (page order: 8, 1, 2, 7, 6, 3, 4, 5), combined those into a PDF. I couldn't figure out how to get the HP app to properly scale the document and print in duplex, but printing from Linux worked fine. I quickly had another book in my hands: “My Conformer.”

She's starting to echo phrases from the to books, and it's been only a few days. Wow!

I'm working on a third book now. Time for something fun: “Let's Make a Smoothie,” since she enjoys making and drinking them. She already knows all the words, so this is more about enjoyment. This time, I'm going to make a workflow that lets me draw on two-page spreads. I don't have any wide drawings planned yet, but it could be handy for later. I made an Inkscape template to help me keep margins in mind. I learned how to use Medibang Paint's folders to organize all the layers, and I'm getting the hang of digitally tracing and painting the photos I took.

I'm looking forward to making even more books and refining my workflow along the way. Here are a few things I want to try:

  • Flat colour
  • Painting
  • Programmatically adding text
  • Printing photos
  • Two-page drawing
  • Parametric templates
  • Smaller format by cutting
  • Programmatically adding photos
  • Heavier-weight paper
  • Board book replacement
  • Printing at Staples or similar
  • Print-on-demand book
  • Handstitching
  • Binding with a cover
  • Smaller format by folding and gluing
  • Mobile workflow
  • Vector drawing

And a few quick ideas for possible next books:

  • Potty Time
  • Brushing Teeth
  • Feelings
  • When I Feel Nervous
  • When I Feel Sad
  • Going to Sleep at the Dentist
  • My Life
  • My Day
  • Going Out
  • At Home
  • I Can…
  • I Can Draw
  • Waiting
  • Try Again
  • Dressing Up
  • Alimango sa Dagat
  • Leron Leron Sinta
View or add comments