Added flip flags and made package available as a library
This commit is contained in:
parent
8c537074aa
commit
f3c90d36b7
|
|
@ -37,7 +37,7 @@ archives:
|
|||
amd64: amd64_64bit
|
||||
arm64: arm64_64bit
|
||||
386: i386_32bit
|
||||
arm: arm32_32bit
|
||||
arm: arm_32bit
|
||||
|
||||
checksum:
|
||||
name_template: 'sha256_checksums.txt'
|
||||
|
|
|
|||
79
README.md
79
README.md
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
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.
|
||||
|
||||
It's also available as a package to be used in Go applications.
|
||||
|
||||
Image formats currently supported:
|
||||
* JPEG/JPG
|
||||
* PNG
|
||||
|
|
@ -18,8 +20,9 @@ Image formats currently supported:
|
|||
* [Go](#go)
|
||||
* [Linux (binaries)](#linux)
|
||||
* [Windows (binaries)](#windows)
|
||||
- [Usage](#usage)
|
||||
- [CLI Usage](#cli-usage)
|
||||
* [Flags](#flags)
|
||||
- [Library Usage](#library-usage)
|
||||
- [Contributing](#contributing)
|
||||
- [Packages used](#packages-used)
|
||||
- [License](#license)
|
||||
|
|
@ -72,7 +75,7 @@ Now, restart any open command prompt and execute "ascii-image-converter -h" for
|
|||
|
||||
<br>
|
||||
|
||||
## Usage
|
||||
## CLI Usage
|
||||
|
||||
Note: Decrease font size or increase terminal width (like zooming out) for maximum quality ascii art
|
||||
|
||||
|
|
@ -211,12 +214,84 @@ ascii-image-converter [image paths/urls] --formats
|
|||
ascii-image-converter [image paths/urls] -f
|
||||
```
|
||||
|
||||
#### --flipX OR -x
|
||||
|
||||
Flip the ascii art horizontally on the terminal.
|
||||
|
||||
```
|
||||
ascii-image-converter [image paths/urls] --flipX
|
||||
# Or
|
||||
ascii-image-converter [image paths/urls] -x
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/TheZoraiz/ascii-image-converter/master/example_gifs/flipx.gif">
|
||||
</p>
|
||||
|
||||
#### --flipY OR -y
|
||||
Flip the ascii art vertically on the terminal.
|
||||
|
||||
```
|
||||
ascii-image-converter [image paths/urls] --flipY
|
||||
# Or
|
||||
ascii-image-converter [image paths/urls] -y
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/TheZoraiz/ascii-image-converter/master/example_gifs/flipy.gif">
|
||||
</p>
|
||||
|
||||
<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.
|
||||
|
||||
```
|
||||
ascii-image-converter [image paths/urls] -Cnd 100,30 -m " .-=+#@" -s ./
|
||||
```
|
||||
<br>
|
||||
|
||||
## Library Usage
|
||||
|
||||
First import the library with:
|
||||
```
|
||||
go get github.com/TheZoraiz/ascii-image-converter/aic_package
|
||||
```
|
||||
|
||||
The library is to be used as follows:
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TheZoraiz/ascii-image-converter/aic_package"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// If image is in current directory. This can also be a URL to an image.
|
||||
imagePath := "myImage.jpeg"
|
||||
|
||||
flags := aic_package.DefaultFlags()
|
||||
|
||||
// This part is optional. You can directly pass flags variable to ConvertImage() if you wish.
|
||||
// For clarity, all flags are covered in this example.
|
||||
flags["complex"] = true // Use complex character set
|
||||
flags["dimensions"] = []int{50, 25} // 50 by 25 ascii art size
|
||||
flags["savePath"] = "." // Saves to current directory
|
||||
flags["negative"] = true // Ascii art will have negative color-depth
|
||||
flags["colored"] = true // Keep colors from original image
|
||||
flags["customMap"] = " .-=+#@" // Starting from darkest to brightest shades. This overrites "complex" flag
|
||||
flags["flipX"] = true // Flips ascii art horizontally
|
||||
flags["flipY"] = true // Flips ascii art vertically
|
||||
|
||||
// Return ascii art as a single string
|
||||
asciiArt, err := aic_package.ConvertImage(imagePath, flags)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%v\n", asciiArt)
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
Copyright © 2021 Zoraiz Hassan <hzoraiz8@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package aic_package
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
// Image format initialization
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
|
||||
// Image format initialization
|
||||
_ "golang.org/x/image/bmp"
|
||||
_ "golang.org/x/image/tiff"
|
||||
_ "golang.org/x/image/webp"
|
||||
|
||||
imgManip "github.com/TheZoraiz/ascii-image-converter/image_manipulation"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
)
|
||||
|
||||
// Return default configuration for flags
|
||||
func DefaultFlags() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"complex": false,
|
||||
"dimensions": nil,
|
||||
"savePath": "",
|
||||
"negative": false,
|
||||
"colored": false,
|
||||
"customMap": "",
|
||||
"flipX": false,
|
||||
"flipY": false,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ConvertImage takes an image path/url as its first argument
|
||||
and a map of flags as the second argument, with which it alters
|
||||
the returned ascii art string.
|
||||
|
||||
The "flags" argument should be declared as follows before passing:
|
||||
|
||||
flags := map[string]interface{}{
|
||||
"complex": bool, // Pass true for using complex character set
|
||||
"dimensions": []int, // Pass 2 integer dimensions. Pass nil to ignore
|
||||
"savePath": string, // System path to save the ascii art string. Pass "" to ignore
|
||||
"negative": bool, // Pass true for negative color-depth ascii art
|
||||
"colored": bool, // Pass true for returning colored ascii string
|
||||
"customMap": string, // Custom map of ascii chars e.g. " .-+#@" . Nullifies "complex" flag. Pass "" to ignore.
|
||||
"flipX": bool, // Pass true to return horizontally flipped ascii art
|
||||
"flipY": bool, // Pass true to return vertically flipped ascii art
|
||||
}
|
||||
*/
|
||||
func ConvertImage(imagePath string, flags map[string]interface{}) (string, error) {
|
||||
|
||||
complex := flags["complex"].(bool)
|
||||
var dimensions []int
|
||||
if flags["dimensions"] == nil {
|
||||
dimensions = nil
|
||||
} else {
|
||||
dimensions = flags["dimensions"].([]int)
|
||||
}
|
||||
savePath := flags["savePath"].(string)
|
||||
negative := flags["negative"].(bool)
|
||||
colored := flags["colored"].(bool)
|
||||
customMap := flags["customMap"].(string)
|
||||
flipX := flags["flipX"].(bool)
|
||||
flipY := flags["flipY"].(bool)
|
||||
|
||||
numberOfDimensions := len(dimensions)
|
||||
if dimensions != nil && numberOfDimensions != 2 {
|
||||
return "", fmt.Errorf("requires 2 dimensions, got %v", numberOfDimensions)
|
||||
}
|
||||
|
||||
// Declared at the start since some variables are initially used in conditional blocks
|
||||
var (
|
||||
pic *os.File
|
||||
urlImgBytes []byte
|
||||
urlImgName string = ""
|
||||
err error
|
||||
)
|
||||
|
||||
pathIsURl := govalidator.IsRequestURL(imagePath)
|
||||
|
||||
// Different modes of reading data depending upon whether or not imagePath is a url
|
||||
if pathIsURl {
|
||||
fmt.Printf("Fetching image from url...\r")
|
||||
|
||||
retrievedImage, err := http.Get(imagePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can't fetching image: %v", err)
|
||||
}
|
||||
|
||||
urlImgBytes, err = ioutil.ReadAll(retrievedImage.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read fetched content: %v", err)
|
||||
}
|
||||
defer retrievedImage.Body.Close()
|
||||
|
||||
urlImgName = path.Base(imagePath)
|
||||
fmt.Printf(" \r") // To erase "Fetching image from url..." text from console
|
||||
} else {
|
||||
pic, err = os.Open(imagePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to open file: %v", err)
|
||||
}
|
||||
defer pic.Close()
|
||||
}
|
||||
|
||||
var imData image.Image
|
||||
|
||||
if pathIsURl {
|
||||
imData, _, err = image.Decode(bytes.NewReader(urlImgBytes))
|
||||
} else {
|
||||
imData, _, err = image.Decode(pic)
|
||||
}
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error decoding %v. %v", imagePath, err)
|
||||
}
|
||||
|
||||
imgSet, err := imgManip.ConvertToAsciiPixels(imData, dimensions, flipX, flipY)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%v", err)
|
||||
}
|
||||
|
||||
asciiSet := imgManip.ConvertToAscii(imgSet, negative, colored, complex, customMap)
|
||||
|
||||
ascii := flattenAscii(asciiSet, colored)
|
||||
|
||||
// Save ascii art before printing it, if --save flag is passed
|
||||
if savePath != "" {
|
||||
if err := saveAsciiArt(asciiSet, imagePath, savePath, urlImgName); err != nil {
|
||||
fmt.Printf("Error: %v\n\n", err)
|
||||
os.Exit(0) // Because this error will be thrown for every image passed to this function if we use "return"
|
||||
}
|
||||
}
|
||||
|
||||
result := strings.Join(ascii, "\n")
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func checkOS() string {
|
||||
if string(os.PathSeparator) == "/" && string(os.PathListSeparator) == ":" {
|
||||
return "linux"
|
||||
} else {
|
||||
return "windows"
|
||||
}
|
||||
}
|
||||
|
||||
// flattenAscii flattens a two-dimensional grid of ascii characters into a one dimension
|
||||
// of lines of ascii
|
||||
func flattenAscii(asciiSet [][]imgManip.AsciiChar, color bool) []string {
|
||||
var ascii []string
|
||||
|
||||
for _, line := range asciiSet {
|
||||
var tempAscii []string
|
||||
|
||||
for i := 0; i < len(line); i++ {
|
||||
if color {
|
||||
tempAscii = append(tempAscii, line[i].Colored)
|
||||
} else {
|
||||
tempAscii = append(tempAscii, line[i].Simple)
|
||||
}
|
||||
}
|
||||
|
||||
ascii = append(ascii, strings.Join(tempAscii, ""))
|
||||
}
|
||||
|
||||
return ascii
|
||||
}
|
||||
|
||||
func saveAsciiArt(asciiSet [][]imgManip.AsciiChar, imagePath, savePath, urlImgName string) error {
|
||||
// To make sure uncolored ascii art is the one saved
|
||||
saveAscii := flattenAscii(asciiSet, false)
|
||||
|
||||
saveFileName, err := createSaveFileName(imagePath, urlImgName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
savePathLastChar := string(savePath[len(savePath)-1])
|
||||
|
||||
// Check if path is closed with appropriate path separator (depending on OS)
|
||||
if savePathLastChar != string(os.PathSeparator) {
|
||||
if checkOS() == "linux" {
|
||||
savePath += "/"
|
||||
} else {
|
||||
savePath += "\\"
|
||||
}
|
||||
}
|
||||
|
||||
// If path exists
|
||||
if _, err := os.Stat(savePath); !os.IsNotExist(err) {
|
||||
return ioutil.WriteFile(savePath+saveFileName, []byte(strings.Join(saveAscii, "\n")), 0666)
|
||||
} else {
|
||||
return fmt.Errorf("save path %v does exist", savePath)
|
||||
}
|
||||
}
|
||||
|
||||
func createSaveFileName(imagePath string, urlImgName string) (string, error) {
|
||||
if urlImgName != "" {
|
||||
return urlImgName + "-ascii-art.txt", nil
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(imagePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
currName := fileInfo.Name()
|
||||
currExt := path.Ext(currName)
|
||||
newName := currName[:len(currName)-len(currExt)] // e.g. Grabs myImage from myImage.jpeg
|
||||
|
||||
// Something like myImage.jpeg-ascii-art.txt
|
||||
return newName + "." + currExt[1:] + "-ascii-art.txt", nil
|
||||
}
|
||||
197
cmd/root.go
197
cmd/root.go
|
|
@ -16,14 +16,10 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/TheZoraiz/ascii-image-converter/aic_package"
|
||||
|
||||
// Image format initialization
|
||||
_ "image/jpeg"
|
||||
|
|
@ -34,8 +30,6 @@ import (
|
|||
_ "golang.org/x/image/tiff"
|
||||
_ "golang.org/x/image/webp"
|
||||
|
||||
imgMani "github.com/TheZoraiz/ascii-image-converter/image_manipulation"
|
||||
"github.com/asaskevich/govalidator"
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
|
@ -44,19 +38,21 @@ import (
|
|||
var (
|
||||
// Flags
|
||||
cfgFile string
|
||||
compl bool
|
||||
complex bool
|
||||
dimensions []int
|
||||
savePath string
|
||||
negative bool
|
||||
formatsTrue bool
|
||||
colored bool
|
||||
customMap string
|
||||
flipX bool
|
||||
flipY bool
|
||||
|
||||
// Root commands
|
||||
rootCmd = &cobra.Command{
|
||||
Use: "ascii-image-converter [image paths/urls]",
|
||||
Short: "Converts images into ascii art",
|
||||
Version: "1.2.5",
|
||||
Version: "1.2.6",
|
||||
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
|
||||
|
|
@ -67,12 +63,6 @@ var (
|
|||
return
|
||||
}
|
||||
|
||||
numberOfDimensions := len(dimensions)
|
||||
if dimensions != nil && numberOfDimensions != 2 {
|
||||
fmt.Printf("-d requires 2 dimensions, got %v\n\n", numberOfDimensions)
|
||||
return
|
||||
}
|
||||
|
||||
if len(args) < 1 {
|
||||
fmt.Printf("Error: Need at least 1 image path/url\n\n")
|
||||
cmd.Help()
|
||||
|
|
@ -84,162 +74,33 @@ var (
|
|||
return
|
||||
}
|
||||
|
||||
flags := map[string]interface{}{
|
||||
"complex": complex,
|
||||
"dimensions": dimensions,
|
||||
"savePath": savePath,
|
||||
"negative": negative,
|
||||
"colored": colored,
|
||||
"customMap": customMap,
|
||||
"flipX": flipX,
|
||||
"flipY": flipY,
|
||||
}
|
||||
|
||||
// fmt.Println(flags)
|
||||
|
||||
for _, imagePath := range args {
|
||||
convertImage(imagePath)
|
||||
|
||||
if asciiArt, err := aic_package.ConvertImage(imagePath, flags); err == nil {
|
||||
fmt.Printf("%s", asciiArt)
|
||||
} else {
|
||||
fmt.Printf("Error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func checkOS() string {
|
||||
if string(os.PathSeparator) == "/" && string(os.PathListSeparator) == ":" {
|
||||
return "linux"
|
||||
} else {
|
||||
return "windows"
|
||||
}
|
||||
}
|
||||
|
||||
func convertImage(imagePath string) {
|
||||
|
||||
// Declared at the start since some variables are initially used in conditional blocks
|
||||
var pic *os.File
|
||||
var urlImgBytes []byte
|
||||
var urlImgName string = ""
|
||||
var err error
|
||||
|
||||
pathIsURl := govalidator.IsRequestURL(imagePath)
|
||||
|
||||
// Different modes of reading data depending upon whether or not imagePath is a url
|
||||
if pathIsURl {
|
||||
fmt.Printf("Fetching image from url...\r")
|
||||
|
||||
retrievedImage, err := http.Get(imagePath)
|
||||
if err != nil {
|
||||
fmt.Printf("Error fetching image: %v\n\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
urlImgBytes, err = ioutil.ReadAll(retrievedImage.Body)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to read fetched content: %v\n\n", err)
|
||||
return
|
||||
}
|
||||
defer retrievedImage.Body.Close()
|
||||
|
||||
urlImgName = path.Base(imagePath)
|
||||
fmt.Printf(" \r") // To erase "Fetching image from url..." text from console
|
||||
} else {
|
||||
pic, err = os.Open(imagePath)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to open file: %v\n\n", err)
|
||||
return
|
||||
}
|
||||
defer pic.Close()
|
||||
}
|
||||
|
||||
var imData image.Image
|
||||
|
||||
if pathIsURl {
|
||||
imData, _, err = image.Decode(bytes.NewReader(urlImgBytes))
|
||||
} else {
|
||||
imData, _, err = image.Decode(pic)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Printf("Error decoding %v. %v\n\n", imagePath, err)
|
||||
return
|
||||
}
|
||||
|
||||
imgSet, err := imgMani.ConvertToAsciiPixels(imData, dimensions)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
asciiSet := imgMani.ConvertToAscii(imgSet, negative, colored, compl, customMap)
|
||||
|
||||
ascii := flattenAscii(asciiSet, colored)
|
||||
|
||||
// Save ascii art before printing it, if --save flag is passed
|
||||
if savePath != "" {
|
||||
if err := saveAsciiArt(asciiSet, imagePath, urlImgName); err != nil {
|
||||
fmt.Printf("Error: %v\n\n", err)
|
||||
os.Exit(0) // Because this error will be thrown for every image passed to this function if we use "return"
|
||||
}
|
||||
}
|
||||
|
||||
for _, line := range ascii {
|
||||
fmt.Println(line)
|
||||
}
|
||||
}
|
||||
|
||||
// flattenAscii flattens a two-dimensional grid of ascii characters into a one dimension
|
||||
// of lines of ascii
|
||||
func flattenAscii(asciiSet [][]imgMani.AsciiChar, color bool) []string {
|
||||
var ascii []string
|
||||
|
||||
for _, line := range asciiSet {
|
||||
var tempAscii []string
|
||||
|
||||
for i := 0; i < len(line); i++ {
|
||||
if color {
|
||||
tempAscii = append(tempAscii, line[i].Colored)
|
||||
} else {
|
||||
tempAscii = append(tempAscii, line[i].Simple)
|
||||
}
|
||||
}
|
||||
|
||||
ascii = append(ascii, strings.Join(tempAscii, ""))
|
||||
}
|
||||
|
||||
return ascii
|
||||
}
|
||||
|
||||
func saveAsciiArt(asciiSet [][]imgMani.AsciiChar, imagePath string, urlImgName string) error {
|
||||
// To make sure uncolored ascii art is the one saved
|
||||
saveAscii := flattenAscii(asciiSet, false)
|
||||
|
||||
saveFileName, err := createSaveFileName(imagePath, urlImgName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
savePathLastChar := string(savePath[len(savePath)-1])
|
||||
|
||||
// Check if path is closed with appropriate path separator (depending on OS)
|
||||
if savePathLastChar != string(os.PathSeparator) {
|
||||
if checkOS() == "linux" {
|
||||
savePath += "/"
|
||||
} else {
|
||||
savePath += "\\"
|
||||
}
|
||||
}
|
||||
|
||||
// If path exists
|
||||
if _, err := os.Stat(savePath); !os.IsNotExist(err) {
|
||||
return ioutil.WriteFile(savePath+saveFileName, []byte(strings.Join(saveAscii, "\n")), 0666)
|
||||
} else {
|
||||
return fmt.Errorf("Save path does not exist.")
|
||||
}
|
||||
}
|
||||
|
||||
func createSaveFileName(imagePath string, urlImgName string) (string, error) {
|
||||
if urlImgName != "" {
|
||||
return urlImgName + "-ascii-art.txt", nil
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(imagePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
currName := fileInfo.Name()
|
||||
currExt := path.Ext(currName)
|
||||
newName := currName[:len(currName)-len(currExt)] // e.g. Grabs myImage from myImage.jpeg
|
||||
|
||||
// Something like myImage.jpeg-ascii-art.txt
|
||||
return newName + "." + currExt[1:] + "-ascii-art.txt", nil
|
||||
}
|
||||
|
||||
// Cobra configuration from here on
|
||||
|
||||
func Execute() {
|
||||
|
|
@ -254,12 +115,14 @@ func init() {
|
|||
|
||||
// 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\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().BoolVarP(&complex, "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")
|
||||
rootCmd.PersistentFlags().BoolVarP(&flipX, "flipX", "x", false, "Flip ascii art horizontally\n")
|
||||
rootCmd.PersistentFlags().BoolVarP(&flipY, "flipY", "y", false, "Flip ascii art vertically\n")
|
||||
|
||||
defaultUsageTemplate := rootCmd.UsageTemplate()
|
||||
rootCmd.SetUsageTemplate("\nCopyright © 2021 Zoraiz Hassan <hzoraiz8@gmail.com>\n" +
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 354 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 349 KiB |
|
|
@ -36,7 +36,7 @@ type AsciiPixel struct {
|
|||
//
|
||||
// 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) ([][]AsciiPixel, error) {
|
||||
func ConvertToAsciiPixels(img image.Image, dimensions []int, flipX, flipY bool) ([][]AsciiPixel, error) {
|
||||
|
||||
var asciiWidth, asciiHeight int
|
||||
var smallImg image.Image
|
||||
|
|
@ -79,7 +79,7 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int) ([][]AsciiPixel, er
|
|||
defaultTermWidth, _ := consolesize.GetConsoleSize()
|
||||
defaultTermWidth -= 1
|
||||
if dimensions[0] > defaultTermWidth {
|
||||
return nil, fmt.Errorf("Set width is larger than terminal width")
|
||||
return nil, fmt.Errorf("set width is larger than terminal width")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,5 +118,29 @@ func ConvertToAsciiPixels(img image.Image, dimensions []int) ([][]AsciiPixel, er
|
|||
imgSet[y] = temp
|
||||
}
|
||||
|
||||
// This rarely affects performance since the ascii art 2D slice size isn't that large
|
||||
if flipX || flipY {
|
||||
imgSet = reverse(imgSet, flipX, flipY)
|
||||
}
|
||||
|
||||
return imgSet, nil
|
||||
}
|
||||
|
||||
func reverse(imgSet [][]AsciiPixel, flipX, flipY bool) [][]AsciiPixel {
|
||||
|
||||
if flipX {
|
||||
for _, row := range imgSet {
|
||||
for i, j := 0, len(row)-1; i < j; i, j = i+1, j-1 {
|
||||
row[i], row[j] = row[j], row[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if flipY {
|
||||
for i, j := 0, len(imgSet)-1; i < j; i, j = i+1, j-1 {
|
||||
imgSet[i], imgSet[j] = imgSet[j], imgSet[i]
|
||||
}
|
||||
}
|
||||
|
||||
return imgSet
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
name: ascii-image-converter
|
||||
base: core18
|
||||
version: "1.2.5"
|
||||
version: "1.2.6"
|
||||
summary: Converts images into ascii art
|
||||
description: |
|
||||
This tool converts images into ascii format and prints them onto the terminal window.
|
||||
|
|
|
|||
Loading…
Reference in New Issue