Нани? Размер QR-кода нельзя настроить?

Java

Недавно на работе у маленького партнера возникла проблема с QR-кодами:Используя zxing, учитывая размер QR-кода указанного размера, когда размер меньше определенного диапазона, размер сгенерированного QR-кода сильно отличается от указанного размера.Например: Например, я дал размер генерации QR-кода 36 * ️36 пикселей, а фактический размер сгенерированного QR-кода составляет 21 * 21 пикселей.

принцип

Если вы знакомы с механизмом QR-кода, вы должны знать, что QR-код обладает хорошей способностью исправления ошибок и большой емкостью для переноса информации. Чтобы добиться лучшей обработки информации в разных масштабах, QR-код задает 40 уровней спецификаций, а генерируемый размер варьируется от 21*21 до 177*177.

В нашем приведенном выше сценарии QR-код, сгенерированный zxing, имеет версию 1, а возвращенный QR-код представляет собой матричную информацию 21 * 21. Данный размер 36 * 36 не является целым числом, кратным 21, и может вместить только 1 часть Информация о размере 21 * 21, поэтому, когда мы преобразуем информационную матрицу в изображение QR-кода, мы можем сгенерировать только QR-код 21 * 21 пикселей.

Конкретный принцип генерации и детали были подробно описаны в этой статье, пожалуйста, обратитесь кБазовая структура и принцип генерации QR-кода. Здесь я перечисляю только те знания, которые относятся к этой статье:

1. Версия

Существует от 1 до 40 различных версий QR-кодов, и каждая версия имеет присущую «структуру символов». (то есть квадратные черные и белые точки QR-кода), начиная с версии 1 (21 символ × 21 символ), и увеличиваясь по 4 символа в вертикальном и горизонтальном направлениях, до версии 40 (177 символов × 177 символов). ).

2. Уровень исправления ошибок

То есть показатель устойчивости к ошибкам имеет 4 уровня, чем выше уровень, тем выше способность к исправлению ошибок, однако из-за увеличения объема данных будет увеличиваться и размер кодирования.

Уровень исправления ошибок Отказоустойчивость
L около 7%
M около 15%
O около 25%
Q около 30%

3. Метод кодирования

То есть метод кодирования двумерной кодовой информации, двумерный код может кодировать информацию в соответствии с числами, английскими буквами, цифрами, двоичными, китайскими иероглифами, японскими и т. д.

Как решить

Из приведенного выше принципа двумерного кода размер двумерного кода всегда кратен определенному размеру в версиях 40. Поэтому для генерации двумерного кода небольшого размера вы можете настроить версию и отказоустойчивость двумерного кода и метода кодирования.Приходите, насколько это возможно с заданными требованиями к размеру. В нашей реальной производственной среде мы используем utf8 для кодирования информации, поэтому размер QR-кода зависит от выбранной версии и уровня исправления ошибок. Конкретные идеи таковы:

  • 1. Найдите версию, наиболее близкую к заданному размеру
  • 2. Определите, может ли версия вместить заданную информацию, и найдите оптимальный уровень отказоустойчивости.
  • 3. Размер кода возврата и уровень отказоустойчивости код показывает, как показано ниже:

public class QrCodeTest {
    //各尺寸最大容量,具体数据请参考 https://www.qrcode.com/zh/about/version.html
    static final int[][] VERSION_ERROR_ARR = new int[][]{
            {10,8,7,4},{20,16,12,8},{32,26,20,15},{48,38,28,21},
            {65,52,37,27},{82,65,45,36},{95,75,53,39},{118,93,66,52},
            {141,111,80,60},{167,131,93,74},{198,155,109,85},{226,177,125,96},
            {262,204,149,109},{282,223,159,120},{320,254,180,136},{361,277,198,154},
            {397,310,224,173},{442,345,243,191},{488,384,272,208},{528,410,297,235},
            {572,438,314,248},{618,480,348,270},{672,528,376,284},{721,561,407,315},
            {784,614,440,330},{842,652,462,365},{902,692,496,385},{940,732,534,405},
            {1002,778,559,430},{1066,843,604,457},{1132,894,634,486},{1201,947,684,518},
            {1273,1002,719,553},{1347,1060,756,590},{1417,1113,790,605},{1496,1176,832,647},
            {1577,1224,876,673},{1661,1292,923,701},{1729,1362,972,750},{1817,1435,1024,784}
    };

    public static int[] getQrCodeVersionAndError(String str, int size) throws Exception{
        if(21 > size){
            throw new IllegalAccessException("二维码尺寸不能小于21*21px");
        }
        
        //查找最接近给定尺寸的version
        int tVersion = (int)Math.floor((size - 21)/4.0);
        int errorCode = -1;
        int len = str.length();
        int minLen = len;

        int tLen1 = Math.abs(size - tVersion * 4 - 21);
        int tLen2 = Math.abs(size - (tVersion + 1) * 4 - 21);
        int version = tLen1 <= tLen2 ? tVersion : tVersion + 1;

        if(VERSION_ERROR_ARR[version][0] > len){
            return new int[]{version, 0};
        }
        //尺寸过小,不能容纳用户给定数据    
        for(int i = version+1; i < VERSION_ERROR_ARR.length; i++){
            for(int j = 0; j < VERSION_ERROR_ARR[i].length; j++){
                int min = Math.abs(len - VERSION_ERROR_ARR[i][j]);
                if(min == 0){
                    minLen = min;
                    version = i;
                    errorCode = j;
                    break;
                }else if(min <= minLen){
                    minLen = min;
                    version = i;
                    errorCode = j;
                }
            }

            if(-1 != errorCode){
                break;
            }
        }

        if(-1 == errorCode){
            throw new IllegalAccessException("该字符串内容过大");
        }

        return new int[]{version, errorCode};
    }

    public static void main(String[] args) throws Exception{
        print("hello",21);
        print("hello",22);
        print("hellohellohellohellohello",42);
        print("hello",43);
    }

    private static void print(String str, int size) throws Exception{
        int[] result = getQrCodeVersionAndError(str,size);
        System.out.println(str+","+size + ":["+result[0] + "," + result[1]+"]");
    }
}

благодарный