SalOne22 / rimage

This is CLI tool inspired by squoosh!
Apache License 2.0
306 stars 19 forks source link

[Feature]: New command line interface #175

Closed SalOne22 closed 7 months ago

SalOne22 commented 8 months ago

Description

We should discuss a new CLI design for a more flexible and clear interface. Maintaining a simple, but more flexible and understandable command line interface.

Problem or Motivation

in #137 was founded a bug with the current implementation in the simple implementation of the CLI. For a clearer and more flexible interface, we should provide specific options for each encoder.

Expected behavior

We have different variants to consider:

  1. For each codec create a sub-command with specific options. Example usage of this can be like so:

    # without preprocessing
    rimage mozjpeg -q 75 ./input.jpg
    
    # throws an error because jxl doesn't have quality option 
    rimage jpegxl -q 80 ./input.jpg
    
    # with preprocessing (needs discussion)
    rimage --width 80 --height 80 mozjpeg ./input.jpg
    # with pipeline preprocessing (position dependent)
    rimage --resize 50% --quantization 75 mozjpeg ./input.jpg
  2. Copy imagemagick implementation with pipeline design (harder to implement):

    # infers codec based on output extension
    rimage ./input.jpg --resize 50% output.png 
    
    # using specific codec (adds more codec specific options)
    rimage ./input.jpg --resize 50% --codec oxipng --interlace --effort 2
    
    # throws an error because jxl doesn't have quality option 
    rimage ./input.jpg --codec jxl --quality 75
  3. Design something new? Any suggestions would help

Alternatives Considered

No response

Anything else?

@Mikachu2333 as a main user of this app, do you have any suggestions?

Mikachu2333 commented 8 months ago

In my opinion, the first option is a good idea. Furthermore, if our goal is to make error messages clear and understandable, why not refer to Git and give it a try?

For example: When I was about to type "commit" but "commut" was given, git tips me that the posssible values and panic.

What we should do is refer to what Git did and add more info about it.

图片


e.g.

>rimage jxx

rimage does not have a command named "jxx"
Maybe you mean "jxl", the details are as follows.

Jxl(JpegXl):
-o, --output <DIR>              Write output file(s) to <DIR>, if "-r" option is not used
-r, --recursive                 Saves output file(s) preserving folder structure
...
>rimage png -o "D:\desktop" -r "D:\f o o\测 试² ⱳ.png"

The "-o" conflict with "-r" opinion, please re-check it.

-o, --output <DIR>              Write output file(s) to <DIR>, if "-r" option is not used
-r, --recursive                 Saves output file(s) preserving folder structure
Mikachu2333 commented 8 months ago

Besides, the help info would also refer to what git.exe do.

e.g.

>rimage

No args are given!

Rimage is a software that ...

Athor: XXX
GitHub: XXXXX
License: XXX
...

Usage:
...
>rimage -h
Rimage is a software that ...

Athor: XXX
GitHub: XXXXX
License: XXX
...

Usage:
Use rimage <Format> -h for more detaild info that allowed for each format.

rimage jxl
rimage png
rimage jpg
...

Example:(3-4 examples)
...
>rimage png -h

Must opinions:
<Input Pic> or <Pics Dir>
-o... (if you want to output the pic to what folder it located, simply use "-r" as an alternative)
...

Possible opinions:
-s...

WARNING:
rimage ONLY support COMMON features of png format, use special images that contain RARE features such as dynamic or multi images will result in unpredictable results.
SalOne22 commented 8 months ago

All of the auto-suggestions and help are provided by the clap crate and its ecosystem. When using variants with subcommands, further discussion is needed regarding the preprocessing pipeline (e.g., resize, quantize) and how exactly these options can be passed to the program. Should different options be used for each preprocessor (--width, --height, --quantize, --dithering), or should there be one option with multiple values (--resize, --quantize)? The first option is more verbose and simpler, while the second option can provide features like scaling by a percentage (e.g., resizing the image by twice its original size) while also preserving default values in numbers (pixels for resizing and percentage for quantization).

Mikachu2333 commented 8 months ago

Should different options be used for each preprocessor (--width, --height, --quantize, --dithering)

--width, --height should be the general opinion for each kind of pic.

--quantize and --dithering depends on the format the pic use, e.g. jxl format on windows.

should there be one option with multiple values (--resize, --quantize)

Perhaps we can provide users with two methods, one is an accurate number of pixels, and the other is a multiple (supporting up to 2 decimal places).

To avoid too many args, may be we could use only one arg for it with special letters such as "@", and "_"

e.g.

rimage a.jpg -f png --resize 0.55         //  ->scaling to 55%
rimage a.jpg -f png --resize 5            //  ->scaling to 5x(500%)
rimage a.jpg -f png --resize @222_333     //  ->resize to 222 px width and 333 px height
rimage a.jpg -f png --resize @_999        //  ->resize to 999 px height with original width
rimage a.jpg -f ong --resize @111_        //  ->resize to 111 px width with original height
SalOne22 commented 8 months ago

Or we can provide pixels as this:

# resizes image to 500x300 px
rimage input.jpg --resize 500 300
# omitting one side
rimage input.jpg --resize _ 300

values with percentage need % at the end

Mikachu2333 commented 8 months ago

values with percentage need % at the end

For me, I'd like to replace --resize 500% with --resize @5 because 5 is shorter than 500 and 0.55 is easy to type on ansi keyboard 🤣 123

Mikachu2333 commented 8 months ago

Sorry for typos 😢 The word "opinion" should be "option"...

SalOne22 commented 7 months ago

Update. I created a new version of the cli on the feature/rimage-next branch. The functionality is not feature complete, but all previous behavior should remain intact. If I missed anything, let me know.

Kosette commented 7 months ago

It might be a bit late.

rimage jpg input.png --arg1 --arg2 or rimage input.png --codec jpg --arg1 --arg2. Both styles are acceptable to me, the former may be a bit more concise.

for --resize, it could be like this: --resize 500:300. for width or height only, 500: or :300. I'm not very sure if there are some side effects for parsing the colon.

Mikachu2333 commented 7 months ago

Maybe we'd better improve the args.

As the following pic shows,the help info notes me that the option -r could be used as --recursive but rimage said that I should use -- -r or -- --recursive and this might make users confused about it. 图片

And, the tips should also modified. 图片

Form rimage.exe [OPTIONS] [-- <files>] [Command] to rimage.exe [Command] [<files>] [OPTIONS]

Mikachu2333 commented 7 months ago

Besides, the supported codecs should be added to the program help info.

For example, if I don't read README on GitHub, never would i know that rimage support .ps file and .hdr file as input and there's no way to output pic with .bmp codec with rimage.

SalOne22 commented 7 months ago

rimage jpg input.png --arg1 --arg2 or rimage input.png --codec jpg --arg1 --arg2. Both styles are acceptable to me, the former may be a bit more concise.

Yes, for example squoosh does --mozjpeg option that accepts codec options in json, but I don't think that json is right format for a command line application. Current implementation does rely on subcommands to differentiate similar in names parameters like --quality from each other, because some codecs like ravif have specific behaviors for this options.

for --resize, it could be like this: --resize 500:300. for width or height only, 500: or :300. I'm not very sure if there are some side effects for parsing the colon.

imagemagick uses x to specify dimentions: -size 320x85 or percentages -resize 400%. I have implemented a vary of options for resize that if you need to I can add colon as another option.

As the following pic shows,the help info notes me that the option -r could be used as --recursive but rimage said that I should use -- -r or -- --recursive and this might make users confused about it.

This is because subcommands mozjpeg, jpeg, and others doesn't accept general options such as --recursive, --directory and all preprocessors. Help should be improved to show that. Also I didn't find how to set required fields with multiple values without issues, so all files are passed after --. I really need to investigate this more. Maybe set that files only acceptable in subcommands.

Besides, the supported codecs should be added to the program help info.

Agree, this should be in the long help

Kosette commented 7 months ago

imagemagick uses x to specify dimentions: -size 320x85 or percentages -resize 400%. I have implemented a vary of options for resize that if you need to I can add colon as another option.

x is good, easy to type. so -size also consumes x400 or 400x while keeping original ratio?

SalOne22 commented 7 months ago

so -size also consumes x400 or 400x while keeping original ratio?

Have done Rust inspired "placeholder" syntax _x400 and 400x_. I can change this to x400 and 400x, just didn't think about this variant. Also 400x can be interpreted as 400 times, not clear that other side is scaled according to aspect ratio.

Mikachu2333 commented 7 months ago

How could I see the tips about --risize?

图片

rimage resize --help
rimage resize -h
rimage resize help
rimage help --resize

None of these is approved...

SalOne22 commented 7 months ago

How could I see the tips about --risize?

rimage --help or rimage help and check the preprocessors section

SalOne22 commented 7 months ago

Updated options according to "cli guidelines", now help for a rimage looks like this:

Optimize images natively with best-in-class codecs

Usage: rimage [COMMAND]

Commands:
  avif      Encode images into AVIF format. (Small and Efficient)
  farbfeld  Encode images into Farbfeld format. (Bitmapped)
  jpeg      Encode images into JPEG format. (Progressive-able)
  jpeg_xl   Encode images into JpegXL format. (Big but Lossless)
  mozjpeg   Encode images into JPEG format using MozJpeg codec. (RECOMMENDED and Small)
  oxipng    Encode images into PNG format using OxiPNG codec. (Progressive-able)
  png       Encode images into PNG format.
  ppm       Encode images into PPM format. (Bitmapped)
  qoi       Encode images into QOI format. (Trendy and Small)
  webp      Encode images into WebP format. (Lossless-able)
  help      Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

And example of oxipng subcommand:

Encode images into PNG format using OxiPNG codec. (Progressive-able)

Usage: rimage oxipng [OPTIONS] <FILES>...

Options:
      --interlace
          Set interlace mode (progressive).

      --effort <NUM>
          Set the optimization level preset.
          The default level 2 is quite fast and provides good compression.

          Lower levels are faster, higher levels provide better compression, though with increasingly diminishing returns.

          0   => (1 trial, determined heuristically)
          1   => (1 trial, determined heuristically)
          2   => (4 fast trials, 1 main trial)
          3   => (4 trials)
          4   => (4 trials)
          5   => (8 trials)
          6   => (10 trials)

          [default: 2]

  -h, --help
          Print help (see a summary with '-h')

General:
  -d, --directory <DIR>
          The directory to write output file(s) to.

          Output files will be written without preserving the folder structure unless the --recursive flag is used.

  -r, --recursive
          Preserves the folder structure when writing output file(s).

          This option should be used in conjunction with the --directory option.

  -s, --suffix [<SUFFIX>]
          Adds the '@suffix' to the names of output file(s).

          When '2x' is provided as the value, the resulting files will be renamed with the '@2x' suffix.
          For example, a file named 'file.jpeg' will become 'file@2x.jpeg'.

          If no suffix is provided, the default updated suffix '@updated' will be added to the resulting files.

  -b, --backup
          Adds the '@backup' to the names of input file(s).

  -t, --threads <NUM>
          The number of threads for concurrent processing.

          Usage of multiple threads can speed up the execution of tasks, especially on multi-core processors.
          By default, the number of available threads is utilized.

  <FILES>...
          Input file(s) to process.

          If the file path contains spaces, enclose the path with double quotation marks on both sides.

Preprocessors:
      --resize <RESIZE>
          Resize the image(s) according to the specified criteria.

          Possible values:
          - @1.5:    Enlarge image size by this multiplier
          - 150%:    Adjust image size by this percentage
          - 100x100: Resize image to these dimensions
          - 200x_:   Adjust image dimensions while maintaining the aspect ratio based on the specified dimension

      --filter <FILTER>
          Filter that used when resizing an image.

          [default: lanczos3]

          Possible values:
          - nearest:     Simplest filter, for each destination pixel gets nearest source pixel.
          - box:         Each pixel contributes equally to destination. For upscaling, like Nearest.
          - bilinear:    Uses linear interpolation among contributing pixels for output.
          - hamming:     Provides quality akin to bicubic for downscaling, sharper than Bilinear, but not optimal for upscaling.
          - catmull-rom: Employs cubic interpolation for output pixel calculation.
          - mitchell:    Utilizes cubic interpolation for output pixel calculation.
          - lanczos3:    Applies high-quality Lanczos filter for output pixel calculation.

      --quantization [<QUALITY>]
          Enables quantization with optional quality in percentage.

          If quality is not provided, default 75 is used

      --dithering [<QUALITY>]
          Enables dithering with optional quality in percentage.

          Used with --quantization flag.
          If quality is not provided, default 75 is used.
Mikachu2333 commented 7 months ago

If I do not use '--baseline' flag when use mozjpeg, would the output pic be progressive by default settings? Or, in other words, how to avoid the pic to be progressive?

图片

This kind of phenomenon is currently widespread, so we'd better note users which option will be used as default although they doesn't mention it. e.g. If sb. use the code as the following shows, although the -q flag was not be mentioned, rimage would also add it to code implicitly Users input: rimage moz 1.jpg -s -r Process done: rimage moz 1.jpg -s -r -q 75

So, I think we should add some notices or tips to avoid this.

Mikachu2333 commented 7 months ago

As a temporary (or even permanent) solution, I believe we should avoid the Rimage program actively adding any implicit parameters in any situation

Kosette commented 7 months ago

If I do not use '--baseline' flag when use mozjpeg, would the output pic be progressive by default settings? Or, in other words, how to avoid the pic to be progressive?

图片

This kind of phenomenon is currently widespread, so we'd better note users which option will be used as default although they doesn't mention it. e.g. If sb. use the code as the following shows, although the -q flag was not be mentioned, rimage would also add it to code implicitly Users input: rimage moz 1.jpg -s -r Process done: rimage moz 1.jpg -s -r -q 75

So, I think we should add some notices or tips to avoid this.

We can say that this is a convention. CLI commands have many options, and default values are always set for some secondary options to avoid explicitly specifying all options for each call.

Options are divided into two types: Boolean and list. The former is often used to invert the default settings, such as --baseline or --recursive. The latter specifies values in the optional list in more detail, such as --thread <NUM>.

For --progressive, mozjpeg usage instructions say the following:

The -progressive switch creates a "progressive JPEG" file. In this type of JPEG file, the data is stored in multiple scans of increasing quality. If the file is being transmitted over a slow communications link, the decoder can use the first scan to display a low-quality image very quickly, and can then improve the display with each subsequent scan. The final image is exactly equivalent to a standard JPEG file of the same quality setting, and the total file size is about the same --- often a little smaller.

SalOne22 commented 7 months ago

Adding to this I want to create a tool that has good defaults for most of the users. You can use rimage mozjpeg ...images and get great results, like squoosh do. Check squoosh.app website to see how complex this options can be. Idk how to implement them in cli