Added --only-save and patch for #14

This commit is contained in:
Zoraiz Hassan 2021-10-06 15:32:35 +05:00
parent 39918a97fb
commit f31ac047ea
13 changed files with 161 additions and 215 deletions

View File

@ -415,6 +415,14 @@ This flag takes an RGB value that sets the font color in saved png and gif files
ascii-image-converter [image paths/urls] -s . --font-color 0,0,0 # For black font color
```
#### --only-save
Don't print ascii art on the terminal if some saving flag is passed.
```
ascii-image-converter [image paths/urls] -s . --only-save
```
#### --formats
Display supported input formats.
@ -462,9 +470,8 @@ func main() {
flags.FontFilePath = "./RobotoMono-Regular.ttf" // If file is in current directory
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
// Note: For environments where a terminal isn't available (such as web servers), you MUST
// specify atleast one of flags.Width, flags.Height or flags.Dimensions
// Conversion for an image
asciiArt, err := aic_package.Convert(filePath, flags)

View File

@ -91,13 +91,17 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
// If a frame is found that is smaller than the first frame, then this gif contains smaller subimages that are
// positioned inside the original gif. This behavior isn't supported by this app
if firstGifFrameWidth != frameImage.Bounds().Dx() || firstGifFrameHeight != frameImage.Bounds().Dy() {
fmt.Printf("Error: GIF contains subimages smaller than default width and height\nProcess aborted because ascii-image-converter doesn't support subimage placement and transparency in GIFs\n\n")
if urlImgName == "" {
fmt.Printf("Error: " + gifPath + " contains subimages smaller than default width and height\n\nProcess aborted because ascii-image-converter doesn't support subimage placement and transparency in GIFs\n\n")
} else {
fmt.Printf("Error: " + urlImgName + " contains subimages smaller than default width and height\n\nProcess aborted because ascii-image-converter doesn't support subimage placement and transparency in GIFs\n\n")
}
os.Exit(0)
}
var imgSet [][]imgManip.AsciiPixel
imgSet, err = imgManip.ConvertToAsciiPixels(frameImage, dimensions, width, height, flipX, flipY, full, braille, dither, noTermSizeComparison)
imgSet, err = imgManip.ConvertToAsciiPixels(frameImage, dimensions, width, height, flipX, flipY, full, braille, dither)
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(0)
@ -236,9 +240,12 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
gif.EncodeAll(gifFile, outGif)
fmt.Printf(" \r")
fmt.Println("Saved " + fullPathName)
}
// Display the gif
if !onlySave {
loopCount := 0
for {
for i, asciiFrame := range asciiArtSet {
@ -257,6 +264,7 @@ func pathIsGif(gifPath, urlImgName string, pathIsURl bool, urlImgBytes []byte, l
break
}
}
}
return nil
}

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)
}
imgSet, err := imgManip.ConvertToAsciiPixels(imData, dimensions, width, height, flipX, flipY, full, braille, dither, noTermSizeComparison)
imgSet, err := imgManip.ConvertToAsciiPixels(imData, dimensions, width, height, flipX, flipY, full, braille, dither)
if err != nil {
return "", err
}
@ -67,6 +67,7 @@ func pathIsImage(imagePath, urlImgName string, pathIsURl bool, urlImgBytes []byt
saveImagePath,
imagePath,
urlImgName,
onlySave,
); err != nil {
return "", fmt.Errorf("can't save file: %v", err)
@ -80,6 +81,7 @@ func pathIsImage(imagePath, urlImgName string, pathIsURl bool, urlImgBytes []byt
imagePath,
saveTxtPath,
urlImgName,
onlySave,
); err != nil {
return "", fmt.Errorf("can't save file: %v", err)
@ -89,5 +91,8 @@ func pathIsImage(imagePath, urlImgName string, pathIsURl bool, urlImgBytes []byt
ascii := flattenAscii(asciiSet, colored || grayscale, false)
result := strings.Join(ascii, "\n")
if onlySave {
return "", nil
}
return result, nil
}

View File

@ -60,7 +60,7 @@ func DefaultFlags() Flags {
Braille: false,
Threshold: 128,
Dither: false,
NoTermSizeComparison: false,
OnlySave: false,
}
}
@ -96,7 +96,7 @@ func Convert(filePath string, flags Flags) (string, error) {
braille = flags.Braille
threshold = flags.Threshold
dither = flags.Dither
noTermSizeComparison = flags.NoTermSizeComparison
onlySave = flags.OnlySave
// Declared at the start since some variables are initially used in conditional blocks
var (

View File

@ -17,6 +17,7 @@ limitations under the License.
package aic_package
import (
"fmt"
"image"
"image/color"
@ -48,7 +49,7 @@ images will considerably decrease ascii art quality because of smaller font size
Size of resulting image may also be considerably larger than original image.
*/
func createImageToSave(asciiArt [][]imgManip.AsciiChar, colored bool, saveImagePath, imagePath, urlImgName string) error {
func createImageToSave(asciiArt [][]imgManip.AsciiChar, colored bool, saveImagePath, imagePath, urlImgName string, onlySave bool) error {
constant := 14.0
@ -138,5 +139,9 @@ func createImageToSave(asciiArt [][]imgManip.AsciiChar, colored bool, saveImageP
return err
}
if onlySave {
fmt.Println("Saved " + fullPathName)
}
return dc.SavePNG(fullPathName)
}

View File

@ -28,7 +28,7 @@ import (
imgManip "github.com/TheZoraiz/ascii-image-converter/image_manipulation"
)
func saveAsciiArt(asciiSet [][]imgManip.AsciiChar, imagePath, savePath, urlImgName string) error {
func saveAsciiArt(asciiSet [][]imgManip.AsciiChar, imagePath, savePath, urlImgName string, onlySave bool) error {
// To make sure uncolored ascii art is the one saved as .txt
saveAscii := flattenAscii(asciiSet, false, true)
@ -46,7 +46,13 @@ func saveAsciiArt(asciiSet [][]imgManip.AsciiChar, imagePath, savePath, urlImgNa
// If path exists
if _, err := os.Stat(savePath); !os.IsNotExist(err) {
return ioutil.WriteFile(savePath+saveFileName, []byte(strings.Join(saveAscii, "\n")), 0666)
err := ioutil.WriteFile(savePath+saveFileName, []byte(strings.Join(saveAscii, "\n")), 0666)
if err != nil {
return err
} else if onlySave {
fmt.Println("Saved " + savePath + saveFileName)
}
return nil
} else {
return fmt.Errorf("save path %v does not exist", savePath)
}

View File

@ -99,13 +99,9 @@ type Flags struct {
// is meant for braille art. Therefore, it will be ignored if Flags.Braille is false
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
// If Flags.SaveImagePath, Flags.SaveTxtPath or Flags.SaveGifPath are set, then don't
// print on terminal
OnlySave bool
}
var (
@ -130,5 +126,5 @@ var (
braille bool
threshold int
dither bool
noTermSizeComparison bool
onlySave bool
)

View File

@ -52,12 +52,13 @@ var (
braille bool
threshold int
dither bool
onlySave bool
// Root commands
rootCmd = &cobra.Command{
Use: "ascii-image-converter [image paths/urls]",
Short: "Converts images and gifs into ascii art",
Version: "1.10.0",
Version: "1.11.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
@ -89,7 +90,7 @@ var (
Braille: braille,
Threshold: threshold,
Dither: dither,
NoTermSizeComparison: false,
OnlySave: onlySave,
}
for _, imagePath := range args {
@ -106,8 +107,10 @@ var (
return
}
}
if !onlySave {
fmt.Println()
}
}
},
}
)
@ -149,6 +152,7 @@ func init() {
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 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().BoolVar(&onlySave, "only-save", false, "Don't print ascii art on terminal\nif some saving flag is passed\n")
rootCmd.PersistentFlags().BoolVar(&formatsTrue, "formats", false, "Display supported input formats\n")
rootCmd.PersistentFlags().BoolP("help", "h", false, "Help for "+rootCmd.Name()+"\n")

View File

@ -19,8 +19,6 @@ package cmd
import (
"fmt"
"path"
"github.com/TheZoraiz/ascii-image-converter/aic_package/winsize"
)
// Check input and flag values for detecting errors or invalid inputs
@ -40,12 +38,12 @@ func checkInputAndFlags(args []string) bool {
}
}
if gifPresent && nonGifPresent {
if gifPresent && nonGifPresent && !onlySave {
fmt.Printf("Error: There are other inputs along with GIFs\nDue to the potential looping nature of GIFs, non-GIFs must not be supplied alongside\n\n")
return true
}
if gifCount > 1 {
if gifCount > 1 && !onlySave {
fmt.Printf("Error: There are multiple GIFs supplied\nDue to the potential looping nature of GIFs, only one GIF per command is supported\n\n")
return true
}
@ -83,18 +81,6 @@ func checkInputAndFlags(args []string) bool {
fmt.Printf("Error: invalid values for dimensions\n\n")
return true
}
defaultTermWidth, _, err := winsize.GetTerminalSize()
if err != nil {
fmt.Printf("Error: %v\n\n", err)
return true
}
defaultTermWidth -= 1
if dimensions[0] > defaultTermWidth {
fmt.Printf("Error: set width must be lower than terminal width\n\n")
return true
}
}
if width != 0 || height != 0 {
@ -102,21 +88,9 @@ func checkInputAndFlags(args []string) bool {
if width != 0 && height != 0 {
fmt.Printf("Error: both --width and --height can't be set. Use --dimensions instead\n\n")
return true
} else {
defaultTermWidth, _, err := winsize.GetTerminalSize()
if err != nil {
fmt.Printf("Error: %v\n\n", err)
return true
}
// Check if set width exceeds terminal
defaultTermWidth -= 1
if width > defaultTermWidth {
fmt.Printf("Error: set width must be lower than terminal width\n\n")
return true
}
if width < 0 {
fmt.Printf("Error: invalid value for width\n\n")
return true
@ -185,5 +159,10 @@ func checkInputAndFlags(args []string) bool {
return true
}
if (saveTxtPath == "" && saveImagePath == "" && saveGifPath == "") && onlySave {
fmt.Printf("Error: you need to supply one of --save-img, --save-txt or --save-gif for using --only-save\n\n")
return true
}
return false
}

View File

@ -124,13 +124,14 @@ func ConvertToAsciiChars(imgSet [][]AsciiPixel, negative, colored, grayscale, co
var char AsciiChar
char.Simple = chosenTable[tempInt]
asciiChar := chosenTable[tempInt]
char.Simple = asciiChar
var err error
if colorBg {
char.OriginalColor, err = getColoredCharForTerm(uint8(r), uint8(g), uint8(b), chosenTable[tempInt], true)
char.OriginalColor, err = getColoredCharForTerm(uint8(r), uint8(g), uint8(b), asciiChar, true)
} else {
char.OriginalColor, err = getColoredCharForTerm(uint8(r), uint8(g), uint8(b), chosenTable[tempInt], false)
char.OriginalColor, err = getColoredCharForTerm(uint8(r), uint8(g), uint8(b), asciiChar, false)
}
if (colored || grayscale) && err != nil {
return nil, err
@ -143,9 +144,9 @@ func ConvertToAsciiChars(imgSet [][]AsciiPixel, negative, colored, grayscale, co
fcB := fontColor[2]
if colorBg {
char.SetColor, err = getColoredCharForTerm(uint8(fcR), uint8(fcG), uint8(fcB), chosenTable[tempInt], true)
char.SetColor, err = getColoredCharForTerm(uint8(fcR), uint8(fcG), uint8(fcB), asciiChar, true)
} else {
char.SetColor, err = getColoredCharForTerm(uint8(fcR), uint8(fcG), uint8(fcB), chosenTable[tempInt], false)
char.SetColor, err = getColoredCharForTerm(uint8(fcR), uint8(fcG), uint8(fcB), asciiChar, false)
}
if err != nil {
return nil, err

View File

@ -34,16 +34,10 @@ getting numeric data for ASCII character comparison.
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, noTermSizeComparison bool) ([][]AsciiPixel, error) {
func ConvertToAsciiPixels(img image.Image, dimensions []int, width, height int, flipX, flipY, full, isBraille, dither bool) ([][]AsciiPixel, error) {
var smallImg image.Image
var err error
smallImg, err := resizeImage(img, full, isBraille, dimensions, width, height)
if noTermSizeComparison {
smallImg, err = resizeImageNoTerm(img, isBraille, dimensions, width, height)
} else {
smallImg, err = resizeImage(img, full, isBraille, dimensions, width, height)
}
if err != nil {
return nil, err
}

View File

@ -45,16 +45,16 @@ func resizeImage(img image.Image, full, isBraille bool, dimensions []int, width,
var asciiWidth, asciiHeight int
var smallImg image.Image
terminalWidth, terminalHeight, err := winsize.GetTerminalSize()
if err != nil {
return nil, err
}
imgWidth := float64(img.Bounds().Dx())
imgHeight := float64(img.Bounds().Dy())
aspectRatio := imgWidth / imgHeight
if full {
terminalWidth, _, err := winsize.GetTerminalSize()
if err != nil {
return nil, err
}
asciiWidth = terminalWidth - 1
asciiHeight = int(float64(asciiWidth) / aspectRatio)
asciiHeight = int(0.5 * float64(asciiHeight))
@ -62,10 +62,6 @@ func resizeImage(img image.Image, full, isBraille bool, dimensions []int, width,
} else if (width != 0 || height != 0) && len(dimensions) == 0 {
// If either width or height is set and dimensions aren't given
if width > terminalWidth-1 {
return nil, fmt.Errorf("set width must be lower than terminal width")
}
if width != 0 && height == 0 {
// If width is set and height is not set, use width to calculate aspect ratio
@ -88,17 +84,18 @@ func resizeImage(img image.Image, full, isBraille bool, dimensions []int, width,
asciiWidth = 1
}
if asciiWidth > terminalWidth-1 {
return nil, fmt.Errorf("width calculated with aspect ratio exceeds terminal width")
}
} else {
return nil, fmt.Errorf("both width and height can't be set. Use dimensions instead")
return nil, fmt.Errorf("error: both width and height can't be set. Use dimensions instead")
}
} else if len(dimensions) == 0 {
// This condition calculates aspect ratio according to terminal height
terminalWidth, terminalHeight, err := winsize.GetTerminalSize()
if err != nil {
return nil, err
}
asciiHeight = terminalHeight - 1
asciiWidth = int(float64(asciiHeight) * aspectRatio)
asciiWidth = int(2 * float64(asciiWidth))
@ -111,69 +108,13 @@ func resizeImage(img image.Image, full, isBraille bool, dimensions []int, width,
}
} else {
// Else, set passed dimensions
asciiWidth = dimensions[0]
asciiHeight = dimensions[1]
}
// Repeated despite being in cmd/root.go to maintain support for library
//
// If there are passed dimensions, check whether the width exceeds terminal width
if len(dimensions) > 0 && !full {
if dimensions[0] > terminalWidth-1 {
return nil, fmt.Errorf("set width must be lower than terminal width")
}
}
if isBraille {
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")
}
// Because one braille character has 8 dots (4 rows and 2 columns)
if isBraille {
asciiWidth *= 2
asciiHeight *= 4

View File

@ -1,6 +1,6 @@
name: ascii-image-converter
base: core18
version: "1.10.0"
version: "1.11.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