Skip to content

Commit

Permalink
Format and TIFFCompression support flag.TextVar (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
sunshineplan committed Nov 23, 2023
1 parent edc53a5 commit e44c482
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 27 deletions.
34 changes: 10 additions & 24 deletions converter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"log/slog"
"os"
"path/filepath"
"strings"
"time"

"github.com/sunshineplan/imgconv"
Expand All @@ -26,11 +25,9 @@ var (
test = flag.Bool("test", false, "")
force = flag.Bool("force", false, "")
pdf = flag.Bool("pdf", false, "")
format = flag.String("format", "jpg", "")
whiteBackground = flag.Bool("white-background", false, "")
gray = flag.Bool("gray", false, "")
quality = flag.Int("quality", 75, "")
compression = flag.String("compression", "deflate", "")
autoOrientation = flag.Bool("auto-orientation", false, "")
watermark = flag.String("watermark", "", "")
opacity = flag.Uint("opacity", 128, "")
Expand All @@ -42,6 +39,9 @@ var (
percent = flag.Float64("percent", 0, "")
worker = flag.Int("worker", 5, "")
debug = flag.Bool("debug", false, "")

format imgconv.Format
compression imgconv.TIFFCompression
)

func usage() {
Expand Down Expand Up @@ -106,7 +106,10 @@ func main() {
return
}

flag.CommandLine.Init(os.Args[0], flag.PanicOnError)
flag.Usage = usage
flag.TextVar(&format, "format", imgconv.JPEG, "")
flag.TextVar(&compression, "compression", imgconv.TIFFDeflate, "")
flags.SetConfigFile(filepath.Join(filepath.Dir(self), "config.ini"))
flags.Parse()

Expand Down Expand Up @@ -150,34 +153,17 @@ func main() {

task := imgconv.NewOptions()

outputFormat, err := imgconv.FormatFromExtension(*format)
if err != nil {
log.Error("Failed to parse image format", "format", *format, "error", err)
code = 1
return
}
var opts []imgconv.EncodeOption
if outputFormat == imgconv.JPEG || outputFormat == imgconv.PDF {
if format == imgconv.JPEG || format == imgconv.PDF {
opts = append(opts, imgconv.Quality(*quality))
}
if outputFormat == imgconv.TIFF {
var ct imgconv.TIFFCompression
switch strings.ToLower(*compression) {
case "none":
ct = imgconv.TIFFUncompressed
case "deflate":
ct = imgconv.TIFFDeflate
default:
log.Error("Unknown tiff compression", "type", *compression)
code = 1
return
}
opts = append(opts, imgconv.TIFFCompressionType(ct))
if format == imgconv.TIFF {
opts = append(opts, imgconv.TIFFCompressionType(compression))
}
if *whiteBackground {
opts = append(opts, imgconv.BackgroundColor(color.White))
}
task.SetFormat(outputFormat, opts...)
task.SetFormat(format, opts...)

if *gray {
task.SetGray(true)
Expand Down
62 changes: 59 additions & 3 deletions format.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package imgconv

import (
"encoding"
"fmt"
"image"
"image/color"
"image/draw"
Expand All @@ -17,6 +19,11 @@ import (
_ "golang.org/x/image/webp" // decode webp format
)

var (
_ encoding.TextUnmarshaler = new(Format)
_ encoding.TextMarshaler = Format(0)
)

// Format is an image file format.
type Format int

Expand All @@ -39,16 +46,21 @@ var formatExts = [][]string{
{"pdf"},
}

func (f Format) String() string {
func (f Format) String() (format string) {
defer func() {
if err := recover(); err != nil {
format = "unknown"
}
}()
return formatExts[f][0]
}

// FormatFromExtension parses image format from filename extension:
// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff"), "bmp" and "pdf" are supported.
func FormatFromExtension(ext string) (Format, error) {
ext = strings.ToLower(ext)
for _, exts := range formatExts {
for index, i := range exts {
for index, exts := range formatExts {
for _, i := range exts {
if ext == i {
return Format(index), nil
}
Expand All @@ -58,6 +70,24 @@ func FormatFromExtension(ext string) (Format, error) {
return -1, image.ErrFormat
}

func (f *Format) UnmarshalText(text []byte) error {
format, err := FormatFromExtension(string(text))
if err != nil {
return err
}
*f = format
return nil
}

func (f Format) MarshalText() ([]byte, error) {
return []byte(f.String()), nil
}

var (
_ encoding.TextUnmarshaler = new(TIFFCompression)
_ encoding.TextMarshaler = TIFFCompression(0)
)

// TIFFCompression describes the type of compression used in Options.
type TIFFCompression int

Expand All @@ -67,6 +97,11 @@ const (
TIFFDeflate
)

var tiffCompression = []string{
"none",
"deflate",
}

func (c TIFFCompression) value() tiff.CompressionType {
switch c {
case TIFFDeflate:
Expand All @@ -75,6 +110,27 @@ func (c TIFFCompression) value() tiff.CompressionType {
return tiff.Uncompressed
}

func (c *TIFFCompression) UnmarshalText(text []byte) error {
t := strings.ToLower(string(text))
for index, tt := range tiffCompression {
if t == tt {
*c = TIFFCompression(index)
return nil
}
}
return fmt.Errorf("tiff: unsupported compression: %s", t)
}

func (c TIFFCompression) MarshalText() (b []byte, err error) {
defer func() {
if err := recover(); err != nil {
b = []byte("unknown")
}
}()
ct := tiffCompression[c]
return []byte(ct), nil
}

// FormatOption is format option
type FormatOption struct {
Format Format
Expand Down
40 changes: 40 additions & 0 deletions format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package imgconv

import (
"bytes"
"flag"
"image"
"image/draw"
"image/png"
Expand All @@ -21,6 +22,45 @@ func TestFormatFromExtension(t *testing.T) {
}
}

func TestTextVar(t *testing.T) {
testCase1 := []struct {
argument string
format Format
}{
{"Jpg", JPEG},
{"TIFF", TIFF},
{"txt", Format(-1)},
}
for _, tc := range testCase1 {
f := flag.NewFlagSet("test", flag.ContinueOnError)
f.SetOutput(io.Discard)
var format Format
f.TextVar(&format, "f", Format(-1), "")
f.Parse(append([]string{"-f"}, tc.argument))
if format != tc.format {
t.Errorf("expected %s format; got %s", tc.format, format)
}
}
testCase2 := []struct {
argument string
compression TIFFCompression
}{
{"none", TIFFUncompressed},
{"Deflate", TIFFDeflate},
{"lzw", TIFFCompression(-1)},
}
for _, tc := range testCase2 {
f := flag.NewFlagSet("test", flag.ContinueOnError)
f.SetOutput(io.Discard)
var compression TIFFCompression
f.TextVar(&compression, "c", TIFFCompression(-1), "")
f.Parse(append([]string{"-c"}, tc.argument))
if compression != tc.compression {
t.Errorf("expected %d compression; got %d", tc.compression, compression)
}
}
}

func TestEncode(t *testing.T) {
testCase := []FormatOption{
{Format: JPEG, EncodeOption: []EncodeOption{Quality(75)}},
Expand Down

0 comments on commit e44c482

Please sign in to comment.