/* * Copyright 2012 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #import "ZXBitMatrix.h" #import "ZXQRCodeDataMask.h" /** * 000: mask bits for which (x + y) mod 2 == 0 */ @interface ZXDataMask000 : ZXQRCodeDataMask @end @implementation ZXDataMask000 - (BOOL)isMasked:(int)i j:(int)j { return ((i + j) & 0x01) == 0; } @end /** * 001: mask bits for which x mod 2 == 0 */ @interface ZXDataMask001 : ZXQRCodeDataMask @end @implementation ZXDataMask001 - (BOOL)isMasked:(int)i j:(int)j { return (i & 0x01) == 0; } @end /** * 010: mask bits for which y mod 3 == 0 */ @interface ZXDataMask010 : ZXQRCodeDataMask @end @implementation ZXDataMask010 - (BOOL)isMasked:(int)i j:(int)j { return j % 3 == 0; } @end /** * 011: mask bits for which (x + y) mod 3 == 0 */ @interface ZXDataMask011 : ZXQRCodeDataMask @end @implementation ZXDataMask011 - (BOOL)isMasked:(int)i j:(int)j { return (i + j) % 3 == 0; } @end /** * 100: mask bits for which (x/2 + y/3) mod 2 == 0 */ @interface ZXDataMask100 : ZXQRCodeDataMask @end @implementation ZXDataMask100 - (BOOL)isMasked:(int)i j:(int)j { return (((i / 2) + (j /3)) & 0x01) == 0; } @end /** * 101: mask bits for which xy mod 2 + xy mod 3 == 0 */ @interface ZXDataMask101 : ZXQRCodeDataMask @end @implementation ZXDataMask101 - (BOOL)isMasked:(int)i j:(int)j { int temp = i * j; return (temp & 0x01) + (temp % 3) == 0; } @end /** * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0 */ @interface ZXDataMask110 : ZXQRCodeDataMask @end @implementation ZXDataMask110 - (BOOL)isMasked:(int)i j:(int)j { int temp = i * j; return (((temp & 0x01) + (temp % 3)) & 0x01) == 0; } @end /** * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0 */ @interface ZXDataMask111 : ZXQRCodeDataMask @end @implementation ZXDataMask111 - (BOOL)isMasked:(int)i j:(int)j { return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0; } @end @implementation ZXQRCodeDataMask /** * See ISO 18004:2006 6.8.1 */ static NSArray *DATA_MASKS = nil; /** * Implementations of this method reverse the data masking process applied to a QR Code and * make its bits ready to read. */ - (void)unmaskBitMatrix:(ZXBitMatrix *)bits dimension:(int)dimension { for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { if ([self isMasked:i j:j]) { [bits flipX:j y:i]; } } } } - (BOOL)isMasked:(int)i j:(int)j { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)] userInfo:nil]; } + (ZXQRCodeDataMask *)forReference:(int)reference { if (!DATA_MASKS) { DATA_MASKS = @[[[ZXDataMask000 alloc] init], [[ZXDataMask001 alloc] init], [[ZXDataMask010 alloc] init], [[ZXDataMask011 alloc] init], [[ZXDataMask100 alloc] init], [[ZXDataMask101 alloc] init], [[ZXDataMask110 alloc] init], [[ZXDataMask111 alloc] init]]; } if (reference < 0 || reference > 7) { [NSException raise:NSInvalidArgumentException format:@"Invalid reference value"]; } return DATA_MASKS[reference]; } @end