From f318be9c56ef22aaa64fa726c8f3bee93d5511ca Mon Sep 17 00:00:00 2001
From: Zoraiz
Date: Fri, 3 Sep 2021 00:09:02 +0500
Subject: [PATCH] Added braille art support
---
README.md | 67 ++++++++----
aic_package/convert_gif.go | 26 +++--
aic_package/convert_image.go | 13 ++-
aic_package/convert_root.go | 6 +-
aic_package/util.go | 14 +--
aic_package/vars.go | 15 ++-
cmd/root.go | 14 ++-
cmd/util.go | 11 +-
image_manipulation/ascii_conversions.go | 130 ++++++++++++++++++++++--
image_manipulation/image_conversions.go | 45 ++++----
snapcraft.yaml | 2 +-
11 files changed, 272 insertions(+), 71 deletions(-)
diff --git a/README.md b/README.md
index 29ee263..a3db2ed 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,9 @@
![Github All Releases](https://img.shields.io/github/downloads/TheZoraiz/ascii-image-converter/total?color=brightgreen&label=Release%20Downloads)
[![ascii-image-converter](https://snapcraft.io/ascii-image-converter/badge.svg)](https://snapcraft.io/ascii-image-converter)
-ascii-image-converter is a command-line tool that converts images into ascii art and prints them out onto the console. Available on Windows, Linux and macOS. GIFs are now experimentally supported as well.
+ascii-image-converter is a command-line tool that converts images into ascii art and prints them out onto the console. Available on Windows, Linux and macOS.
+
+Now supports braille art!
Input formats currently supported:
* JPEG/JPG
@@ -14,7 +16,28 @@ Input formats currently supported:
* BMP
* WEBP
* TIFF/TIF
-* GIF (Experimental)
+* GIF
+
+
+Single image:
+
+
+
+
+
+Multiple images:
+
+
+
+
+
+GIF:
+
+
+
+
+
+
## Table of Contents
@@ -130,24 +153,6 @@ Example:
```
ascii-image-converter myImage.jpeg
```
-
-Single image:
-
-
-
-
-
-Multiple images:
-
-
-
-
-
-GIF:
-
-
-
-
### Flags
@@ -165,6 +170,28 @@ ascii-image-converter [image paths/urls] --color
+#### --braille OR -b
+
+Use braille characters instead of ascii. For this flag, your terminal must support braille patters (UTF-8) properly. Otherwise, you may encounter problems with colored or even uncolored braille art.
+```
+ascii-image-converter [image paths/urls] -b
+# Or
+ascii-image-converter [image paths/urls] --braille
+```
+
+
+
+
+
+#### --threshold
+
+Set threshold value to compare when converting each pixel into a dot. Value must be between 0 and 255.
+
+Example:
+```
+ascii-image-converter [image paths/urls] -b --threshold 170
+```
+
#### --dimensions OR -d
> **Note:** Don't immediately append another flag with -d
diff --git a/aic_package/convert_gif.go b/aic_package/convert_gif.go
index b5e0111..324dd57 100644
--- a/aic_package/convert_gif.go
+++ b/aic_package/convert_gif.go
@@ -45,7 +45,7 @@ as an ascii art gif.
Multi-threading has been implemented in multiple places due to long execution time
*/
-func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, localGif *os.File) (string, error) {
+func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, localGif *os.File) error {
var (
originalGif *gif.GIF
@@ -58,7 +58,12 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
originalGif, err = gif.DecodeAll(localGif)
}
if err != nil {
- return "", fmt.Errorf("can't decode %v: %v", gifPath, err)
+ return fmt.Errorf("can't decode %v: %v", gifPath, err)
+ }
+
+ // Error handled earlier to save time in case of long gif processing
+ if braille && saveGifPath != "" {
+ return fmt.Errorf("saving braille art as a gif is not supported")
}
var (
@@ -97,13 +102,18 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
var imgSet [][]imgManip.AsciiPixel
- imgSet, err = imgManip.ConvertToAsciiPixels(frameImage, dimensions, width, height, flipX, flipY, full)
+ imgSet, err = imgManip.ConvertToAsciiPixels(frameImage, dimensions, width, height, flipX, flipY, full, braille)
if err != nil {
fmt.Println("Error:", err)
os.Exit(0)
}
- asciiCharSet := imgManip.ConvertToAsciiChars(imgSet, negative, colored, complex, customMap, fontColor)
+ var asciiCharSet [][]imgManip.AsciiChar
+ if braille {
+ asciiCharSet = imgManip.ConvertToBrailleChars(imgSet, negative, colored, fontColor, threshold)
+ } else {
+ asciiCharSet = imgManip.ConvertToAsciiChars(imgSet, negative, colored, complex, customMap, fontColor)
+ }
gifFramesSlice[i].asciiCharSet = asciiCharSet
gifFramesSlice[i].delay = originalGif.Delay[i]
@@ -137,12 +147,12 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
saveFileName, err := createSaveFileName(gifPath, urlImgName, "-ascii-art.gif")
if err != nil {
- return "", err
+ return err
}
fullPathName, err := getFullSavePath(saveFileName, saveGifPath)
if err != nil {
- return "", fmt.Errorf("can't save file: %v", err)
+ return fmt.Errorf("can't save file: %v", err)
}
// Initializing some constants for gif. Done outside loop to save execution
@@ -219,7 +229,7 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
gifFile, err := os.OpenFile(fullPathName, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
- return "", fmt.Errorf("can't save file: %v", err)
+ return fmt.Errorf("can't save file: %v", err)
}
defer gifFile.Close()
@@ -248,5 +258,5 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
}
}
- return "", nil
+ return nil
}
diff --git a/aic_package/convert_image.go b/aic_package/convert_image.go
index 2331897..0576c7c 100644
--- a/aic_package/convert_image.go
+++ b/aic_package/convert_image.go
@@ -43,15 +43,24 @@ func pathIsImage(imagePath, urlImgName string, pathIsURl bool, urlImgBytes []byt
return "", fmt.Errorf("can't decode %v: %v", imagePath, err)
}
- imgSet, err := imgManip.ConvertToAsciiPixels(imData, dimensions, width, height, flipX, flipY, full)
+ imgSet, err := imgManip.ConvertToAsciiPixels(imData, dimensions, width, height, flipX, flipY, full, braille)
if err != nil {
return "", err
}
- asciiSet := imgManip.ConvertToAsciiChars(imgSet, negative, colored, complex, customMap, fontColor)
+ var asciiSet [][]imgManip.AsciiChar
+
+ if braille {
+ asciiSet = imgManip.ConvertToBrailleChars(imgSet, negative, colored, fontColor, threshold)
+ } else {
+ asciiSet = imgManip.ConvertToAsciiChars(imgSet, negative, colored, complex, customMap, fontColor)
+ }
// Save ascii art as .png image before printing it, if --save-img flag is passed
if saveImagePath != "" {
+ if braille {
+ return "", fmt.Errorf("saving braille art as an image is not supported")
+ }
if err := createImageToSave(
asciiSet,
colored || grayscale,
diff --git a/aic_package/convert_root.go b/aic_package/convert_root.go
index 47a7cc5..50e4511 100644
--- a/aic_package/convert_root.go
+++ b/aic_package/convert_root.go
@@ -57,6 +57,8 @@ func DefaultFlags() Flags {
FontFilePath: "",
FontColor: [3]int{255, 255, 255},
SaveBackgroundColor: [3]int{0, 0, 0},
+ Braille: false,
+ Threshold: 128,
}
}
@@ -88,6 +90,8 @@ func Convert(filePath string, flags Flags) (string, error) {
fontPath = flags.FontFilePath
fontColor = flags.FontColor
saveBgColor = flags.SaveBackgroundColor
+ braille = flags.Braille
+ threshold = flags.Threshold
// Declared at the start since some variables are initially used in conditional blocks
var (
@@ -141,7 +145,7 @@ func Convert(filePath string, flags Flags) (string, error) {
}
if path.Ext(filePath) == ".gif" {
- return pathIsGif(filePath, urlImgName, pathIsURl, urlImgBytes, localFile)
+ return "", pathIsGif(filePath, urlImgName, pathIsURl, urlImgBytes, localFile)
} else {
return pathIsImage(filePath, urlImgName, pathIsURl, urlImgBytes, localFile)
}
diff --git a/aic_package/util.go b/aic_package/util.go
index 9ceb79c..a71a712 100644
--- a/aic_package/util.go
+++ b/aic_package/util.go
@@ -79,24 +79,24 @@ func flattenAscii(asciiSet [][]imgManip.AsciiChar, colored, toSaveTxt bool) []st
var ascii []string
for _, line := range asciiSet {
- var tempAscii []string
+ var tempAscii string
- for i := 0; i < len(line); i++ {
+ for _, char := range line {
if toSaveTxt {
- tempAscii = append(tempAscii, line[i].Simple)
+ tempAscii += char.Simple
continue
}
if colored {
- tempAscii = append(tempAscii, line[i].OriginalColor)
+ tempAscii += char.OriginalColor
} else if fontColor != [3]int{255, 255, 255} {
- tempAscii = append(tempAscii, line[i].SetColor)
+ tempAscii += char.SetColor
} else {
- tempAscii = append(tempAscii, line[i].Simple)
+ tempAscii += char.Simple
}
}
- ascii = append(ascii, strings.Join(tempAscii, ""))
+ ascii = append(ascii, tempAscii)
}
return ascii
diff --git a/aic_package/vars.go b/aic_package/vars.go
index 02f1147..dd23220 100644
--- a/aic_package/vars.go
+++ b/aic_package/vars.go
@@ -74,13 +74,22 @@ type Flags struct {
// This will be ignored if Flags.SaveImagePath or Flags.SaveGifPath are not set
FontFilePath string
- // Font RGB color in saved png or gif files.
- // This will be ignored if Flags.SaveImagePath or Flags.SaveGifPath are not set
+ // Font RGB color for terminal display and saved png or gif files.
FontColor [3]int
// Background RGB color in saved png or gif files.
// This will be ignored if Flags.SaveImagePath or Flags.SaveGifPath are not set
SaveBackgroundColor [3]int
+
+ // Use braille characters instead of ascii. Terminal must support UTF-8 encoding.
+ // Otherwise, problems may be encountered with colored or even uncolored braille art.
+ // This overrides Flags.Complex and Flags.CustomMap
+ Braille bool
+
+ // Threshold for braille art if Flags.Braille is set to true. Value provided must
+ // be between 0 and 255. Ideal value is 128.
+ // This will be ignored if Flags.Braille is not set
+ Threshold int
}
var (
@@ -101,4 +110,6 @@ var (
fontPath string
fontColor [3]int
saveBgColor [3]int
+ braille bool
+ threshold int
)
diff --git a/cmd/root.go b/cmd/root.go
index dbb045d..a1142a7 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -48,12 +48,14 @@ var (
fontFile string
fontColor []int
saveBgColor []int
+ braille bool
+ threshold int
// Root commands
rootCmd = &cobra.Command{
Use: "ascii-image-converter [image paths/urls]",
Short: "Converts images and gifs into ascii art",
- Version: "1.6.0",
+ Version: "1.7.0",
Long: "This tool converts images into ascii art and prints them on the terminal.\nFurther configuration can be managed with flags.",
// Not RunE since help text is getting larger and seeing it for every error impacts user experience
@@ -81,6 +83,8 @@ var (
FontFilePath: fontFile,
FontColor: [3]int{fontColor[0], fontColor[1], fontColor[2]},
SaveBackgroundColor: [3]int{saveBgColor[0], saveBgColor[1], saveBgColor[2]},
+ Braille: braille,
+ Threshold: threshold,
}
for _, imagePath := range args {
@@ -119,12 +123,14 @@ func init() {
rootCmd.Flags().SortFlags = false
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.ascii-image-converter.yaml)")
- rootCmd.PersistentFlags().BoolVarP(&colored, "color", "C", false, "Display ascii art with original colors\n(Can work with the --negative flag)\n(Overrides --grayscale and --font-color flags)\n")
+ rootCmd.PersistentFlags().BoolVarP(&colored, "color", "C", false, "Display ascii art with original colors\n(Inverts with --negative flag)\n(Overrides --grayscale and --font-color flags)\n")
rootCmd.PersistentFlags().IntSliceVarP(&dimensions, "dimensions", "d", nil, "Set width and height for ascii art in CHARACTER length\ne.g. -d 60,30 (defaults to terminal height)\n(Overrides --width and --height flags)\n")
rootCmd.PersistentFlags().IntVarP(&width, "width", "W", 0, "Set width for ascii art in CHARACTER length\nHeight is kept to aspect ratio\ne.g. -W 60\n")
rootCmd.PersistentFlags().IntVarP(&height, "height", "H", 0, "Set height for ascii art in CHARACTER length\nWidth is kept to aspect ratio\ne.g. -H 60\n")
rootCmd.PersistentFlags().StringVarP(&customMap, "map", "m", "", "Give custom ascii characters to map against\nOrdered from darkest to lightest\ne.g. -m \" .-+#@\" (Quotation marks excluded from map)\n(Overrides --complex flag)\n")
- rootCmd.PersistentFlags().BoolVarP(&grayscale, "grayscale", "g", false, "Display grayscale ascii art\n(Can work with --negative flag)\n(Overrides --font-color flag)\n")
+ rootCmd.PersistentFlags().BoolVarP(&braille, "braille", "b", false, "Use braille characters instead of ascii\nTerminal must support braille patterns properly\n(Overrides --complex and --map flags)\n")
+ rootCmd.PersistentFlags().IntVar(&threshold, "threshold", 0, "Threshold for braille art\nValue between 0-255 is accepted\ne.g. --threshold 170\n(Defaults to 128)\n")
+ rootCmd.PersistentFlags().BoolVarP(&grayscale, "grayscale", "g", false, "Display grayscale ascii art\n(Inverts with --negative flag)\n(Overrides --font-color flag)\n")
rootCmd.PersistentFlags().BoolVarP(&complex, "complex", "c", false, "Display ascii characters in a larger range\nMay result in higher quality\n")
rootCmd.PersistentFlags().BoolVarP(&full, "full", "f", false, "Use largest dimensions for ascii art\nthat fill the terminal width\n(Overrides --dimensions, --width and --height flags)\n")
rootCmd.PersistentFlags().BoolVarP(&negative, "negative", "n", false, "Display ascii art in negative colors\n")
@@ -141,6 +147,8 @@ func init() {
rootCmd.PersistentFlags().BoolP("help", "h", false, "Help for "+rootCmd.Name()+"\n")
rootCmd.PersistentFlags().BoolP("version", "v", false, "Version for "+rootCmd.Name())
+ rootCmd.SetVersionTemplate("{{printf \"v%s\" .Version}}\n")
+
defaultUsageTemplate := rootCmd.UsageTemplate()
rootCmd.SetUsageTemplate(defaultUsageTemplate + "\nCopyright © 2021 Zoraiz Hassan \n" +
"Distributed under the Apache License Version 2.0 (Apache-2.0)\n" +
diff --git a/cmd/util.go b/cmd/util.go
index 99b7724..f532d29 100644
--- a/cmd/util.go
+++ b/cmd/util.go
@@ -57,7 +57,7 @@ func checkInputAndFlags(args []string) bool {
"WEBP\n" +
"BMP\n" +
"TIFF/TIF\n" +
- "GIF (Experimental)\n\n")
+ "GIF\n\n")
return true
}
@@ -171,5 +171,14 @@ func checkInputAndFlags(args []string) bool {
}
}
+ if threshold == 0 {
+ threshold = 128
+ }
+
+ if threshold < 0 || threshold > 255 {
+ fmt.Printf("Error: threshold must be between 0 and 255\n\n")
+ return true
+ }
+
return false
}
diff --git a/image_manipulation/ascii_conversions.go b/image_manipulation/ascii_conversions.go
index 9b66692..f8b2510 100644
--- a/image_manipulation/ascii_conversions.go
+++ b/image_manipulation/ascii_conversions.go
@@ -22,12 +22,24 @@ import (
"github.com/gookit/color"
)
-// Reference taken from http://paulbourke.net/dataformats/asciiart/
-var asciiTableSimple = " .:-=+*#%@"
-var asciiTableDetailed = " .'`^\",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"
+var (
+ // Reference taken from http://paulbourke.net/dataformats/asciiart/
+ asciiTableSimple = " .:-=+*#%@"
+ asciiTableDetailed = " .'`^\",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"
+
+ // Structure for braille dots
+ BrailleStruct = [4][2]int{
+ {0x1, 0x8},
+ {0x2, 0x10},
+ {0x4, 0x20},
+ {0x40, 0x80},
+ }
+
+ BrailleThreshold uint32
+)
// For each individual element of imgSet in ConvertToASCIISlice()
-const MAX_VAL float64 = 65535
+const MAX_VAL float64 = 255
type AsciiChar struct {
OriginalColor string
@@ -72,10 +84,7 @@ func ConvertToAsciiChars(imgSet [][]AsciiPixel, negative, colored, complex bool,
}
}
- result := make([][]AsciiChar, height)
- for i := range result {
- result[i] = make([]AsciiChar, width)
- }
+ var result [][]AsciiChar
for i := 0; i < height; i++ {
@@ -146,8 +155,111 @@ func ConvertToAsciiChars(imgSet [][]AsciiPixel, negative, colored, complex bool,
tempSlice = append(tempSlice, char)
}
- result[i] = tempSlice
+ result = append(result, tempSlice)
+ }
+
+ return result
+}
+
+/*
+Converts the 2D image_conversions.AsciiPixel slice of image data (each instance representing each compressed pixel of original image)
+to a 2D image_conversions.AsciiChar slice
+
+Unlike ConvertToAsciiChars(), this function calculates braille characters instead of ascii
+*/
+func ConvertToBrailleChars(imgSet [][]AsciiPixel, negative, colored bool, fontColor [3]int, threshold int) [][]AsciiChar {
+
+ BrailleThreshold = uint32(threshold)
+
+ height := len(imgSet)
+ width := len(imgSet[0])
+
+ var result [][]AsciiChar
+
+ for i := 0; i < height; i += 4 {
+
+ var tempSlice []AsciiChar
+
+ for j := 0; j < width; j += 2 {
+
+ brailleChar := getBrailleChar(i, j, negative, imgSet)
+
+ var r, g, b int
+
+ if colored {
+ r = int(imgSet[i][j].rgbValue[0])
+ g = int(imgSet[i][j].rgbValue[1])
+ b = int(imgSet[i][j].rgbValue[2])
+ } else {
+ r = int(imgSet[i][j].grayscaleValue[0])
+ g = int(imgSet[i][j].grayscaleValue[1])
+ b = int(imgSet[i][j].grayscaleValue[2])
+ }
+
+ if negative {
+ // Select character from opposite side of table as well as turn pixels negative
+ r = 255 - r
+ g = 255 - g
+ b = 255 - b
+
+ if colored {
+ imgSet[i][j].rgbValue = [3]uint32{uint32(r), uint32(g), uint32(b)}
+ } else {
+ imgSet[i][j].grayscaleValue = [3]uint32{uint32(r), uint32(g), uint32(b)}
+ }
+ }
+
+ rStr := strconv.Itoa(r)
+ gStr := strconv.Itoa(g)
+ bStr := strconv.Itoa(b)
+
+ var char AsciiChar
+
+ char.Simple = brailleChar
+ char.OriginalColor = color.Sprintf("%v>", brailleChar)
+
+ // If font color is not set, use a simple string. Otherwise, use True color
+ if fontColor != [3]int{255, 255, 255} {
+ fcR := strconv.Itoa(fontColor[0])
+ fcG := strconv.Itoa(fontColor[1])
+ fcB := strconv.Itoa(fontColor[2])
+
+ char.SetColor = color.Sprintf("%v>", brailleChar)
+ }
+
+ if colored {
+ char.RgbValue = imgSet[i][j].rgbValue
+ } else {
+ char.RgbValue = imgSet[i][j].grayscaleValue
+ }
+
+ tempSlice = append(tempSlice, char)
+ }
+
+ result = append(result, tempSlice)
}
return result
}
+
+// Iterate through the BrailleStruct table to see which dots need to be highlighted
+func getBrailleChar(x, y int, negative bool, imgSet [][]AsciiPixel) string {
+
+ brailleChar := 0x2800
+
+ for i := 0; i < 4; i++ {
+ for j := 0; j < 2; j++ {
+ if negative {
+ if imgSet[x+i][y+j].charDepth <= BrailleThreshold {
+ brailleChar += BrailleStruct[i][j]
+ }
+ } else {
+ if imgSet[x+i][y+j].charDepth >= BrailleThreshold {
+ brailleChar += BrailleStruct[i][j]
+ }
+ }
+ }
+ }
+
+ return string(brailleChar)
+}
diff --git a/image_manipulation/image_conversions.go b/image_manipulation/image_conversions.go
index 93bcb08..93ae277 100644
--- a/image_manipulation/image_conversions.go
+++ b/image_manipulation/image_conversions.go
@@ -31,6 +31,10 @@ type AsciiPixel struct {
rgbValue [3]uint32
}
+func resizeForBraille(asciiWidth, asciiHeight int) (int, int) {
+ return asciiWidth * 2, asciiHeight * 4
+}
+
/*
This function shrinks the passed image according to passed dimensions or terminal
size if none are passed. Stores each pixel's grayscale and RGB values in an AsciiPixel
@@ -39,7 +43,7 @@ instance to simplify getting numeric data for ASCII character comparison.
The returned 2D AsciiPixel slice contains each corresponding pixel's values. Grayscale value
ranges from 0 to 65535, while RGB values are separate.
*/
-func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int, flipX, flipY, full bool) ([][]AsciiPixel, error) {
+func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int, flipX, flipY, full, isBraille bool) ([][]AsciiPixel, error) {
var asciiWidth, asciiHeight int
var smallImg image.Image
@@ -57,8 +61,11 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int,
asciiHeight = smallImg.Bounds().Max.Y - smallImg.Bounds().Min.Y
// To fix aspect ratio in eventual ascii art
- asciiHeight = int(0.5 * float32(asciiHeight))
+ asciiHeight = int(0.5 * float64(asciiHeight))
+ if isBraille {
+ asciiWidth, asciiHeight = resizeForBraille(asciiWidth, asciiHeight)
+ }
smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos)
} else if (width != 0 || height != 0) && len(dimensions) == 0 {
@@ -76,13 +83,11 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int,
smallImg = imaging.Resize(img, asciiWidth, 0, imaging.Lanczos)
asciiHeight = smallImg.Bounds().Max.Y - smallImg.Bounds().Min.Y
- asciiHeight = int(0.5 * float32(asciiHeight))
+ asciiHeight = int(0.5 * float64(asciiHeight))
if asciiHeight == 0 {
asciiHeight = 1
}
- smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos)
-
} else if height != 0 && width == 0 {
// If height is set and width is not set, use height to calculate aspect ratio
@@ -91,18 +96,21 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int,
smallImg = imaging.Resize(img, 0, asciiHeight, imaging.Lanczos)
asciiWidth = smallImg.Bounds().Max.X - smallImg.Bounds().Min.X
- asciiWidth = int(2 * float32(asciiWidth))
+ asciiWidth = int(2 * float64(asciiWidth))
if asciiWidth > terminalWidth-1 {
return nil, fmt.Errorf("width calculated with aspect ratio exceeds terminal width")
}
- smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos)
-
} else {
return nil, fmt.Errorf("both width and height can't be set. Use dimensions instead")
}
+ if isBraille {
+ asciiWidth, asciiHeight = resizeForBraille(asciiWidth, asciiHeight)
+ }
+ smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos)
+
} else if len(dimensions) == 0 {
// This condition calculates aspect ratio according to terminal height
@@ -112,7 +120,7 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int,
asciiWidth = smallImg.Bounds().Max.X - smallImg.Bounds().Min.X
// To fix aspect ratio in eventual ascii art
- asciiWidth = int(2 * float32(asciiWidth))
+ asciiWidth = int(2 * float64(asciiWidth))
// If ascii width exceeds terminal width, change ratio with respect to terminal width
if asciiWidth >= terminalWidth {
@@ -123,14 +131,21 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int,
asciiHeight = smallImg.Bounds().Max.Y - smallImg.Bounds().Min.Y
// To fix aspect ratio in eventual ascii art
- asciiHeight = int(0.5 * float32(asciiHeight))
+ asciiHeight = int(0.5 * float64(asciiHeight))
}
+ if isBraille {
+ asciiWidth, asciiHeight = resizeForBraille(asciiWidth, asciiHeight)
+ }
smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos)
} else {
asciiWidth = dimensions[0]
asciiHeight = dimensions[1]
+
+ if isBraille {
+ asciiWidth, asciiHeight = resizeForBraille(asciiWidth, asciiHeight)
+ }
smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos)
}
@@ -143,11 +158,7 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int,
}
}
- // Initialize imgSet 2D slice
- imgSet := make([][]AsciiPixel, asciiHeight)
- for i := range imgSet {
- imgSet[i] = make([]AsciiPixel, asciiWidth)
- }
+ var imgSet [][]AsciiPixel
b := smallImg.Bounds()
@@ -161,7 +172,7 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int,
grayPixel := color.GrayModel.Convert(oldPixel)
r1, g1, b1, _ := grayPixel.RGBA()
- charDepth := r1 // Only Red is needed from RGB for charDepth in AsciiPixel since they have the same value for grayscale images
+ charDepth := r1 / 257 // Only Red is needed from RGB for charDepth in AsciiPixel since they have the same value for grayscale images
r1 = uint32(r1 / 257)
g1 = uint32(g1 / 257)
b1 = uint32(b1 / 257)
@@ -179,7 +190,7 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int,
})
}
- imgSet[y] = temp
+ imgSet = append(imgSet, temp)
}
// This rarely affects performance since the ascii art 2D slice size isn't that large
diff --git a/snapcraft.yaml b/snapcraft.yaml
index 72df5f9..3669361 100644
--- a/snapcraft.yaml
+++ b/snapcraft.yaml
@@ -1,6 +1,6 @@
name: ascii-image-converter
base: core18
-version: "1.6.0"
+version: "1.7.0"
summary: Convert images and gifs into ascii art
description: |
ascii-image-converter is a command-line tool that converts images into ascii art and prints