123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275 |
- /*
- * Copyright (c) 2010 Psytec Inc.
- * Copyright (c) 2012 Alexey Mednyy <swexru@gmail.com>
- * Copyright (c) 2012-2014 Pavol Rusnak <stick@gk2.sk>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
- #include <string.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include "qr_encode.h"
- #include "qr_consts.h"
- static int m_nLevel;
- static int m_nVersion;
- static int m_nMaskingNo;
- static int m_ncDataCodeWordBit, m_ncAllCodeWord, nEncodeVersion;
- static int m_ncDataBlock;
- static int m_nSymbleSize;
- static int m_nBlockLength[QR_MAX_DATACODEWORD];
- static uint8_t m_byModuleData[QR_MAX_MODULESIZE][QR_MAX_MODULESIZE]; // [x][y]
- static uint8_t m_byAllCodeWord[QR_MAX_ALLCODEWORD];
- static uint8_t m_byBlockMode[QR_MAX_DATACODEWORD];
- static uint8_t m_byDataCodeWord[QR_MAX_DATACODEWORD];
- static uint8_t m_byRSWork[QR_MAX_CODEBLOCK];
- static int IsNumeralData(uint8_t c)
- {
- if (c >= '0' && c <= '9')
- return 1;
- return 0;
- }
- static int IsAlphabetData(uint8_t c)
- {
- if (c >= '0' && c <= '9')
- return 1;
- if (c >= 'A' && c <= 'Z')
- return 1;
- if (c == ' ' || c == '$' || c == '%' || c == '*' || c == '+' || c == '-' || c == '.' || c == '/' || c == ':')
- return 1;
- return 0;
- }
- static uint8_t AlphabetToBinary(uint8_t c)
- {
- if (c >= '0' && c <= '9')
- return (uint8_t)(c - '0');
- if (c >= 'A' && c <= 'Z')
- return (uint8_t)(c - 'A' + 10);
- if (c == ' ')
- return 36;
- if (c == '$')
- return 37;
- if (c == '%')
- return 38;
- if (c == '*')
- return 39;
- if (c == '+')
- return 40;
- if (c == '-')
- return 41;
- if (c == '.')
- return 42;
- if (c == '/')
- return 43;
- return 44; // c == ':'
- }
- static int SetBitStream(int nIndex, uint16_t wData, int ncData)
- {
- int i;
- if (nIndex == -1 || nIndex + ncData > QR_MAX_DATACODEWORD * 8)
- return -1;
- for (i = 0; i < ncData; i++)
- {
- if (wData & (1 << (ncData - i - 1)))
- {
- m_byDataCodeWord[(nIndex + i) / 8] |= 1 << (7 - ((nIndex + i) % 8));
- }
- }
- return nIndex + ncData;
- }
- static int GetBitLength(uint8_t nMode, int ncData, int nVerGroup)
- {
- int ncBits = 0;
- switch (nMode)
- {
- case QR_MODE_NUMERAL:
- ncBits = 4 + nIndicatorLenNumeral[nVerGroup] + (10 * (ncData / 3));
- switch (ncData % 3)
- {
- case 1:
- ncBits += 4;
- break;
- case 2:
- ncBits += 7;
- break;
- default: // case 0:
- break;
- }
- break;
- case QR_MODE_ALPHABET:
- ncBits = 4 + nIndicatorLenAlphabet[nVerGroup] + (11 * (ncData / 2)) + (6 * (ncData % 2));
- break;
- default: // case QR_MODE_8BIT:
- ncBits = 4 + nIndicatorLen8Bit[nVerGroup] + (8 * ncData);
- break;
- }
- return ncBits;
- }
- static int EncodeSourceData(const char *lpsSource, int ncLength, int nVerGroup)
- {
- memset(m_nBlockLength, 0, sizeof(m_nBlockLength));
- int i, j;
- // Investigate whether continuing characters (bytes) which mode is what
- for (m_ncDataBlock = i = 0; i < ncLength; i++)
- {
- uint8_t byMode;
- if (IsNumeralData(lpsSource[i]))
- {
- byMode = QR_MODE_NUMERAL;
- }
- else if (IsAlphabetData(lpsSource[i]))
- {
- byMode = QR_MODE_ALPHABET;
- }
- else
- {
- byMode = QR_MODE_8BIT;
- }
- if (i == 0)
- {
- m_byBlockMode[0] = byMode;
- }
- if (m_byBlockMode[m_ncDataBlock] != byMode)
- {
- m_byBlockMode[++m_ncDataBlock] = byMode;
- }
- m_nBlockLength[m_ncDataBlock]++;
- }
- m_ncDataBlock++;
- // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
- // Linked by a sequence of conditional block alphanumeric mode and numeric mode block adjacent
- int ncSrcBits, ncDstBits; // The bit length of the block mode if you have over the original bit length and a single alphanumeric
- int nBlock = 0;
- while (nBlock < m_ncDataBlock - 1)
- {
- int ncJoinFront, ncJoinBehind; // Bit length when combined with 8-bit byte block mode before and after
- int nJoinPosition = 0; // Block the binding of 8-bit byte mode: combined with the previous -1 = 0 = do not bind, bind behind a =
- // Sort of - "digit alphanumeric" - "or alphanumeric numbers"
- if ((m_byBlockMode[nBlock] == QR_MODE_NUMERAL && m_byBlockMode[nBlock + 1] == QR_MODE_ALPHABET) ||
- (m_byBlockMode[nBlock] == QR_MODE_ALPHABET && m_byBlockMode[nBlock + 1] == QR_MODE_NUMERAL))
- {
- // If you compare the bit length of alphanumeric characters and a single block mode over the original bit length
- ncSrcBits = GetBitLength(m_byBlockMode[nBlock], m_nBlockLength[nBlock], nVerGroup) +
- GetBitLength(m_byBlockMode[nBlock + 1], m_nBlockLength[nBlock + 1], nVerGroup);
- ncDstBits = GetBitLength(QR_MODE_ALPHABET, m_nBlockLength[nBlock] + m_nBlockLength[nBlock + 1], nVerGroup);
- if (ncSrcBits > ncDstBits)
- {
- // If there is an 8-bit byte block mode back and forth, check whether they favor the binding of
- if (nBlock >= 1 && m_byBlockMode[nBlock - 1] == QR_MODE_8BIT)
- {
- // There are 8-bit byte block mode before
- ncJoinFront = GetBitLength(QR_MODE_8BIT, m_nBlockLength[nBlock - 1] + m_nBlockLength[nBlock], nVerGroup) +
- GetBitLength(m_byBlockMode[nBlock + 1], m_nBlockLength[nBlock + 1], nVerGroup);
- if (ncJoinFront > ncDstBits + GetBitLength(QR_MODE_8BIT, m_nBlockLength[nBlock - 1], nVerGroup))
- {
- ncJoinFront = 0; // 8-bit byte and block mode does not bind
- }
- }
- else
- {
- ncJoinFront = 0;
- }
- if (nBlock < m_ncDataBlock - 2 && m_byBlockMode[nBlock + 2] == QR_MODE_8BIT)
- {
- // There are 8-bit byte mode block behind
- ncJoinBehind = GetBitLength(m_byBlockMode[nBlock], m_nBlockLength[nBlock], nVerGroup) +
- GetBitLength(QR_MODE_8BIT, m_nBlockLength[nBlock + 1] + m_nBlockLength[nBlock + 2], nVerGroup);
- if (ncJoinBehind > ncDstBits + GetBitLength(QR_MODE_8BIT, m_nBlockLength[nBlock + 2], nVerGroup))
- {
- ncJoinBehind = 0; // 8-bit byte and block mode does not bind
- }
- }
- else
- {
- ncJoinBehind = 0;
- }
- if (ncJoinFront != 0 && ncJoinBehind != 0)
- {
- // If there is a 8-bit byte block mode has priority both before and after the way the data length is shorter
- nJoinPosition = (ncJoinFront < ncJoinBehind) ? -1 : 1;
- }
- else
- {
- nJoinPosition = (ncJoinFront != 0) ? -1 : ((ncJoinBehind != 0) ? 1 : 0);
- }
- if (nJoinPosition != 0)
- {
- // Block the binding of 8-bit byte mode
- if (nJoinPosition == -1)
- {
- m_nBlockLength[nBlock - 1] += m_nBlockLength[nBlock];
- // The subsequent shift
- for (i = nBlock; i < m_ncDataBlock - 1; i++)
- {
- m_byBlockMode[i] = m_byBlockMode[i + 1];
- m_nBlockLength[i] = m_nBlockLength[i + 1];
- }
- }
- else
- {
- m_byBlockMode[nBlock + 1] = QR_MODE_8BIT;
- m_nBlockLength[nBlock + 1] += m_nBlockLength[nBlock + 2];
- // The subsequent shift
- for (i = nBlock + 2; i < m_ncDataBlock - 1; i++)
- {
- m_byBlockMode[i] = m_byBlockMode[i + 1];
- m_nBlockLength[i] = m_nBlockLength[i + 1];
- }
- }
- m_ncDataBlock--;
- }
- else
- {
- // Block mode integrated into a single alphanumeric string of numbers and alphanumeric
- if (nBlock < m_ncDataBlock - 2 && m_byBlockMode[nBlock + 2] == QR_MODE_ALPHABET)
- {
- // Binding mode of the block followed by alphanumeric block attempts to join
- m_nBlockLength[nBlock + 1] += m_nBlockLength[nBlock + 2];
- // The subsequent shift
- for (i = nBlock + 2; i < m_ncDataBlock - 1; i++)
- {
- m_byBlockMode[i] = m_byBlockMode[i + 1];
- m_nBlockLength[i] = m_nBlockLength[i + 1];
- }
- m_ncDataBlock--;
- }
- m_byBlockMode[nBlock] = QR_MODE_ALPHABET;
- m_nBlockLength[nBlock] += m_nBlockLength[nBlock + 1];
- // The subsequent shift
- for (i = nBlock + 1; i < m_ncDataBlock - 1; i++)
- {
- m_byBlockMode[i] = m_byBlockMode[i + 1];
- m_nBlockLength[i] = m_nBlockLength[i + 1];
- }
- m_ncDataBlock--;
- if (nBlock >= 1 && m_byBlockMode[nBlock - 1] == QR_MODE_ALPHABET)
- {
- // Combined mode of alphanumeric block before the block bound
- m_nBlockLength[nBlock - 1] += m_nBlockLength[nBlock];
- // The subsequent shift
- for (i = nBlock; i < m_ncDataBlock - 1; i++)
- {
- m_byBlockMode[i] = m_byBlockMode[i + 1];
- m_nBlockLength[i] = m_nBlockLength[i + 1];
- }
- m_ncDataBlock--;
- }
- }
- continue;
- // Re-examine the block of the current position
- }
- }
- nBlock++; // Investigate the next block
- }
- // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
- // 8-bit byte block mode over the short block mode to continuous
- nBlock = 0;
- while (nBlock < m_ncDataBlock - 1)
- {
- ncSrcBits = GetBitLength(m_byBlockMode[nBlock], m_nBlockLength[nBlock], nVerGroup) + GetBitLength(m_byBlockMode[nBlock + 1], m_nBlockLength[nBlock + 1], nVerGroup);
- ncDstBits = GetBitLength(QR_MODE_8BIT, m_nBlockLength[nBlock] + m_nBlockLength[nBlock + 1], nVerGroup);
- // If there is a 8-bit byte block mode before, subtract the duplicate indicator minute
- if (nBlock >= 1 && m_byBlockMode[nBlock - 1] == QR_MODE_8BIT)
- {
- ncDstBits -= (4 + nIndicatorLen8Bit[nVerGroup]);
- }
- // If there is a block behind the 8-bit byte mode, subtract the duplicate indicator minute
- if (nBlock < m_ncDataBlock - 2 && m_byBlockMode[nBlock + 2] == QR_MODE_8BIT)
- {
- ncDstBits -= (4 + nIndicatorLen8Bit[nVerGroup]);
- }
- if (ncSrcBits > ncDstBits)
- {
- if (nBlock >= 1 && m_byBlockMode[nBlock - 1] == QR_MODE_8BIT)
- {
- // 8-bit byte mode coupling block in front of the block to join
- m_nBlockLength[nBlock - 1] += m_nBlockLength[nBlock];
- // The subsequent shift
- for (i = nBlock; i < m_ncDataBlock - 1; i++)
- {
- m_byBlockMode[i] = m_byBlockMode[i + 1];
- m_nBlockLength[i] = m_nBlockLength[i + 1];
- }
- m_ncDataBlock--;
- nBlock--;
- }
- if (nBlock < m_ncDataBlock - 2 && m_byBlockMode[nBlock + 2] == QR_MODE_8BIT)
- {
- // 8-bit byte mode coupling block at the back of the block to join
- m_nBlockLength[nBlock + 1] += m_nBlockLength[nBlock + 2];
- // The subsequent shift
- for (i = nBlock + 2; i < m_ncDataBlock - 1; i++)
- {
- m_byBlockMode[i] = m_byBlockMode[i + 1];
- m_nBlockLength[i] = m_nBlockLength[i + 1];
- }
- m_ncDataBlock--;
- }
- m_byBlockMode[nBlock] = QR_MODE_8BIT;
- m_nBlockLength[nBlock] += m_nBlockLength[nBlock + 1];
- // The subsequent shift
- for (i = nBlock + 1; i < m_ncDataBlock - 1; i++)
- {
- m_byBlockMode[i] = m_byBlockMode[i + 1];
- m_nBlockLength[i] = m_nBlockLength[i + 1];
- }
- m_ncDataBlock--;
- // Re-examination in front of the block bound
- if (nBlock >= 1)
- {
- nBlock--;
- }
- continue;
- }
- nBlock++; // Investigate the next block
- }
- // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
- // Mosquito bit array
- int ncComplete = 0; // Data pre-processing counter
- uint16_t wBinCode;
- m_ncDataCodeWordBit = 0; // Bit counter processing unit
- memset(m_byDataCodeWord, 0, sizeof(m_byDataCodeWord));
- for (i = 0; i < m_ncDataBlock && m_ncDataCodeWordBit != -1; i++)
- {
- if (m_byBlockMode[i] == QR_MODE_NUMERAL)
- {
- // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
- // Numeric mode
- // Indicator (0001b)
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, 1, 4);
- // Set number of characters
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, (uint16_t)m_nBlockLength[i], nIndicatorLenNumeral[nVerGroup]);
- // Save the bit string
- for (j = 0; j < m_nBlockLength[i]; j += 3)
- {
- if (j < m_nBlockLength[i] - 2)
- {
- wBinCode = (uint16_t)(((lpsSource[ncComplete + j] - '0') * 100) +
- ((lpsSource[ncComplete + j + 1] - '0') * 10) +
- (lpsSource[ncComplete + j + 2] - '0'));
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, wBinCode, 10);
- }
- else if (j == m_nBlockLength[i] - 2)
- {
- // 2 bytes fraction
- wBinCode = (uint16_t)(((lpsSource[ncComplete + j] - '0') * 10) +
- (lpsSource[ncComplete + j + 1] - '0'));
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, wBinCode, 7);
- }
- else if (j == m_nBlockLength[i] - 1)
- {
- // A fraction of bytes
- wBinCode = (uint16_t)(lpsSource[ncComplete + j] - '0');
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, wBinCode, 4);
- }
- }
- ncComplete += m_nBlockLength[i];
- }
- else if (m_byBlockMode[i] == QR_MODE_ALPHABET)
- {
- // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
- // Alphanumeric mode
- // Mode indicator (0010b)
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, 2, 4);
- // Set number of characters
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, (uint16_t)m_nBlockLength[i], nIndicatorLenAlphabet[nVerGroup]);
- // Save the bit string
- for (j = 0; j < m_nBlockLength[i]; j += 2)
- {
- if (j < m_nBlockLength[i] - 1)
- {
- wBinCode = (uint16_t)((AlphabetToBinary(lpsSource[ncComplete + j]) * 45) +
- AlphabetToBinary(lpsSource[ncComplete + j + 1]));
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, wBinCode, 11);
- }
- else
- {
- // A fraction of bytes
- wBinCode = (uint16_t)AlphabetToBinary(lpsSource[ncComplete + j]);
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, wBinCode, 6);
- }
- }
- ncComplete += m_nBlockLength[i];
- }
- else
- { // (m_byBlockMode[i] == QR_MODE_8BIT)
- // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
- // 8-bit byte mode
- // Mode indicator (0100b)
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, 4, 4);
- // Set number of characters
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, (uint16_t)m_nBlockLength[i], nIndicatorLen8Bit[nVerGroup]);
- // Save the bit string
- for (j = 0; j < m_nBlockLength[i]; j++)
- {
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, (uint16_t)lpsSource[ncComplete + j], 8);
- }
- ncComplete += m_nBlockLength[i];
- }
- }
- return (m_ncDataCodeWordBit != -1);
- }
- // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
- // APPLICATIONS: To get the bit length
- // Args: data mode type, data length, group version (model number)
- // Returns: data bit length
- static int GetEncodeVersion(int nVersion, const char *lpsSource, int ncLength)
- {
- int nVerGroup = nVersion >= 27 ? QR_VERSION_L : (nVersion >= 10 ? QR_VERSION_M : QR_VERSION_S);
- int i, j;
- for (i = nVerGroup; i <= QR_VERSION_L; i++)
- {
- if (EncodeSourceData(lpsSource, ncLength, i))
- {
- if (i == QR_VERSION_S)
- {
- for (j = 1; j <= 9; j++)
- {
- if ((m_ncDataCodeWordBit + 7) / 8 <= QR_VersonInfo[j].ncDataCodeWord[m_nLevel])
- {
- return j;
- }
- }
- }
- #if QR_MAX_VERSION >= QR_VERSION_M
- else if (i == QR_VERSION_M)
- {
- for (j = 10; j <= 26; j++)
- {
- if ((m_ncDataCodeWordBit + 7) / 8 <= QR_VersonInfo[j].ncDataCodeWord[m_nLevel])
- {
- return j;
- }
- }
- }
- #endif
- #if QR_MAX_VERSION >= QR_VERSION_L
- else if (i == QR_VERSION_L)
- {
- for (j = 27; j <= 40; j++)
- {
- if ((m_ncDataCodeWordBit + 7) / 8 <= QR_VersonInfo[j].ncDataCodeWord[m_nLevel])
- {
- return j;
- }
- }
- }
- #endif
- }
- }
- return 0;
- }
- static void GetRSCodeWord(uint8_t *lpbyRSWork, int ncDataCodeWord, int ncRSCodeWord)
- {
- int i, j;
- for (i = 0; i < ncDataCodeWord; i++)
- {
- if (lpbyRSWork[0] != 0)
- {
- uint8_t nExpFirst = byIntToExp[lpbyRSWork[0]]; // Multiplier coefficient is calculated from the first term
- for (j = 0; j < ncRSCodeWord; j++)
- {
- // Add (% 255 ^ 255 = 1) the first term multiplier to multiplier sections
- uint8_t nExpElement = (uint8_t)(((int)(byRSExp[ncRSCodeWord][j] + nExpFirst)) % 255);
- // Surplus calculated by the exclusive
- lpbyRSWork[j] = (uint8_t)(lpbyRSWork[j + 1] ^ byExpToInt[nExpElement]);
- }
- // Shift the remaining digits
- for (j = ncRSCodeWord; j < ncDataCodeWord + ncRSCodeWord - 1; j++)
- {
- lpbyRSWork[j] = lpbyRSWork[j + 1];
- }
- }
- else
- {
- // Shift the remaining digits
- for (j = 0; j < ncDataCodeWord + ncRSCodeWord - 1; j++)
- {
- lpbyRSWork[j] = lpbyRSWork[j + 1];
- }
- }
- }
- }
- static void SetFinderPattern(int x, int y)
- {
- static const uint8_t byPattern[] = {0x7f, // 1111111b
- 0x41, // 1000001b
- 0x5d, // 1011101b
- 0x5d, // 1011101b
- 0x5d, // 1011101b
- 0x41, // 1000001b
- 0x7f}; // 1111111b
- int i, j;
- for (i = 0; i < 7; i++)
- {
- for (j = 0; j < 7; j++)
- {
- m_byModuleData[x + j][y + i] = (byPattern[i] & (1 << (6 - j))) ? '\x30' : '\x20';
- }
- }
- }
- static void SetVersionPattern(void)
- {
- int i, j;
- if (m_nVersion <= 6)
- {
- return;
- }
- int nVerData = m_nVersion << 12;
- // Calculated bit remainder
- for (i = 0; i < 6; i++)
- {
- if (nVerData & (1 << (17 - i)))
- {
- nVerData ^= (0x1f25 << (5 - i));
- }
- }
- nVerData += m_nVersion << 12;
- for (i = 0; i < 6; i++)
- {
- for (j = 0; j < 3; j++)
- {
- m_byModuleData[m_nSymbleSize - 11 + j][i] = m_byModuleData[i][m_nSymbleSize - 11 + j] =
- (nVerData & (1 << (i * 3 + j))) ? '\x30' : '\x20';
- }
- }
- }
- static void SetAlignmentPattern(int x, int y)
- {
- static const uint8_t byPattern[] = {0x1f, // 11111b
- 0x11, // 10001b
- 0x15, // 10101b
- 0x11, // 10001b
- 0x1f}; // 11111b
- int i, j;
- if (m_byModuleData[x][y] & 0x20)
- {
- return; // Excluded due to overlap with the functional module
- }
- x -= 2;
- y -= 2; // Convert the coordinates to the upper left corner
- for (i = 0; i < 5; i++)
- {
- for (j = 0; j < 5; j++)
- {
- m_byModuleData[x + j][y + i] = (byPattern[i] & (1 << (4 - j))) ? '\x30' : '\x20';
- }
- }
- }
- static void SetFunctionModule(void)
- {
- int i, j;
- // Position detection pattern
- SetFinderPattern(0, 0);
- SetFinderPattern(m_nSymbleSize - 7, 0);
- SetFinderPattern(0, m_nSymbleSize - 7);
- // Separator pattern position detection
- for (i = 0; i < 8; i++)
- {
- m_byModuleData[i][7] = m_byModuleData[7][i] = '\x20';
- m_byModuleData[m_nSymbleSize - 8][i] = m_byModuleData[m_nSymbleSize - 8 + i][7] = '\x20';
- m_byModuleData[i][m_nSymbleSize - 8] = m_byModuleData[7][m_nSymbleSize - 8 + i] = '\x20';
- }
- // Registration as part of a functional module position description format information
- for (i = 0; i < 9; i++)
- {
- m_byModuleData[i][8] = m_byModuleData[8][i] = '\x20';
- }
- for (i = 0; i < 8; i++)
- {
- m_byModuleData[m_nSymbleSize - 8 + i][8] = m_byModuleData[8][m_nSymbleSize - 8 + i] = '\x20';
- }
- // Version information pattern
- SetVersionPattern();
- // Pattern alignment
- for (i = 0; i < QR_VersonInfo[m_nVersion].ncAlignPoint; i++)
- {
- SetAlignmentPattern(QR_VersonInfo[m_nVersion].nAlignPoint[i], 6);
- SetAlignmentPattern(6, QR_VersonInfo[m_nVersion].nAlignPoint[i]);
- for (j = 0; j < QR_VersonInfo[m_nVersion].ncAlignPoint; j++)
- {
- SetAlignmentPattern(QR_VersonInfo[m_nVersion].nAlignPoint[i], QR_VersonInfo[m_nVersion].nAlignPoint[j]);
- }
- }
- // Timing pattern
- for (i = 8; i <= m_nSymbleSize - 9; i++)
- {
- m_byModuleData[i][6] = (i % 2) == 0 ? '\x30' : '\x20';
- m_byModuleData[6][i] = (i % 2) == 0 ? '\x30' : '\x20';
- }
- }
- static void SetCodeWordPattern(void)
- {
- int x = m_nSymbleSize;
- int y = m_nSymbleSize - 1;
- int nCoef_x = 1; // placement orientation axis x
- int nCoef_y = 1; // placement orientation axis y
- int i, j;
- for (i = 0; i < m_ncAllCodeWord; i++)
- {
- for (j = 0; j < 8; j++)
- {
- do
- {
- x += nCoef_x;
- nCoef_x *= -1;
- if (nCoef_x < 0)
- {
- y += nCoef_y;
- if (y < 0 || y == m_nSymbleSize)
- {
- y = (y < 0) ? 0 : m_nSymbleSize - 1;
- nCoef_y *= -1;
- x -= 2;
- if (x == 6)
- { // Timing pattern
- x--;
- }
- }
- }
- } while (m_byModuleData[x][y] & 0x20); // Exclude a functional module
- m_byModuleData[x][y] = (m_byAllCodeWord[i] & (1 << (7 - j))) ? '\x02' : '\x00';
- }
- }
- }
- static void SetMaskingPattern(int nPatternNo)
- {
- int i, j;
- for (i = 0; i < m_nSymbleSize; i++)
- {
- for (j = 0; j < m_nSymbleSize; j++)
- {
- if (!(m_byModuleData[j][i] & 0x20))
- { // Exclude a functional module
- int bMask;
- switch (nPatternNo)
- {
- case 0:
- bMask = ((i + j) % 2 == 0);
- break;
- case 1:
- bMask = (i % 2 == 0);
- break;
- case 2:
- bMask = (j % 3 == 0);
- break;
- case 3:
- bMask = ((i + j) % 3 == 0);
- break;
- case 4:
- bMask = (((i / 2) + (j / 3)) % 2 == 0);
- break;
- case 5:
- bMask = (((i * j) % 2) + ((i * j) % 3) == 0);
- break;
- case 6:
- bMask = ((((i * j) % 2) + ((i * j) % 3)) % 2 == 0);
- break;
- default: // case 7:
- bMask = ((((i * j) % 3) + ((i + j) % 2)) % 2 == 0);
- break;
- }
- m_byModuleData[j][i] = (uint8_t)((m_byModuleData[j][i] & 0xfe) | (((m_byModuleData[j][i] & 0x02) > 1) ^ bMask));
- }
- }
- }
- }
- static void SetFormatInfoPattern(int nPatternNo)
- {
- int nFormatInfo;
- int i;
- switch (m_nLevel)
- {
- case QR_LEVEL_L:
- nFormatInfo = 0x08; // 01nnnb
- break;
- case QR_LEVEL_M:
- nFormatInfo = 0x00; // 00nnnb
- break;
- case QR_LEVEL_Q:
- nFormatInfo = 0x18; // 11nnnb
- break;
- default: // case QR_LEVEL_H:
- nFormatInfo = 0x10; // 10nnnb
- break;
- }
- nFormatInfo += nPatternNo;
- int nFormatData = nFormatInfo << 10;
- // Calculated bit remainder
- for (i = 0; i < 5; i++)
- {
- if (nFormatData & (1 << (14 - i)))
- {
- nFormatData ^= (0x0537 << (4 - i)); // 10100110111b
- }
- }
- nFormatData += nFormatInfo << 10;
- // Masking
- nFormatData ^= 0x5412; // 101010000010010b
- // Position detection patterns located around the upper left
- for (i = 0; i <= 5; i++)
- {
- m_byModuleData[8][i] = (nFormatData & (1 << i)) ? '\x30' : '\x20';
- }
- m_byModuleData[8][7] = (nFormatData & (1 << 6)) ? '\x30' : '\x20';
- m_byModuleData[8][8] = (nFormatData & (1 << 7)) ? '\x30' : '\x20';
- m_byModuleData[7][8] = (nFormatData & (1 << 8)) ? '\x30' : '\x20';
- for (i = 9; i <= 14; i++)
- {
- m_byModuleData[14 - i][8] = (nFormatData & (1 << i)) ? '\x30' : '\x20';
- }
- // Position detection patterns located under the upper right corner
- for (i = 0; i <= 7; i++)
- {
- m_byModuleData[m_nSymbleSize - 1 - i][8] = (nFormatData & (1 << i)) ? '\x30' : '\x20';
- }
- // Right lower left position detection patterns located
- m_byModuleData[8][m_nSymbleSize - 8] = '\x30'; // Module fixed dark
- for (i = 8; i <= 14; i++)
- {
- m_byModuleData[8][m_nSymbleSize - 15 + i] = (nFormatData & (1 << i)) ? '\x30' : '\x20';
- }
- }
- static int CountPenalty(void)
- {
- int nPenalty = 0;
- int i, j, k;
- // Column of the same color adjacent module
- for (i = 0; i < m_nSymbleSize; i++)
- {
- for (j = 0; j < m_nSymbleSize - 4; j++)
- {
- int nCount = 1;
- for (k = j + 1; k < m_nSymbleSize; k++)
- {
- if (((m_byModuleData[i][j] & 0x11) == 0) == ((m_byModuleData[i][k] & 0x11) == 0))
- {
- nCount++;
- }
- else
- {
- break;
- }
- }
- if (nCount >= 5)
- {
- nPenalty += 3 + (nCount - 5);
- }
- j = k - 1;
- }
- }
- // Adjacent module line of the same color
- for (i = 0; i < m_nSymbleSize; i++)
- {
- for (j = 0; j < m_nSymbleSize - 4; j++)
- {
- int nCount = 1;
- for (k = j + 1; k < m_nSymbleSize; k++)
- {
- if (((m_byModuleData[j][i] & 0x11) == 0) == ((m_byModuleData[k][i] & 0x11) == 0))
- {
- nCount++;
- }
- else
- {
- break;
- }
- }
- if (nCount >= 5)
- {
- nPenalty += 3 + (nCount - 5);
- }
- j = k - 1;
- }
- }
- // Modules of the same color block (2 ~ 2)
- for (i = 0; i < m_nSymbleSize - 1; i++)
- {
- for (j = 0; j < m_nSymbleSize - 1; j++)
- {
- if ((((m_byModuleData[i][j] & 0x11) == 0) == ((m_byModuleData[i + 1][j] & 0x11) == 0)) &&
- (((m_byModuleData[i][j] & 0x11) == 0) == ((m_byModuleData[i][j + 1] & 0x11) == 0)) &&
- (((m_byModuleData[i][j] & 0x11) == 0) == ((m_byModuleData[i + 1][j + 1] & 0x11) == 0)))
- {
- nPenalty += 3;
- }
- }
- }
- // Pattern (dark dark: light: dark: light) ratio 1:1:3:1:1 in the same column
- for (i = 0; i < m_nSymbleSize; i++)
- {
- for (j = 0; j < m_nSymbleSize - 6; j++)
- {
- if (((j == 0) || (!(m_byModuleData[i][j - 1] & 0x11))) &&
- (m_byModuleData[i][j] & 0x11) &&
- (!(m_byModuleData[i][j + 1] & 0x11)) &&
- (m_byModuleData[i][j + 2] & 0x11) &&
- (m_byModuleData[i][j + 3] & 0x11) &&
- (m_byModuleData[i][j + 4] & 0x11) &&
- (!(m_byModuleData[i][j + 5] & 0x11)) &&
- (m_byModuleData[i][j + 6] & 0x11) &&
- ((j == m_nSymbleSize - 7) || (!(m_byModuleData[i][j + 7] & 0x11))))
- {
- // Clear pattern of four or more before or after
- if (((j < 2 || !(m_byModuleData[i][j - 2] & 0x11)) &&
- (j < 3 || !(m_byModuleData[i][j - 3] & 0x11)) &&
- (j < 4 || !(m_byModuleData[i][j - 4] & 0x11))) ||
- ((j >= m_nSymbleSize - 8 || !(m_byModuleData[i][j + 8] & 0x11)) &&
- (j >= m_nSymbleSize - 9 || !(m_byModuleData[i][j + 9] & 0x11)) &&
- (j >= m_nSymbleSize - 10 || !(m_byModuleData[i][j + 10] & 0x11))))
- {
- nPenalty += 40;
- }
- }
- }
- }
- // Pattern (dark dark: light: dark: light) in the same line ratio 1:1:3:1:1
- for (i = 0; i < m_nSymbleSize; i++)
- {
- for (j = 0; j < m_nSymbleSize - 6; j++)
- {
- if (((j == 0) || (!(m_byModuleData[j - 1][i] & 0x11))) &&
- (m_byModuleData[j][i] & 0x11) &&
- (!(m_byModuleData[j + 1][i] & 0x11)) &&
- (m_byModuleData[j + 2][i] & 0x11) &&
- (m_byModuleData[j + 3][i] & 0x11) &&
- (m_byModuleData[j + 4][i] & 0x11) &&
- (!(m_byModuleData[j + 5][i] & 0x11)) &&
- (m_byModuleData[j + 6][i] & 0x11) &&
- ((j == m_nSymbleSize - 7) || (!(m_byModuleData[j + 7][i] & 0x11))))
- {
- // Clear pattern of four or more before or after
- if (((j < 2 || !(m_byModuleData[j - 2][i] & 0x11)) &&
- (j < 3 || !(m_byModuleData[j - 3][i] & 0x11)) &&
- (j < 4 || !(m_byModuleData[j - 4][i] & 0x11))) ||
- ((j >= m_nSymbleSize - 8 || !(m_byModuleData[j + 8][i] & 0x11)) &&
- (j >= m_nSymbleSize - 9 || !(m_byModuleData[j + 9][i] & 0x11)) &&
- (j >= m_nSymbleSize - 10 || !(m_byModuleData[j + 10][i] & 0x11))))
- {
- nPenalty += 40;
- }
- }
- }
- }
- // The proportion of modules for the entire dark
- int nCount = 0;
- for (i = 0; i < m_nSymbleSize; i++)
- {
- for (j = 0; j < m_nSymbleSize; j++)
- {
- if (!(m_byModuleData[i][j] & 0x11))
- {
- nCount++;
- }
- }
- }
- nPenalty += (abs(50 - ((nCount * 100) / (m_nSymbleSize * m_nSymbleSize))) / 5) * 10;
- return nPenalty;
- }
- static void FormatModule(void)
- {
- int i, j;
- memset(m_byModuleData, 0, sizeof(m_byModuleData));
- // Function module placement
- SetFunctionModule();
- // Data placement
- SetCodeWordPattern();
- if (m_nMaskingNo == -1)
- {
- // Select the best pattern masking
- m_nMaskingNo = 0;
- SetMaskingPattern(m_nMaskingNo); // Masking
- SetFormatInfoPattern(m_nMaskingNo); // Placement pattern format information
- int nMinPenalty = CountPenalty();
- for (i = 1; i <= 7; i++)
- {
- SetMaskingPattern(i); // Masking
- SetFormatInfoPattern(i); // Placement pattern format information
- int nPenalty = CountPenalty();
- if (nPenalty < nMinPenalty)
- {
- nMinPenalty = nPenalty;
- m_nMaskingNo = i;
- }
- }
- }
- SetMaskingPattern(m_nMaskingNo); // Masking
- SetFormatInfoPattern(m_nMaskingNo); // Placement pattern format information
- // The module pattern converted to a Boolean value
- for (i = 0; i < m_nSymbleSize; i++)
- {
- for (j = 0; j < m_nSymbleSize; j++)
- {
- m_byModuleData[i][j] = (uint8_t)((m_byModuleData[i][j] & 0x11) != 0);
- }
- }
- }
- static void putBitToPos(uint32_t pos, int bw, uint8_t *bits)
- {
- if (bw == 0)
- return;
- uint32_t tmp;
- uint32_t bitpos[8] = {128, 64, 32, 16, 8, 4, 2, 1};
- if (pos % 8 == 0)
- {
- tmp = (pos / 8) - 1;
- bits[tmp] = bits[tmp] ^ bitpos[7];
- }
- else
- {
- tmp = pos / 8;
- bits[tmp] = bits[tmp] ^ bitpos[pos % 8 - 1];
- }
- }
- int qr_encode(int level, int version, const char *source, size_t source_len, uint8_t *result)
- {
- int i, j;
- const bool auto_extent = 0;
- m_nLevel = level;
- m_nMaskingNo = -1;
- memset(result, 0, QR_MAX_BITDATA);
- // If the data length is not specified, acquired by lstrlen
- size_t ncLength = source_len > 0 ? source_len : strlen(source);
- if (ncLength == 0)
- {
- return -1; // No data
- }
- // Check version (model number)
- nEncodeVersion = GetEncodeVersion(version, source, ncLength);
- if (nEncodeVersion == 0)
- {
- return -1; // Over-capacity
- }
- if (version == 0)
- {
- // Auto Part
- m_nVersion = nEncodeVersion;
- }
- else
- {
- if (nEncodeVersion <= version)
- {
- m_nVersion = version;
- }
- else
- {
- if (auto_extent)
- {
- m_nVersion = nEncodeVersion; // Automatic extended version (model number)
- }
- else
- {
- return -1; // Over-capacity
- }
- }
- }
- // Terminator addition code "0000"
- int ncDataCodeWord = QR_VersonInfo[m_nVersion].ncDataCodeWord[level];
- int ncTerminater = (ncDataCodeWord * 8) - m_ncDataCodeWordBit;
- if (ncTerminater < 4)
- {
- ncTerminater = 4;
- }
- if (ncTerminater > 0)
- {
- m_ncDataCodeWordBit = SetBitStream(m_ncDataCodeWordBit, 0, ncTerminater);
- }
- // Additional padding code "11101100, 00010001"
- uint8_t byPaddingCode = 0xec;
- for (i = (m_ncDataCodeWordBit + 7) / 8; i < ncDataCodeWord; i++)
- {
- m_byDataCodeWord[i] = byPaddingCode;
- byPaddingCode = (uint8_t)(byPaddingCode == 0xec ? 0x11 : 0xec);
- }
- // Calculated the total clear area code word
- m_ncAllCodeWord = QR_VersonInfo[m_nVersion].ncAllCodeWord;
- memset(m_byAllCodeWord, 0, sizeof(m_byAllCodeWord));
- int nDataCwIndex = 0; // Position data processing code word
- // Division number data block
- int ncBlock1 = QR_VersonInfo[m_nVersion].RS_BlockInfo1[level].ncRSBlock;
- int ncBlock2 = QR_VersonInfo[m_nVersion].RS_BlockInfo2[level].ncRSBlock;
- int ncBlockSum = ncBlock1 + ncBlock2;
- int nBlockNo = 0; // Block number in the process
- // The number of data code words by block
- int ncDataCw1 = QR_VersonInfo[m_nVersion].RS_BlockInfo1[level].ncDataCodeWord;
- int ncDataCw2 = QR_VersonInfo[m_nVersion].RS_BlockInfo2[level].ncDataCodeWord;
- // Code word interleaving data placement
- for (i = 0; i < ncBlock1; i++)
- {
- for (j = 0; j < ncDataCw1; j++)
- {
- m_byAllCodeWord[(ncBlockSum * j) + nBlockNo] = m_byDataCodeWord[nDataCwIndex++];
- }
- nBlockNo++;
- }
- for (i = 0; i < ncBlock2; i++)
- {
- for (j = 0; j < ncDataCw2; j++)
- {
- if (j < ncDataCw1)
- {
- m_byAllCodeWord[(ncBlockSum * j) + nBlockNo] = m_byDataCodeWord[nDataCwIndex++];
- }
- else
- {
- // 2 minute fraction block placement event
- m_byAllCodeWord[(ncBlockSum * ncDataCw1) + i] = m_byDataCodeWord[nDataCwIndex++];
- }
- }
- nBlockNo++;
- }
- // RS code words by block number (currently the same number)
- int ncRSCw1 = QR_VersonInfo[m_nVersion].RS_BlockInfo1[level].ncAllCodeWord - ncDataCw1;
- int ncRSCw2 = QR_VersonInfo[m_nVersion].RS_BlockInfo2[level].ncAllCodeWord - ncDataCw2;
- // RS code word is calculated
- nDataCwIndex = 0;
- nBlockNo = 0;
- for (i = 0; i < ncBlock1; i++)
- {
- memset(m_byRSWork, 0, sizeof(m_byRSWork));
- memmove(m_byRSWork, m_byDataCodeWord + nDataCwIndex, ncDataCw1);
- GetRSCodeWord(m_byRSWork, ncDataCw1, ncRSCw1);
- // RS code word placement
- for (j = 0; j < ncRSCw1; j++)
- {
- m_byAllCodeWord[ncDataCodeWord + (ncBlockSum * j) + nBlockNo] = m_byRSWork[j];
- }
- nDataCwIndex += ncDataCw1;
- nBlockNo++;
- }
- for (i = 0; i < ncBlock2; i++)
- {
- memset(m_byRSWork, 0, sizeof(m_byRSWork));
- memmove(m_byRSWork, m_byDataCodeWord + nDataCwIndex, ncDataCw2);
- GetRSCodeWord(m_byRSWork, ncDataCw2, ncRSCw2);
- // RS code word placement
- for (j = 0; j < ncRSCw2; j++)
- {
- m_byAllCodeWord[ncDataCodeWord + (ncBlockSum * j) + nBlockNo] = m_byRSWork[j];
- }
- nDataCwIndex += ncDataCw2;
- nBlockNo++;
- }
- m_nSymbleSize = m_nVersion * 4 + 17;
- // Module placement
- FormatModule();
- for (i = 0; i < m_nSymbleSize; i++)
- {
- for (j = 0; j < m_nSymbleSize; j++)
- {
- if (!m_byModuleData[i][j])
- {
- putBitToPos((j * m_nSymbleSize) + i + 1, 0, result);
- }
- else
- {
- putBitToPos((j * m_nSymbleSize) + i + 1, 1, result);
- }
- }
- }
- return m_nSymbleSize;
- }
|