Library update

This commit is contained in:
Zoraiz 2021-09-10 00:34:08 +05:00
parent de35b19962
commit 178c48fbe1
9 changed files with 172 additions and 83 deletions

View File

@ -425,14 +425,14 @@ ascii-image-converter --formats
## Library Usage ## Library Usage
> **Note:** The library may throw errors during Go tests due to some unresolved bugs with the [consolesize-go](https://github.com/nathan-fiscaletti/consolesize-go) package (Only during tests, not main program execution). Furthermore, GIF conversion is not advised as it isn't fully library-compatible yet. > **Note:** The library may throw errors during Go tests due to some unresolved bugs with the [consolesize-go](https://github.com/nathan-fiscaletti/consolesize-go) package (Only during tests, not main program execution).
First, install the library with: First, install the library with:
``` ```
go get -u github.com/TheZoraiz/ascii-image-converter/aic_package go get -u github.com/TheZoraiz/ascii-image-converter/aic_package
``` ```
The library is to be used as follows: For an image:
```go ```go
package main package main
@ -460,6 +460,10 @@ func main() {
flags.FontFilePath = "./RobotoMono-Regular.ttf" // If file is in current directory flags.FontFilePath = "./RobotoMono-Regular.ttf" // If file is in current directory
flags.SaveBackgroundColor = [3]int{50, 50, 50} flags.SaveBackgroundColor = [3]int{50, 50, 50}
// This MUST be set to true for environments where a terminal isn't available (such as web servers)
// However, for this, one of flags.Width, flags.Height or flags.Dimensions must be set.
flags.NoTermSizeComparison = true
// Conversion for an image // Conversion for an image
asciiArt, err := aic_package.Convert(filePath, flags) asciiArt, err := aic_package.Convert(filePath, flags)
if err != nil { if err != nil {
@ -467,19 +471,34 @@ func main() {
} }
fmt.Printf("%v\n", asciiArt) fmt.Printf("%v\n", asciiArt)
}
```
<br>
// ----- > **Note:** GIF conversion is not advised as the function may run infinitely, depending on the GIF. More work needs to be done on this to make it more library-compatible.
// GIF CONVERSION IS AN EXPERIMENTAL FEATURE
// For a gif. This function may run infinitely, depending on the gif
// Work needs to be done on gif conversion to be more library-compatible
For a GIF:
```go
package main
import (
"fmt"
"github.com/TheZoraiz/ascii-image-converter/aic_package"
)
func main() {
filePath = "myGif.gif" filePath = "myGif.gif"
flags := aic_package.DefaultFlags()
_, err := aic_package.Convert(filePath, flags) _, err := aic_package.Convert(filePath, flags)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
} }
``` ```
<br> <br>

View File

@ -97,7 +97,7 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
var imgSet [][]imgManip.AsciiPixel var imgSet [][]imgManip.AsciiPixel
imgSet, err = imgManip.ConvertToAsciiPixels(frameImage, dimensions, width, height, flipX, flipY, full, braille, dither) imgSet, err = imgManip.ConvertToAsciiPixels(frameImage, dimensions, width, height, flipX, flipY, full, braille, dither, noTermSizeComparison)
if err != nil { if err != nil {
fmt.Println("Error:", err) fmt.Println("Error:", err)
os.Exit(0) os.Exit(0)

View File

@ -43,7 +43,7 @@ func pathIsImage(imagePath, urlImgName string, pathIsURl bool, urlImgBytes []byt
return "", fmt.Errorf("can't decode %v: %v", imagePath, err) return "", fmt.Errorf("can't decode %v: %v", imagePath, err)
} }
imgSet, err := imgManip.ConvertToAsciiPixels(imData, dimensions, width, height, flipX, flipY, full, braille, dither) imgSet, err := imgManip.ConvertToAsciiPixels(imData, dimensions, width, height, flipX, flipY, full, braille, dither, noTermSizeComparison)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -40,27 +40,28 @@ import (
// Can be sent directly to ConvertImage() for default ascii art // Can be sent directly to ConvertImage() for default ascii art
func DefaultFlags() Flags { func DefaultFlags() Flags {
return Flags{ return Flags{
Complex: false, Complex: false,
Dimensions: nil, Dimensions: nil,
Width: 0, Width: 0,
Height: 0, Height: 0,
SaveTxtPath: "", SaveTxtPath: "",
SaveImagePath: "", SaveImagePath: "",
SaveGifPath: "", SaveGifPath: "",
Negative: false, Negative: false,
Colored: false, Colored: false,
CharBackgroundColor: false, CharBackgroundColor: false,
Grayscale: false, Grayscale: false,
CustomMap: "", CustomMap: "",
FlipX: false, FlipX: false,
FlipY: false, FlipY: false,
Full: false, Full: false,
FontFilePath: "", FontFilePath: "",
FontColor: [3]int{255, 255, 255}, FontColor: [3]int{255, 255, 255},
SaveBackgroundColor: [3]int{0, 0, 0}, SaveBackgroundColor: [3]int{0, 0, 0},
Braille: false, Braille: false,
Threshold: 128, Threshold: 128,
Dither: false, Dither: false,
NoTermSizeComparison: false,
} }
} }
@ -96,6 +97,7 @@ func Convert(filePath string, flags Flags) (string, error) {
braille = flags.Braille braille = flags.Braille
threshold = flags.Threshold threshold = flags.Threshold
dither = flags.Dither dither = flags.Dither
noTermSizeComparison = flags.NoTermSizeComparison
// Declared at the start since some variables are initially used in conditional blocks // Declared at the start since some variables are initially used in conditional blocks
var ( var (

View File

@ -98,28 +98,37 @@ type Flags struct {
// Apply FloydSteinberg dithering on an image before ascii conversion. This option // Apply FloydSteinberg dithering on an image before ascii conversion. This option
// is meant for braille art. Therefore, it will be ignored if Flags.Braille is false // is meant for braille art. Therefore, it will be ignored if Flags.Braille is false
Dither bool Dither bool
// Set this to true to disable comparing ascii art size to terminal. However, at least
// one of Flags.Width, Flags.Height or Flags.Dimensions should be passed to keep it from
// throwing an error.
//
// Note: This option is added for using the library in an environment without terminals (such as web servers).
// Furthermore, coloring options will not work outside of a terminal environment.
NoTermSizeComparison bool
} }
var ( var (
dimensions []int dimensions []int
width int width int
height int height int
complex bool complex bool
saveTxtPath string saveTxtPath string
saveImagePath string saveImagePath string
saveGifPath string saveGifPath string
grayscale bool grayscale bool
negative bool negative bool
colored bool colored bool
colorBg bool colorBg bool
customMap string customMap string
flipX bool flipX bool
flipY bool flipY bool
full bool full bool
fontPath string fontPath string
fontColor [3]int fontColor [3]int
saveBgColor [3]int saveBgColor [3]int
braille bool braille bool
threshold int threshold int
dither bool dither bool
noTermSizeComparison bool
) )

View File

@ -57,7 +57,7 @@ var (
rootCmd = &cobra.Command{ rootCmd = &cobra.Command{
Use: "ascii-image-converter [image paths/urls]", Use: "ascii-image-converter [image paths/urls]",
Short: "Converts images and gifs into ascii art", Short: "Converts images and gifs into ascii art",
Version: "1.9.0", Version: "1.9.1",
Long: "This tool converts images into ascii art and prints them on the terminal.\nFurther configuration can be managed with flags.", 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 // Not RunE since help text is getting larger and seeing it for every error impacts user experience
@ -68,27 +68,28 @@ var (
} }
flags := aic_package.Flags{ flags := aic_package.Flags{
Complex: complex, Complex: complex,
Dimensions: dimensions, Dimensions: dimensions,
Width: width, Width: width,
Height: height, Height: height,
SaveTxtPath: saveTxtPath, SaveTxtPath: saveTxtPath,
SaveImagePath: saveImagePath, SaveImagePath: saveImagePath,
SaveGifPath: saveGifPath, SaveGifPath: saveGifPath,
Negative: negative, Negative: negative,
Colored: colored, Colored: colored,
CharBackgroundColor: colorBg, CharBackgroundColor: colorBg,
Grayscale: grayscale, Grayscale: grayscale,
CustomMap: customMap, CustomMap: customMap,
FlipX: flipX, FlipX: flipX,
FlipY: flipY, FlipY: flipY,
Full: full, Full: full,
FontFilePath: fontFile, FontFilePath: fontFile,
FontColor: [3]int{fontColor[0], fontColor[1], fontColor[2]}, FontColor: [3]int{fontColor[0], fontColor[1], fontColor[2]},
SaveBackgroundColor: [3]int{saveBgColor[0], saveBgColor[1], saveBgColor[2]}, SaveBackgroundColor: [3]int{saveBgColor[0], saveBgColor[1], saveBgColor[2]},
Braille: braille, Braille: braille,
Threshold: threshold, Threshold: threshold,
Dither: dither, Dither: dither,
NoTermSizeComparison: false,
} }
for _, imagePath := range args { for _, imagePath := range args {
@ -145,8 +146,8 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&saveImagePath, "save-img", "s", "", "Save ascii art as a .png file\nFormat: <image-name>-ascii-art.png\nImage will be saved in passed path\n(pass . for current directory)\n") rootCmd.PersistentFlags().StringVarP(&saveImagePath, "save-img", "s", "", "Save ascii art as a .png file\nFormat: <image-name>-ascii-art.png\nImage will be saved in passed path\n(pass . for current directory)\n")
rootCmd.PersistentFlags().StringVar(&saveTxtPath, "save-txt", "", "Save ascii art as a .txt file\nFormat: <image-name>-ascii-art.txt\nFile will be saved in passed path\n(pass . for current directory)\n") rootCmd.PersistentFlags().StringVar(&saveTxtPath, "save-txt", "", "Save ascii art as a .txt file\nFormat: <image-name>-ascii-art.txt\nFile will be saved in passed path\n(pass . for current directory)\n")
rootCmd.PersistentFlags().StringVar(&saveGifPath, "save-gif", "", "If input is a gif, save it as a .gif file\nFormat: <gif-name>-ascii-art.gif\nGif will be saved in passed path\n(pass . for current directory)\n") rootCmd.PersistentFlags().StringVar(&saveGifPath, "save-gif", "", "If input is a gif, save it as a .gif file\nFormat: <gif-name>-ascii-art.gif\nGif will be saved in passed path\n(pass . for current directory)\n")
rootCmd.PersistentFlags().IntSliceVar(&saveBgColor, "save-bg", nil, "Set background color for --save-img and --save-gif flags\nPass an RGB value\ne.g. --save-bg 255,255,255\n(Defaults to 0,0,0)\n") rootCmd.PersistentFlags().IntSliceVar(&saveBgColor, "save-bg", nil, "Set background color for --save-img\nand --save-gif flags\nPass an RGB value\ne.g. --save-bg 255,255,255\n(Defaults to 0,0,0)\n")
rootCmd.PersistentFlags().StringVar(&fontFile, "font", "", "Set font for --save-img and --save-gif flags\nPass file path to font .ttf file\ne.g. --font ./RobotoMono-Regular.ttf\n(Defaults to Hack-Regular)\n") rootCmd.PersistentFlags().StringVar(&fontFile, "font", "", "Set font for --save-img and --save-gif flags\nPass file path to font .ttf file\ne.g. --font ./RobotoMono-Regular.ttf\n(Defaults to Hack-Regular for ascii and\n DejaVuSans-Oblique for braille)\n")
rootCmd.PersistentFlags().IntSliceVar(&fontColor, "font-color", nil, "Set font color for terminal as well as\n--save-img and --save-gif flags\nPass an RGB value\ne.g. --font-color 0,0,0\n(Defaults to 255,255,255)\n") rootCmd.PersistentFlags().IntSliceVar(&fontColor, "font-color", nil, "Set font color for terminal as well as\n--save-img and --save-gif flags\nPass an RGB value\ne.g. --font-color 0,0,0\n(Defaults to 255,255,255)\n")
rootCmd.PersistentFlags().BoolVar(&formatsTrue, "formats", false, "Display supported input formats\n") rootCmd.PersistentFlags().BoolVar(&formatsTrue, "formats", false, "Display supported input formats\n")

View File

@ -34,9 +34,16 @@ getting numeric data for ASCII character comparison.
The returned 2D AsciiPixel slice contains each corresponding pixel's values The returned 2D AsciiPixel slice contains each corresponding pixel's values
*/ */
func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int, flipX, flipY, full, isBraille, dither bool) ([][]AsciiPixel, error) { func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int, flipX, flipY, full, isBraille, dither, noTermSizeComparison bool) ([][]AsciiPixel, error) {
smallImg, err := resizeImage(img, full, isBraille, dimensions, width, height) var smallImg image.Image
var err error
if noTermSizeComparison {
smallImg, err = resizeImageNoTerm(img, isBraille, dimensions, width, height)
} else {
smallImg, err = resizeImage(img, full, isBraille, dimensions, width, height)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -26,10 +26,6 @@ import (
"github.com/makeworld-the-better-one/dither/v2" "github.com/makeworld-the-better-one/dither/v2"
) )
func resizeForBraille(asciiWidth, asciiHeight int) (int, int) {
return asciiWidth * 2, asciiHeight * 4
}
func ditherImage(img image.Image) image.Image { func ditherImage(img image.Image) image.Image {
palette := []color.Color{ palette := []color.Color{
@ -87,6 +83,10 @@ func resizeImage(img image.Image, full, isBraille bool, dimensions []int, width,
asciiWidth = int(float64(asciiHeight) * aspectRatio) asciiWidth = int(float64(asciiHeight) * aspectRatio)
asciiWidth = int(2 * float64(asciiWidth)) asciiWidth = int(2 * float64(asciiWidth))
if asciiWidth == 0 {
asciiWidth = 1
}
if asciiWidth > terminalWidth-1 { if asciiWidth > terminalWidth-1 {
return nil, fmt.Errorf("width calculated with aspect ratio exceeds terminal width") return nil, fmt.Errorf("width calculated with aspect ratio exceeds terminal width")
} }
@ -124,7 +124,58 @@ func resizeImage(img image.Image, full, isBraille bool, dimensions []int, width,
} }
if isBraille { if isBraille {
asciiWidth, asciiHeight = resizeForBraille(asciiWidth, asciiHeight) asciiWidth *= 2
asciiHeight *= 4
}
smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos)
return smallImg, nil
}
func resizeImageNoTerm(img image.Image, isBraille bool, dimensions []int, width, height int) (image.Image, error) {
var asciiWidth, asciiHeight int
var smallImg image.Image
imgWidth := float64(img.Bounds().Dx())
imgHeight := float64(img.Bounds().Dy())
aspectRatio := imgWidth / imgHeight
if (width != 0 || height != 0) && len(dimensions) == 0 {
if width != 0 && height == 0 {
asciiWidth = width
asciiHeight = int(float64(asciiWidth) / aspectRatio)
asciiHeight = int(0.5 * float64(asciiHeight))
if asciiHeight == 0 {
asciiHeight = 1
}
} else if height != 0 && width == 0 {
asciiHeight = height
asciiWidth = int(float64(asciiHeight) * aspectRatio)
asciiWidth = int(2 * float64(asciiWidth))
if asciiWidth == 0 {
asciiWidth = 1
}
} else {
return nil, fmt.Errorf("error: both width and height can't be set. Use dimensions instead")
}
} else if len(dimensions) != 0 {
asciiWidth = dimensions[0]
asciiHeight = dimensions[1]
} else {
return nil, fmt.Errorf("error: at least one of width, height or dimensions should be passed for NoTermSizeComparison")
}
if isBraille {
asciiWidth *= 2
asciiHeight *= 4
} }
smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos) smallImg = imaging.Resize(img, asciiWidth, asciiHeight, imaging.Lanczos)

View File

@ -1,10 +1,10 @@
name: ascii-image-converter name: ascii-image-converter
base: core18 base: core18
version: "1.9.0" version: "1.9.1"
summary: Convert images and gifs into ascii art summary: Convert images and gifs into ascii art
description: | description: |
ascii-image-converter is a command-line tool that converts images into ascii art and prints ascii-image-converter is a command-line tool that converts images into ascii art and prints
them out onto the console. Supported input formats are JPEG/JPG, PNG, WEBP, BMP, TIFF/TIF and GIF them out onto the console. Supported input formats are JPEG/JPG, PNG, WEBP, BMP, TIFF/TIF and GIF.
Now supports braille art. Now supports braille art.
grade: stable grade: stable