func WithBorderWidth(widths ...int) ImageOption {
	apply := func(arr *[4]int, top, right, bottom, left int) {
		arr[0] = top
		arr[1] = right
		arr[2] = bottom
		arr[3] = left
	}
	return newFuncDialOption(func(oo *outputImageOptions) {
		n := len(widths)
		switch n {
		case 0:
			apply(&oo.borderWidths, _defaultPadding, _defaultPadding, _defaultPadding, _defaultPadding)
		case 1:
			apply(&oo.borderWidths, widths[0], widths[0], widths[0], widths[0])
		case 2, 3:
			apply(&oo.borderWidths, widths[0], widths[1], widths[0], widths[1])
		default:
			apply(&oo.borderWidths, widths[0], widths[1], widths[2], widths[3])
		}
	})
}
WithBorderWidth specify the both 4 sides' border width. Notice that
WithBorderWidth(a) means all border width use this variable `a`,
WithBorderWidth(a, b) mean top/bottom equal to `a`, left/right equal to `b`.
WithBorderWidth(a, b, c, d) mean top, right, bottom, left.
package qrcode
import (
	"fmt"
	"image"
	"image/color"
	"image/jpeg"
	"image/png"
	"os"
	"github.com/yeqown/go-qrcode/matrix"
)
type ImageOption interface {
	apply(o *outputImageOptions)
}
type funcOption struct {
	f func(oo *outputImageOptions)
}
func (fo *funcOption) apply(oo *outputImageOptions) {
	fo.f(oo)
}
func newFuncDialOption(f func(oo *outputImageOptions)) *funcOption {
	return &funcOption{
		f: f,
	}
}
func WithBgColor(c color.Color) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		oo.bgColor = c
		_stateToRGBA[matrix.StateFalse] = oo.bgColor
	})
}
func WithBgColorRGBHex(hex string) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		oo.bgColor = hexToRGBA(hex)
		_stateToRGBA[matrix.StateFalse] = oo.bgColor
	})
}
func WithFgColor(c color.Color) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		oo.qrColor = c
		_stateToRGBA[matrix.StateTrue] = oo.qrColor
		_stateToRGBA[matrix.StateFinder] = oo.qrColor
	})
}
func WithFgColorRGBHex(hex string) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		oo.qrColor = hexToRGBA(hex)
		_stateToRGBA[matrix.StateTrue] = oo.qrColor
		_stateToRGBA[matrix.StateFinder] = oo.qrColor
	})
}
func WithLogoImage(img image.Image) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		oo.logo = img
	})
}
func WithLogoImageFileJPEG(f string) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		fd, err := os.Open(f)
		if err != nil {
			fmt.Printf("could not open file(%s), error=%v\n", f, err)
			return
		}
		img, err := jpeg.Decode(fd)
		if err != nil {
			fmt.Printf("could not open file(%s), error=%v\n", f, err)
			return
		}
		oo.logo = img
	})
}
func WithLogoImageFilePNG(f string) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		fd, err := os.Open(f)
		if err != nil {
			fmt.Printf("Open file(%s) failed: %v\n", f, err)
			return
		}
		img, err := png.Decode(fd)
		if err != nil {
			fmt.Printf("Decode file(%s) as PNG failed: %v\n", f, err)
			return
		}
		oo.logo = img
	})
}
func WithQRWidth(width uint8) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		oo.qrWidth = int(width)
	})
}
func WithCircleShape() ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		oo.shape = _shapeCircle
	})
}
func WithCustomShape(shape IShape) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		oo.shape = shape
	})
}
func WithBuiltinImageEncoder(format formatTyp) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		var encoder ImageEncoder
		switch format {
		case JPEG_FORMAT:
			encoder = jpegEncoder{}
		case PNG_FORMAT:
			encoder = pngEncoder{}
		default:
			panic("Not supported file format")
		}
		oo.imageEncoder = encoder
	})
}
func WithCustomImageEncoder(encoder ImageEncoder) ImageOption {
	return newFuncDialOption(func(oo *outputImageOptions) {
		if encoder == nil {
			return
		}
		oo.imageEncoder = encoder
	})
}