Недавно на работе у маленького партнера возникла проблема с 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]+"]");
}
}