Last active
November 13, 2017 07:33
-
-
Save johanhar/a421a14bef2f06ee2340 to your computer and use it in GitHub Desktop.
uic-918-3 aztec barcode decoding ios objective-c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// add this method to ZXAztecDecoder.m (ZXingObjC) | |
+ (NSString *)UIC9183TicketId:(ZXBoolArray *)correctedBits | |
{ | |
NSMutableData *bytes = [[NSMutableData alloc] init]; | |
int endIndex = (int)correctedBits.length; | |
ZXAztecTable latchTable = ZXAztecTableUpper; // table most recently latched to | |
ZXAztecTable shiftTable = ZXAztecTableUpper; // table to use for the next read | |
int index = 0; | |
int byteIndex = 0; | |
while (index < endIndex) { | |
if (shiftTable == ZXAztecTableBinary) { | |
if (endIndex - index < 5) { | |
break; | |
} | |
int length = [self readCode:correctedBits startIndex:index length:5]; | |
index += 5; | |
if (length == 0) { | |
if (endIndex - index < 11) { | |
break; | |
} | |
length = [self readCode:correctedBits startIndex:index length:11] + 31; | |
index += 11; | |
} | |
for (int charCount = 0; charCount < length; charCount++) { | |
if (endIndex - index < 8) { | |
index = endIndex; // Force outer loop to exit | |
break; | |
} | |
int code = [self readCode:correctedBits startIndex:index length:8]; | |
// deflated content starts from byte 68 according to UIC-918-3 | |
if (byteIndex >= 68) { | |
unsigned char compressedBytes[1]; | |
compressedBytes[0] = (unsigned char)code; | |
[bytes appendBytes:compressedBytes length:1]; | |
} | |
index += 8; | |
byteIndex++; | |
} | |
// Go back to whatever mode we had been in | |
shiftTable = latchTable; | |
} else { | |
int size = shiftTable == ZXAztecTableDigit ? 4 : 5; | |
if (endIndex - index < size) { | |
break; | |
} | |
int code = [self readCode:correctedBits startIndex:index length:size]; | |
index += size; | |
NSString *str = [self character:shiftTable code:code]; | |
if ([str hasPrefix:@"CTRL_"]) { | |
// Table changes | |
shiftTable = [self table:[str characterAtIndex:5]]; | |
if ([str characterAtIndex:6] == 'L') { | |
latchTable = shiftTable; | |
} | |
} else { | |
byteIndex++; | |
// Go back to whatever mode we had been in | |
shiftTable = latchTable; | |
} | |
} | |
} | |
NSData *inflated1 = [[bytes copy] inflateWithMissingHeader:YES]; | |
NSData *inflated2 = [[bytes copy] inflateWithMissingHeader:NO]; | |
NSString *inflatedString; | |
NSMutableString *ticketID = [[NSMutableString alloc] init]; | |
if (inflated1.length > 0) { | |
inflatedString = [[NSString alloc] initWithData:inflated1 encoding:NSUTF8StringEncoding]; | |
} else if (inflated2.length > 0) { | |
inflatedString = [[NSString alloc] initWithData:inflated2 encoding:NSUTF8StringEncoding]; | |
} | |
// we find the UIC-918-3 ticket id in the inflated content from 16 to 35 | |
// it will always be 20 bytes long, so we need to eliminate null-characters and whatnot | |
if (inflatedString.length > 36) { | |
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\w+" | |
options:0 | |
error:nil]; | |
NSRange textRange = NSMakeRange(16, 20); | |
NSRange matchRange = [regex rangeOfFirstMatchInString:inflatedString | |
options:NSMatchingReportProgress | |
range:textRange]; | |
if (matchRange.location != NSNotFound) { | |
[ticketID appendString:[inflatedString substringWithRange:matchRange]]; | |
} | |
} | |
return [ticketID copy]; | |
} | |
// inflating (NSData category) | |
- (NSData *)inflateWithMissingHeader:(BOOL)missingHeader | |
{ | |
if ([self length] == 0) return self; | |
NSInteger full_length = [self length]; | |
NSInteger half_length = [self length] / 2; | |
NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; | |
BOOL done = NO; | |
int status; | |
z_stream strm; | |
strm.next_in = (Bytef *)[self bytes]; | |
strm.avail_in = (unsigned int)[self length]; | |
strm.total_out = 0; | |
strm.zalloc = Z_NULL; | |
strm.zfree = Z_NULL; | |
if (missingHeader) { | |
if (inflateInit2(&strm, -15) != Z_OK) return nil; | |
} else { | |
if (inflateInit2(&strm, (15+32)) != Z_OK) return nil; | |
} | |
while (!done) | |
{ | |
// Make sure we have enough room and reset the lengths. | |
if (strm.total_out >= [decompressed length]) | |
[decompressed increaseLengthBy: half_length]; | |
strm.next_out = [decompressed mutableBytes] + strm.total_out; | |
strm.avail_out = (unsigned int)([decompressed length] - strm.total_out); | |
// Inflate another chunk. | |
status = inflate (&strm, Z_SYNC_FLUSH); | |
if (status == Z_STREAM_END) done = YES; | |
else if (status != Z_OK) break; | |
} | |
if (inflateEnd (&strm) != Z_OK) return nil; | |
// Set real length. | |
if (done) | |
{ | |
[decompressed setLength: strm.total_out]; | |
return [NSData dataWithData: decompressed]; | |
} | |
else return nil; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment