pquerna / otp

TOTP library for Go
Apache License 2.0
2.26k stars 221 forks source link

How to fix QR image size #85

Open ryan-swit opened 1 year ago

ryan-swit commented 1 year ago

It looks like QR image size depends on accountName length.

I was wondering how to fix QR image size.

Plaenkler commented 12 months ago

It looks like QR image size depends on accountName length.

I was wondering how to fix QR image size.

Do you mean the length/width of the image or the size in bytes?

ryan-swit commented 11 months ago

@Plaenkler Thank you for answering that.

The overall image size of QR img is fixed, but the actual part of QR img is changing. Could it be possible to return the same size even if the length of the account name changes?

I want to be able to fix the offset.

func scale2DCode(bc Barcode, width, height int) (Barcode, error) {
    orgBounds := bc.Bounds()
    orgWidth := orgBounds.Max.X - orgBounds.Min.X
    orgHeight := orgBounds.Max.Y - orgBounds.Min.Y

    factor := int(math.Min(float64(width)/float64(orgWidth), float64(height)/float64(orgHeight)))
    if factor <= 0 {
        return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx%d", orgWidth, orgHeight)
    }

    offsetX := (width - (orgWidth * factor)) / 2
    offsetY := (height - (orgHeight * factor)) / 2

    wrap := func(x, y int) color.Color {
        if x < offsetX || y < offsetY {
            return color.White
        }
        x = (x - offsetX) / factor
        y = (y - offsetY) / factor
        if x >= orgWidth || y >= orgHeight {
            return color.White
        }
        return bc.At(x, y)
    }

    return newScaledBC(
        bc,
        wrap,
        image.Rect(0, 0, width, height),
    ), nil
}
KEINOS commented 2 weeks ago

The overall image size of QR img is fixed, but the actual part of QR img is changing. Could it be possible to return the same size even if the length of the account name changes?

@ryan-swit

I apologize if I did not understand your question correctly.

If you do not want images to be scaled to a fixed size, you need to write a function like Image() that does not scale them automatically.

https://github.com/pquerna/otp/blob/3357de7c04813a328d6a1e4a514854213e0f8ce8/otp.go#L81-L94

The below example outputs the QR code that does not scale. Each "dot" of the QR code is alway the same size.

package main

import (
    "fmt"
    "image/png"
    "log"
    "os"

    "github.com/boombuler/barcode/qr"
    "github.com/pquerna/otp/totp"
)

func main() {
    key, err := totp.Generate(totp.GenerateOpts{
        Issuer:      "example.com",
        AccountName: "alice@example.com",
        SecretSize:  32,
    })
    if err != nil {
        log.Fatalf("Failed to generate OTP: %v", err)
    }

    qrImgFix, err := qr.Encode(key.String(), qr.M, qr.Auto)
    if err != nil {
        log.Fatalf("Failed to generate QR Code img: %v", err)
    }

    file, err := os.Create("otp_qrcode.png")
    if err != nil {
        log.Fatalf("Failed to create file for QR code: %v", err)
    }

    defer file.Close()

    if err := png.Encode(file, qrImgFix); err != nil {
        log.Fatalf("Failed to save QR code image: %v", err)
    }
    fmt.Println("QR code generated and saved as otp_qrcode.png")
}