logo.go (2003B)
1 package utils 2 3 import ( 4 "fmt" 5 "image" 6 "path/filepath" 7 "strings" 8 "sync" 9 10 aic "github.com/TheZoraiz/ascii-image-converter/aic_package" 11 "github.com/disintegration/imaging" 12 ) 13 14 var logoMu sync.Mutex 15 16 const logoPath = "static/me.jpg" 17 18 // logoCrop frames the face: fractions of the source image (x0, y0, x1, y1). 19 var logoCrop = [4]float64{0.12, 0.08, 0.88, 0.84} 20 21 // LogoASCII renders static/me.jpg for terminals. Colored output uses 22 // half-block cells (upper half = foreground, lower half = background), so each 23 // cell carries two truecolor pixels and the portrait reads as a photo. Plain 24 // output falls back to ascii art. 25 func LogoASCII(width int, colored bool) string { 26 logoMu.Lock() 27 defer logoMu.Unlock() 28 29 if colored { 30 if s, err := halfBlocks(logoPath, width); err == nil { 31 return s 32 } 33 } 34 flags := aic.DefaultFlags() 35 flags.Width = width 36 flags.Dither = true 37 flags.Threshold = 160 38 ascii, err := aic.Convert(filepath.FromSlash(logoPath), flags) 39 if err != nil { 40 return "" 41 } 42 return strings.TrimRight(ascii, "\n") 43 } 44 45 func halfBlocks(path string, width int) (string, error) { 46 src, err := imaging.Open(path, imaging.AutoOrientation(true)) 47 if err != nil { 48 return "", err 49 } 50 b := src.Bounds() 51 w, h := float64(b.Dx()), float64(b.Dy()) 52 rect := image.Rect( 53 b.Min.X+int(logoCrop[0]*w), b.Min.Y+int(logoCrop[1]*h), 54 b.Min.X+int(logoCrop[2]*w), b.Min.Y+int(logoCrop[3]*h), 55 ) 56 crop := imaging.Crop(src, rect) 57 // one cell is roughly twice as tall as wide, so two pixel rows per cell 58 // keep the pixels square 59 rows := int(float64(width)*float64(rect.Dy())/float64(rect.Dx())+0.5) &^ 1 60 img := imaging.Resize(crop, width, rows, imaging.Lanczos) 61 62 var sb strings.Builder 63 for y := 0; y < rows; y += 2 { 64 if y > 0 { 65 sb.WriteByte('\n') 66 } 67 for x := 0; x < width; x++ { 68 t := img.NRGBAAt(x, y) 69 u := img.NRGBAAt(x, y+1) 70 fmt.Fprintf(&sb, "\x1b[38;2;%d;%d;%dm\x1b[48;2;%d;%d;%dmâ–€", t.R, t.G, t.B, u.R, u.G, u.B) 71 } 72 sb.WriteString("\x1b[0m") 73 } 74 return sb.String(), nil 75 }