123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /*
- * qrencode - QR Code encoder
- *
- * Masking for Micro QR Code.
- * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #if HAVE_CONFIG_H
- # include "config.h"
- #endif
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
- #include <errno.h>
- #include "qrencode.h"
- #include "mqrspec.h"
- #include "mmask.h"
- #define STATIC_IN_RELEASE
- STATIC_IN_RELEASE void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
- {
- unsigned int format;
- unsigned char v;
- int i;
- format = MQRspec_getFormatInfo(mask, version, level);
- for(i = 0; i < 8; i++) {
- v = 0x84 | (format & 1);
- frame[width * (i + 1) + 8] = v;
- format = format >> 1;
- }
- for(i = 0; i < 7; i++) {
- v = 0x84 | (format & 1);
- frame[width * 8 + 7 - i] = v;
- format = format >> 1;
- }
- }
- #define MASKMAKER(__exp__) \
- int x, y;\
- \
- for(y = 0; y < width; y++) {\
- for(x = 0; x < width; x++) {\
- if(*s & 0x80) {\
- *d = *s;\
- } else {\
- *d = *s ^ ((__exp__) == 0);\
- }\
- s++; d++;\
- }\
- }
- static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
- {
- MASKMAKER(y&1)
- }
- static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
- {
- MASKMAKER(((y/2)+(x/3))&1)
- }
- static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
- {
- MASKMAKER((((x*y)&1)+(x*y)%3)&1)
- }
- static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
- {
- MASKMAKER((((x+y)&1)+((x*y)%3))&1)
- }
- #define maskNum (4)
- typedef void MaskMaker(int, const unsigned char *, unsigned char *);
- static MaskMaker *maskMakers[maskNum] = {
- Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
- };
- #ifdef WITH_TESTS
- unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
- {
- unsigned char *masked;
- masked = (unsigned char *)malloc((size_t)(width * width));
- if(masked == NULL) return NULL;
- maskMakers[mask](width, frame, masked);
- return masked;
- }
- #endif
- unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
- {
- unsigned char *masked;
- int width;
- if(mask < 0 || mask >= maskNum) {
- errno = EINVAL;
- return NULL;
- }
- width = MQRspec_getWidth(version);
- masked = (unsigned char *)malloc((size_t)(width * width));
- if(masked == NULL) return NULL;
- maskMakers[mask](width, frame, masked);
- MMask_writeFormatInformation(version, width, masked, mask, level);
- return masked;
- }
- STATIC_IN_RELEASE int MMask_evaluateSymbol(int width, unsigned char *frame)
- {
- int x, y;
- unsigned char *p;
- int sum1 = 0, sum2 = 0;
- p = frame + width * (width - 1);
- for(x = 1; x < width; x++) {
- sum1 += (p[x] & 1);
- }
- p = frame + width * 2 - 1;
- for(y = 1; y < width; y++) {
- sum2 += (*p & 1);
- p += width;
- }
- return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
- }
- unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
- {
- int i;
- unsigned char *mask, *bestMask;
- int maxScore = 0;
- int score;
- int width;
- width = MQRspec_getWidth(version);
- mask = (unsigned char *)malloc((size_t)(width * width));
- if(mask == NULL) return NULL;
- bestMask = NULL;
- for(i = 0; i < maskNum; i++) {
- score = 0;
- maskMakers[i](width, frame, mask);
- MMask_writeFormatInformation(version, width, mask, i, level);
- score = MMask_evaluateSymbol(width, mask);
- if(score > maxScore) {
- maxScore = score;
- free(bestMask);
- bestMask = mask;
- mask = (unsigned char *)malloc((size_t)(width * width));
- if(mask == NULL) break;
- }
- }
- free(mask);
- return bestMask;
- }
|