123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- /*
- * 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 "ZXByteArray.h"
- #import "ZXDecodeHints.h"
- #import "ZXDecoderResult.h"
- #import "ZXErrors.h"
- #import "ZXGenericGF.h"
- #import "ZXIntArray.h"
- #import "ZXMaxiCodeBitMatrixParser.h"
- #import "ZXMaxiCodeDecodedBitStreamParser.h"
- #import "ZXMaxiCodeDecoder.h"
- #import "ZXReedSolomonDecoder.h"
-
- const int ZX_MAXI_CODE_ALL = 0;
- const int ZX_MAXI_CODE_EVEN = 1;
- const int ZX_MAXI_CODE_ODD = 2;
-
- @interface ZXMaxiCodeDecoder ()
-
- @property (nonatomic, strong, readonly) ZXReedSolomonDecoder *rsDecoder;
-
- @end
-
- @implementation ZXMaxiCodeDecoder
-
- - (id)init {
- if (self = [super init]) {
- _rsDecoder = [[ZXReedSolomonDecoder alloc] initWithField:[ZXGenericGF MaxiCodeField64]];
- }
-
- return self;
- }
-
- - (ZXDecoderResult *)decode:(ZXBitMatrix *)bits error:(NSError **)error {
- return [self decode:bits hints:nil error:error];
- }
-
- - (ZXDecoderResult *)decode:(ZXBitMatrix *)bits hints:(ZXDecodeHints *)hints error:(NSError **)error {
- ZXMaxiCodeBitMatrixParser *parser = [[ZXMaxiCodeBitMatrixParser alloc] initWithBitMatrix:bits error:error];
- if (!parser) {
- return nil;
- }
- ZXByteArray *codewords = [parser readCodewords];
-
- if (![self correctErrors:codewords start:0 dataCodewords:10 ecCodewords:10 mode:ZX_MAXI_CODE_ALL error:error]) {
- return nil;
- }
- int mode = codewords.array[0] & 0x0F;
- ZXByteArray *datawords;
- switch (mode) {
- case 2:
- case 3:
- case 4:
- if (![self correctErrors:codewords start:20 dataCodewords:84 ecCodewords:40 mode:ZX_MAXI_CODE_EVEN error:error]) {
- return nil;
- }
- if (![self correctErrors:codewords start:20 dataCodewords:84 ecCodewords:40 mode:ZX_MAXI_CODE_ODD error:error]) {
- return nil;
- }
- datawords = [[ZXByteArray alloc] initWithLength:94];
- break;
- case 5:
- if (![self correctErrors:codewords start:20 dataCodewords:68 ecCodewords:56 mode:ZX_MAXI_CODE_EVEN error:error]) {
- return nil;
- }
- if (![self correctErrors:codewords start:20 dataCodewords:68 ecCodewords:56 mode:ZX_MAXI_CODE_ODD error:error]) {
- return nil;
- }
- datawords = [[ZXByteArray alloc] initWithLength:78];
- break;
- default:
- if (error) *error = ZXNotFoundErrorInstance();
- return nil;
- }
-
- for (int i = 0; i < 10; i++) {
- datawords.array[i] = codewords.array[i];
- }
- for (int i = 20; i < datawords.length + 10; i++) {
- datawords.array[i - 10] = codewords.array[i];
- }
-
- return [ZXMaxiCodeDecodedBitStreamParser decode:datawords mode:mode];
- }
-
- - (BOOL)correctErrors:(ZXByteArray *)codewordBytes start:(int)start dataCodewords:(int)dataCodewords
- ecCodewords:(int)ecCodewords mode:(int)mode error:(NSError **)error {
- int codewords = dataCodewords + ecCodewords;
-
- // in EVEN or ODD mode only half the codewords
- int divisor = mode == ZX_MAXI_CODE_ALL ? 1 : 2;
-
- // First read into an array of ints
- ZXIntArray *codewordsInts = [[ZXIntArray alloc] initWithLength:codewords / divisor];
- for (int i = 0; i < codewords; i++) {
- if ((mode == ZX_MAXI_CODE_ALL) || (i % 2 == (mode - 1))) {
- codewordsInts.array[i / divisor] = codewordBytes.array[i + start] & 0xFF;
- }
- }
-
- NSError *decodeError = nil;
- if (![self.rsDecoder decode:codewordsInts twoS:ecCodewords / divisor error:&decodeError]) {
- if (decodeError.code == ZXReedSolomonError && error) {
- *error = ZXChecksumErrorInstance();
- }
- return NO;
- }
- // Copy back into array of bytes -- only need to worry about the bytes that were data
- // We don't care about errors in the error-correction codewords
- for (int i = 0; i < dataCodewords; i++) {
- if ((mode == ZX_MAXI_CODE_ALL) || (i % 2 == (mode - 1))) {
- codewordBytes.array[i + start] = (int8_t) codewordsInts.array[i / divisor];
- }
- }
-
- return YES;
- }
-
- @end
|