Last active
August 1, 2020 18:04
-
-
Save sug0/e9307c6ad16a4a6640a3bb3088851ff7 to your computer and use it in GitHub Desktop.
Image to braille art converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // $ mkdir braille | |
| // $ cd braille | |
| // $ go mod init braille | |
| // $ <... copy this file into main.go> | |
| // $ go build | |
| // $ curl -sf <some image> | ./braille -width 100 -height 100 -lum 128 | |
| package main | |
| import ( | |
| "os" | |
| "fmt" | |
| "flag" | |
| "bufio" | |
| "bytes" | |
| "image" | |
| "image/draw" | |
| _ "image/png" | |
| _ "image/jpeg" | |
| "github.com/bamiaux/rez" | |
| _ "github.com/hullerob/go.farbfeld" | |
| ) | |
| var lum byte | |
| var inv rune | |
| var iinv bool | |
| var width, height, llum int | |
| func main() { | |
| flag.IntVar(&width, "width", 20, "The width of the image.") | |
| flag.IntVar(&height, "height", 20, "The height of the image.") | |
| flag.IntVar(&llum, "lum", 128, "The lum of the image.") | |
| flag.BoolVar(&iinv, "inv", false, "Invert colors.") | |
| flag.Parse() | |
| if width % 2 != 0 { | |
| panic("width % 2 != 0") | |
| } | |
| if height % 4 != 0 { | |
| panic("height % 4 != 0") | |
| } | |
| if iinv { | |
| inv = 1 | |
| } else { | |
| inv = 0 | |
| } | |
| lum = byte(llum & 0xff) | |
| imgIface, _, err := image.Decode(bufio.NewReader(os.Stdin)) | |
| if err != nil { | |
| panic(err) | |
| } | |
| if _, ok := imgIface.(*image.Gray); !ok { | |
| newIface := image.NewGray(imgIface.Bounds()) | |
| draw.Draw(newIface, imgIface.Bounds(), imgIface, image.Pt(0, 0), draw.Over) | |
| imgIface = newIface | |
| } | |
| im := image.NewGray(image.Rect(0, 0, width, height)) | |
| err = rez.Convert(im, imgIface, rez.NewBilinearFilter()) | |
| if err != nil { | |
| panic(err) | |
| } | |
| var buf bytes.Buffer | |
| for y := 0; y < height; y += 4 { | |
| for x := 0; x < width; x += 2 { | |
| var bits rune | |
| bits |= runeValue(im.Pix[(y+0)*width + (x+0)]) << 0 | |
| bits |= runeValue(im.Pix[(y+0)*width + (x+1)]) << 3 | |
| bits |= runeValue(im.Pix[(y+1)*width + (x+0)]) << 1 | |
| bits |= runeValue(im.Pix[(y+1)*width + (x+1)]) << 4 | |
| bits |= runeValue(im.Pix[(y+2)*width + (x+0)]) << 2 | |
| bits |= runeValue(im.Pix[(y+2)*width + (x+1)]) << 5 | |
| bits |= runeValue(im.Pix[(y+3)*width + (x+0)]) << 6 | |
| bits |= runeValue(im.Pix[(y+3)*width + (x+1)]) << 7 | |
| fmt.Fprintf(&buf, "%c", 0x2800 | bits) | |
| } | |
| fmt.Fprintln(&buf) | |
| } | |
| os.Stdout.Write(buf.Bytes()) | |
| } | |
| func runeValue(y byte) rune { | |
| if y < lum { | |
| return 1 ^ inv | |
| } | |
| return 0 ^ inv | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment