Library update
This commit is contained in:
parent
de35b19962
commit
178c48fbe1
31
README.md
31
README.md
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 (
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
||||||
49
cmd/root.go
49
cmd/root.go
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue