Set default image ratio to terminal height, included --map flag, improved help text

This commit is contained in:
Zoraiz
2021-05-27 14:42:50 +05:00
parent f022070c20
commit b09a5540d9
7 changed files with 155 additions and 92 deletions

View File

@@ -28,7 +28,7 @@ archives:
format: zip
files:
- LICENSE
- LICENSE.txt
replacements:
linux: Linux

123
README.md
View File

@@ -1,38 +1,36 @@
# ascii-image-converter
ascii-image-converter is a command-line tool that converts images into ascii art and prints them out onto the console. It is cross-platform so both Windows and Linux distributions are supported
ascii-image-converter is a command-line tool that converts images into ascii art and prints them out onto the console. It is cross-platform so both Windows and Linux distributions are supported.
Image formats currently supported:
* JPEG/JPG
* PNG
* WEBP
* BMP
* WEBP
* TIFF/TIF
## Table of Contents
- [Example](#example-source)
- [Installation](#installation)
* [Snap](#snap)
* [Go](#go)
* [Linux (binaries)](#linux)
* [Windows (binaries)](#windows)
- [Usage](#usage)
* [Flags](#flags)
- [Contributing](#contributing)
- [Packages used](#packages-used)
- [License](#license)
- [Example](#example-source)
- [Installation](#installation)
* [Snap](#snap)
* [Go](#go)
* [Linux (binaries)](#linux)
* [Windows (binaries)](#windows)
- [Usage](#usage)
* [Flags](#flags)
- [Contributing](#contributing)
- [Packages used](#packages-used)
- [License](#license)
### Example ([Source](https://medium.com/@sean.glancy/practical-applications-of-binary-trees-3097cf663062)):
![Example](https://raw.githubusercontent.com/TheZoraiz/ascii-image-converter/master/example_images/tree.png)
### ASCII Art:
![Example](https://raw.githubusercontent.com/TheZoraiz/ascii-image-converter/master/example_images/ascii_tree.png)
## Installation
### Snap
@@ -40,12 +38,14 @@ Image formats currently supported:
You can download through snap. However, the snap will not have access to hidden images and images outside the $HOME directory.
```
sudo snap install ascii-image-converter --stable
sudo snap install ascii-image-converter
```
Visit [the app's snap store listing](https://snapcraft.io/ascii-image-converter) for instructions regarding enabling snapd on your distribution.
<hr>
### Go
For installing through Go
```
go install github.com/TheZoraiz/ascii-image-converter@latest
@@ -54,7 +54,8 @@ go install github.com/TheZoraiz/ascii-image-converter@latest
For physically installing the binaries, follow the steps with respect to your OS.
### Linux
Extract the archive for your chosen Linux architecture after downloading it from [here](https://github.com/TheZoraiz/ascii-image-converter/releases/latest), and open the extracted directory.
Download the archive for your distribution's architecture [here](https://github.com/TheZoraiz/ascii-image-converter/releases/latest), extract it, and open the extracted directory.
Now, open a terminal in the same directory and execute this command:
@@ -67,7 +68,7 @@ Now you can use ascii-image-converter in the terminal. Execute "ascii-image-conv
You will need to set an Environment Variable to the folder the ascii-image-converter.exe executable is placed in to be able to use it in the command prompt. Follow the instructions in case of confusion:
Extract the archive for the your chosen Windows architecture after downloading it from [here](https://github.com/TheZoraiz/ascii-image-converter/releases/latest). Open the newly created folder and copy the path to it from the top of the file explorer.
Download the archive for your Windows architecture [here](https://github.com/TheZoraiz/ascii-image-converter/releases/latest), extract it, and open the extracted folder.
* In Search, search for and then select: System (Control Panel)
* Click the Advanced System settings link.
* Click Environment Variables. In the section User Variables find the Path environment variable and select it. Click "Edit".
@@ -82,77 +83,105 @@ Now, restart any open command prompt and execute "ascii-image-converter -h" for
Note: Decrease font size or increase terminal width (like zooming out) for maximum quality ascii art
To convert an image into ascii format, the usage is as follows:
The basic usage for converting an image into ascii art is as follows. You can also supply paths to multiple images.
```
ascii-image-converter [path to image]
ascii-image-converter [image-paths]
```
Example
Example:
```
ascii-image-converter myImage.jpeg
```
### Flags
#### --complex OR -c
Print the image with a wider array of ascii characters. Sometimes improves accuracy.
#### --color OR -C
Display ascii art with the colors from original image. Works with the --negative flag as well.
```
ascii-image-converter [path to image] -c
ascii-image-converter [image-paths] -C
# Or
ascii-image-converter [path to image] --complex
ascii-image-converter [image-paths] --color
```
#### --complex OR -c
Print the image with a wider array of ascii characters for more detailed lighting density. Sometimes improves accuracy.
```
ascii-image-converter [image-paths] -c
# Or
ascii-image-converter [image-paths] --complex
```
#### --dimensions OR -d
Set the width and height for ascii art in CHARACTER lengths. (Don't immediately append another flag with -d)
Note: Don't immediately append another flag with -d
Set the width and height for ascii art in CHARACTER lengths.
```
ascii-image-converter [path to image] -d <width>,<height>
ascii-image-converter [image-paths] -d <width>,<height>
# Or
ascii-image-converter [path to image] --dimensions <width>,<height>
ascii-image-converter [image-paths] --dimensions <width>,<height>
```
Example:
```
ascii-image-converter [path to image] -d 100,30
ascii-image-converter [image-paths] -d 100,30
```
#### --color OR -C
Display ascii art with the colors from original image. Works with the -n flag as well.
#### --map OR -m
Note: Don't immediately append another flag with -m
Pass a string of your own ascii characters to map against. Passed characters must start from darkest character and end with lightest. There is no limit to number of characters.
Notes: Empty spaces can be passed if string is passed inside quotation marks. You can use both single or double quote for quotation marks. For repeating quotation mark inside string, append it with \ (such as \\").
```
ascii-image-converter [path to image] -C
ascii-image-converter [image-paths] -m "<string-of-characters>"
# Or
ascii-image-converter [path to image] --color
ascii-image-converter [image-paths] --map "<string-of-characters>"
```
Following example contains 7 depths of lighting.
```
ascii-image-converter [image-paths] -m " .-=+#@"
```
#### --negative OR -n
Display ascii art in negative colors. Works with both uncolored and colored text from -C flag.
Display ascii art in negative colors. Works with both uncolored and colored text from --color flag.
```
ascii-image-converter [path to image] -n
ascii-image-converter [image-paths] -n
# Or
ascii-image-converter [path to image] --negative
ascii-image-converter [image-paths] --negative
```
#### --save OR -s
Save the printed ascii art in a file ascii-image.txt in the directory passed alongside. (Don't immediately append another flag with -s)
Save ascii art in the format `<image-name>-<image-extension>-ascii-art.txt` in the directory path passed to the flag.
Example for current directory:
```
ascii-image-converter [path to image] --save ./
ascii-image-converter [image-paths] --save .
# Or
ascii-image-converter [path to image] -s ./
ascii-image-converter [image-paths] -s .
```
#### --formats OR -f
Display supported image formats.
```
ascii-image-converter [path to image] --formats
ascii-image-converter [image-paths] --formats
# Or
ascii-image-converter [path to image] -f
ascii-image-converter [image-paths] -f
```
<br>
You can combine flags as well. Following command outputs colored and negative ascii art, with fixed 100 by 30 character dimensions, custom defined ascii characters " .-=+#@" and saves the output in current directory as well.
You can combine flags as well. Following command outputs colored and negative ascii art, with complex characters, fixed 100 by 30 character dimensions and saves the output in current directory as well.
```
ascii-image-converter [path to image] -Ccnd 100,30 -s ./
ascii-image-converter [image-paths] -Cnd 100,30 -m " .-=+#@" -s ./
```
<br>
@@ -175,6 +204,6 @@ You can fork the project and implement any changes you want for a pull request.
[github.com/gookit/color](https://github.com/gookit/color)
## License
[Apache-2.0](https://github.com/TheZoraiz/ascii-image-converter/blob/master/LICENSE)
[Apache-2.0](https://github.com/TheZoraiz/ascii-image-converter/blob/master/LICENSE)

View File

@@ -49,15 +49,14 @@ var (
negative bool
formatsTrue bool
colored bool
customMap string
// Root commands
rootCmd = &cobra.Command{
Use: "ascii-image-converter [image path]",
Use: "ascii-image-converter [image-paths]",
Short: "Converts images into ascii format",
Version: "1.2.3",
Example: " ascii-image-converter myImage.jpeg\n\n" +
"For further details, visit https://github.com/TheZoraiz/ascii-image-converter",
Long: `This tool converts images into ascii format and prints them onto the terminal window. Further configuration can be managed with flags`,
Version: "1.2.4",
Long: "This tool converts images into ascii art and prints them on the terminal.\nFurther configuration can be managed with flags.",
RunE: func(cmd *cobra.Command, args []string) error {
if formatsTrue {
@@ -65,18 +64,26 @@ var (
return nil
}
if len(args) != 1 {
return fmt.Errorf("Requires 1 image path, got %v", len(args))
}
numberOfDimensions := len(dimensions)
if dimensions != nil && numberOfDimensions != 2 {
return fmt.Errorf("-d requires 2 dimensions, got %v", numberOfDimensions)
}
imagePath := args[0]
if len(args) < 1 {
return fmt.Errorf("Need at least 1 image path")
}
return convertImage(imagePath)
if len(customMap) < 2 && customMap != "" {
fmt.Println("Need at least 2 characters")
os.Exit(0)
}
for _, imagePath := range args {
if err := convertImage(imagePath); err != nil {
return err
}
}
return nil
},
}
)
@@ -93,22 +100,25 @@ func convertImage(imagePath string) error {
pic, err := os.Open(imagePath)
if err != nil {
return fmt.Errorf("Unable to open file: %w", err)
fmt.Printf("Unable to open file: %v\n", err)
os.Exit(0)
}
defer pic.Close()
imData, _, err := image.Decode(pic)
if err != nil {
return fmt.Errorf("Unable to decode file: %w", err)
fmt.Printf("Error decoding file: %v\n", err)
os.Exit(0)
}
imgSet, err := imgMani.ConvertToAsciiPixels(imData, dimensions)
if err != nil {
return err
fmt.Printf("Error: %v\n", err)
os.Exit(0)
}
var asciiSet [][]imgMani.AsciiChar
asciiSet = imgMani.ConvertToAscii(imgSet, negative, colored, compl)
asciiSet = imgMani.ConvertToAscii(imgSet, negative, colored, compl, customMap)
var ascii []string
ascii = flattenAscii(asciiSet, colored)
@@ -116,7 +126,8 @@ func convertImage(imagePath string) error {
// Save art before printing it, if flag is passed
if savePath != "" {
if err := saveAsciiArt(asciiSet, imagePath); err != nil {
return err
fmt.Printf("Error: %v\n", err)
os.Exit(0)
}
}
@@ -153,7 +164,7 @@ func saveAsciiArt(asciiSet [][]imgMani.AsciiChar, imagePath string) error {
if _, err := os.Stat(savePath); !os.IsNotExist(err) {
return ioutil.WriteFile(savePath+saveFileName, []byte(strings.Join(saveAscii, "\n")), 0777)
} else {
return fmt.Errorf("Path does not exist.")
return fmt.Errorf("Save path does not exist.")
}
}
@@ -201,13 +212,19 @@ func init() {
cobra.OnInitialize(initConfig)
// 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 the colors from original image (Can work with the -n flag)")
rootCmd.PersistentFlags().BoolVarP(&compl, "complex", "c", false, "Display ascii characters in a larger range, may result in higher quality")
rootCmd.PersistentFlags().IntSliceVarP(&dimensions, "dimensions", "d", nil, "Set width and height for ascii art in CHARACTER length e.g. 100,30 (defaults to terminal size)")
rootCmd.PersistentFlags().BoolVarP(&formatsTrue, "formats", "f", false, "Display supported image formats")
rootCmd.PersistentFlags().BoolVarP(&negative, "negative", "n", false, "Display ascii art in negative colors (Can work with the -C flag)")
rootCmd.PersistentFlags().StringVarP(&savePath, "save", "s", "", "Save ascii art in an <image-name>-<image-extension>-ascii-art.txt file in a given path (pass . for current directory)")
rootCmd.PersistentFlags().BoolVarP(&colored, "color", "C", false, "Display ascii art with the colors from original image\n(Can work with the -n flag)\n")
rootCmd.PersistentFlags().BoolVarP(&compl, "complex", "c", false, "Display ascii characters in a larger range\nMay result in higher quality\n")
rootCmd.PersistentFlags().IntSliceVarP(&dimensions, "dimensions", "d", nil, "Set width and height for ascii art in CHARACTER length\ne.g. -d 100,30 (defaults to terminal height)\n")
rootCmd.PersistentFlags().BoolVarP(&formatsTrue, "formats", "f", false, "Display supported image formats\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(Cancels --complex flag)\n")
rootCmd.PersistentFlags().BoolVarP(&negative, "negative", "n", false, "Display ascii art in negative colors\n(Can work with the --color flag)\n")
rootCmd.PersistentFlags().StringVarP(&savePath, "save", "s", "", "Save ascii art in the format:\n<image-name>-<image-extension>-ascii-art.txt\nFile will be saved in passed path\n(pass . for current directory)\n")
defaultUsageTemplate := rootCmd.UsageTemplate()
rootCmd.SetUsageTemplate("\nCopyright © 2021 Zoraiz Hassan <hzoraiz8@gmail.com>\n" +
"Distributed under the Apache License Version 2.0 (Apache-2.0)\n" +
"For further details, visit https://github.com/TheZoraiz/ascii-image-converter\n\n" +
defaultUsageTemplate)
}
// initConfig reads in config file and ENV variables if set.

View File

@@ -123,16 +123,24 @@ type AsciiChar struct {
//
// If complex parameter is true, values are compared to 69 levels of color density in ASCII characters.
// Otherwise, values are compared to 10 levels of color density in ASCII characters.
func ConvertToAscii(imgSet [][]AsciiPixel, negative bool, colored bool, complex bool) [][]AsciiChar {
func ConvertToAscii(imgSet [][]AsciiPixel, negative bool, colored bool, complex bool, customMap string) [][]AsciiChar {
height := len(imgSet)
width := len(imgSet[0])
var chosenTable map[int]string
if complex {
chosenTable = asciiTableDetailed
if customMap == "" {
if complex {
chosenTable = asciiTableDetailed
} else {
chosenTable = asciiTableSimple
}
} else {
chosenTable = asciiTableSimple
chosenTable = map[int]string{}
for index, char := range customMap {
chosenTable[index] = string(char)
}
}
result := make([][]AsciiChar, height)

View File

@@ -38,31 +38,40 @@ type AsciiPixel struct {
// ranges from 0 to 65535, while RGB values are separate.
func ConvertToAsciiPixels(img image.Image, dimensions []int) ([][]AsciiPixel, error) {
var terminalWidth, terminalHeight int
var asciiWidth, asciiHeight int
var smallImg image.Image
// Get dimensions of current terminal
if len(dimensions) == 0 {
terminalWidth, _ = consolesize.GetConsoleSize()
// Following code in this condition calculates ratio according to terminal height
// Sometimes full length outputs print empty lines between ascii art
terminalWidth -= 1
terminalWidth, terminalHeight := consolesize.GetConsoleSize()
asciiHeight = terminalHeight - 1
// Passing 0 in place of height keeps the original image's aspect ratio
smallImg = resize.Resize(uint(terminalWidth), 0, img, resize.Lanczos3)
terminalHeight = smallImg.Bounds().Max.Y - smallImg.Bounds().Min.Y
// Passing 0 in place of width keeps the original image's aspect ratio
smallImg = resize.Resize(0, uint(asciiHeight), img, resize.Lanczos3)
asciiWidth = smallImg.Bounds().Max.X - smallImg.Bounds().Min.X
// To fix height ratio in eventual ascii art
terminalHeight = int(0.5 * float32(terminalHeight))
// To fix aspect ratio in eventual ascii art
asciiWidth = int(2 * float32(asciiWidth))
smallImg = resize.Resize(uint(terminalWidth), uint(terminalHeight), img, resize.Lanczos3)
// If ascii width exceeds terminal width, change ratio with respect to terminal width
if asciiWidth > terminalWidth {
smallImg = resize.Resize(uint(terminalWidth), 0, img, resize.Lanczos3)
asciiWidth = terminalWidth
asciiHeight = smallImg.Bounds().Max.Y - smallImg.Bounds().Min.Y
// To fix aspect ratio in eventual ascii art
asciiHeight = int(0.5 * float32(asciiHeight))
}
smallImg = resize.Resize(uint(asciiWidth), uint(asciiHeight), img, resize.Lanczos3)
} else {
terminalWidth = dimensions[0]
terminalHeight = dimensions[1]
smallImg = resize.Resize(uint(terminalWidth), uint(terminalHeight), img, resize.Lanczos3)
asciiWidth = dimensions[0]
asciiHeight = dimensions[1]
smallImg = resize.Resize(uint(asciiWidth), uint(asciiHeight), img, resize.Lanczos3)
}
// If there are passed dimensions, check whether the width exceeds terminal width
@@ -75,9 +84,9 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int) ([][]AsciiPixel, er
}
// Initialize imgSet 2D slice
imgSet := make([][]AsciiPixel, terminalHeight)
imgSet := make([][]AsciiPixel, asciiHeight)
for i := range imgSet {
imgSet[i] = make([]AsciiPixel, terminalWidth)
imgSet[i] = make([]AsciiPixel, asciiWidth)
}
b := smallImg.Bounds()

View File

@@ -1,6 +1,6 @@
name: ascii-image-converter
base: core18
version: "1.2.3"
version: "1.2.4"
summary: Converts images into ascii format
description: |
This tool converts images into ascii format and prints them onto the terminal window.