status-go/vendor/github.com/yeqown/go-qrcode/writer/standard/image_option.go

191 lines
4.5 KiB
Go
Raw Normal View History

package standard
import (
"fmt"
"image"
"image/color"
"github.com/yeqown/go-qrcode/v2"
)
type ImageOption interface {
apply(o *outputImageOptions)
}
// defaultOutputImageOption default output image background color and etc options
func defaultOutputImageOption() *outputImageOptions {
return &outputImageOptions{
bgColor: color_WHITE, // white
bgTransparent: false, // not transparent
qrColor: color_BLACK, // black
logo: nil, //
qrWidth: 20, //
shape: _shapeRectangle, //
imageEncoder: jpegEncoder{},
borderWidths: [4]int{_defaultPadding, _defaultPadding, _defaultPadding, _defaultPadding},
}
}
// outputImageOptions to output QR code image
type outputImageOptions struct {
// bgColor is the background color of the QR code image.
bgColor color.RGBA
// bgTransparent only affects on PNG_FORMAT
bgTransparent bool
// qrColor is the foreground color of the QR code.
qrColor color.RGBA
// logo this icon image would be put the center of QR Code image
// NOTE: logo only should have 1/5 size of QRCode image
logo image.Image
// qrWidth width of each qr block
qrWidth int
// shape means how to draw the shape of each cell.
shape IShape
// imageEncoder specify which file format would be encoded the QR image.
imageEncoder ImageEncoder
// borderWidths indicates the border width of the output image. the order is
// top, right, bottom, left same as the WithBorder
borderWidths [4]int
// halftoneImg is the halftone image for the output image.
halftoneImg image.Image
}
func (oo *outputImageOptions) backgroundColor() color.RGBA {
if oo == nil {
return color_WHITE
}
if oo.bgTransparent {
(&oo.bgColor).A = 0x00
}
return oo.bgColor
}
func (oo *outputImageOptions) logoImage() image.Image {
if oo == nil || oo.logo == nil {
return nil
}
return oo.logo
}
func (oo *outputImageOptions) qrBlockWidth() int {
if oo == nil || (oo.qrWidth <= 0 || oo.qrWidth > 255) {
return 20
}
return oo.qrWidth
}
func (oo *outputImageOptions) getShape() IShape {
if oo == nil || oo.shape == nil {
return _shapeRectangle
}
return oo.shape
}
// preCalculateAttribute this function must reference to draw function.
func (oo *outputImageOptions) preCalculateAttribute(dimension int) *Attribute {
if oo == nil {
return nil
}
top, right, bottom, left := oo.borderWidths[0], oo.borderWidths[1], oo.borderWidths[2], oo.borderWidths[3]
return &Attribute{
W: dimension*oo.qrBlockWidth() + right + left,
H: dimension*oo.qrBlockWidth() + top + bottom,
Borders: oo.borderWidths,
BlockWidth: oo.qrBlockWidth(),
}
}
var (
color_WHITE = parseFromHex("#ffffff")
color_BLACK = parseFromHex("#000000")
)
var (
// _STATE_MAPPING mapping matrix.State to color.RGBA in debug mode.
_STATE_MAPPING = map[qrcode.QRType]color.RGBA{
qrcode.QRType_INIT: parseFromHex("#ffffff"), // [bg]
qrcode.QRType_DATA: parseFromHex("#cdc9c3"), // [bg]
qrcode.QRType_VERSION: parseFromHex("#000000"), // [fg]
qrcode.QRType_FORMAT: parseFromHex("#444444"), // [fg]
qrcode.QRType_FINDER: parseFromHex("#555555"), // [fg]
qrcode.QRType_DARK: parseFromHex("#2BA859"), // [fg]
qrcode.QRType_SPLITTER: parseFromHex("#2BA859"), // [fg]
qrcode.QRType_TIMING: parseFromHex("#000000"), // [fg]
}
)
// translateToRGBA get color.RGBA by value State, if not found, return outputImageOptions.qrColor.
// NOTE: this function decides the state should use qrColor or bgColor.
func (oo *outputImageOptions) translateToRGBA(v qrcode.QRValue) (rgba color.RGBA) {
// TODO(@yeqown): use _STATE_MAPPING to replace this function while in debug mode
// or some special flag.
if v.IsSet() {
rgba = oo.qrColor
return rgba
}
if oo.bgTransparent {
(&oo.bgColor).A = 0x00
}
rgba = oo.bgColor
return rgba
}
// parseFromHex convert hex string into color.RGBA
func parseFromHex(s string) color.RGBA {
c := color.RGBA{
R: 0,
G: 0,
B: 0,
A: 0xff,
}
var err error
switch len(s) {
case 7:
_, err = fmt.Sscanf(s, "#%02x%02x%02x", &c.R, &c.G, &c.B)
case 4:
_, err = fmt.Sscanf(s, "#%1x%1x%1x", &c.R, &c.G, &c.B)
// Double the hex digits:
c.R *= 17
c.G *= 17
c.B *= 17
default:
err = fmt.Errorf("invalid length, must be 7 or 4")
}
if err != nil {
panic(err)
}
return c
}
func parseFromColor(c color.Color) color.RGBA {
rgba, ok := c.(color.RGBA)
if ok {
return rgba
}
r, g, b, a := c.RGBA()
return color.RGBA{
R: uint8(r),
G: uint8(g),
B: uint8(b),
A: uint8(a),
}
}