LeadSuccess - 2013-11-11

As time was really short, we did the following ourselves:

download the sources of ZBar, beeing prepared to modify it for our needs :-(

Looking into it, we realised, that in the C object zbar_symbol_t that's wrapped within Objective-C ZBarSymbol the char attribute named data (copied into ZBarSymbol.data) obviously includes all bytes of the scan, as there's also an unsigned int attribute named datalen; so it's irrelevant if data contains nulls, as long as it's read up to datalen.

Luckily Obj-C ZBarSymbol also has a property named zbarSymbol of type const zbar_symbol_t*. So we use that directly.

But there's another problem:
obviously when ZBar gets binary data, it assumes, those come encoded with ISO 8859-1 - like defined in http://en.wikipedia.org/wiki/QR_code
but that also means, many characters come coded with more than one byte - blowing up the real binary data, that was in the QR, with a lot of useless bytes between.
Our "solution" here is to convert into a cString from NSISOLatin1 (which is ISO 8859-1).
And as it only can be done without nulls, there has to be a loop over all chunks ending with a null, collected into a NSMutableData.
And as the first 7 characters include some sign telling us that it's a vCard that's compressed or/and encoded, we start from the 8th character.

The code:
(scanResult is one - we only use the first - ZBarSymbol from reader's ZBarSymbolSet, which has to be extracted somehow (see the doku) from the second parameter of
imagePickerController:didFinishPickingMediaWithInfo)

//=====
NSString * strdata = [scanResult data];
bool convertible = [strdata canBeConvertedToEncoding:NSISOLatin1StringEncoding]; // for the safety
NSInteger start = 7;
NSString * header = [strdata substringToIndex:start] // we use that later to decide how to decompress/decode
, * part;
const zbar_symbol_t * rawobj = [scanResult zbarSymbol];
char * rawdata = rawobj->data;
unsigned int lenght = rawobj->datalen;
const char * encod;
NSMutableData * result = [NSMutableData dataWithLength:0];

for (int i = start; i < lenght; i++) {
if (!rawdata[i]) { // 00
if (convertible) {
part = [NSString stringWithUTF8String:rawdata+start]; // goes up to 00
encod = [part cStringUsingEncoding:NSISOLatin1StringEncoding];
[result appendBytes:encod length:strlen(encod)+1]; // +1 to include ending 00
}
else
[result appendBytes:rawdata+start length:i-start];
start = i + 1;
}
}
// if there's a rest not terminated with null
if (start < length) {
// do nearly the same as above, just not to a 00 but to the end
...
}
//=====

for rawobj to compile we also had to redefine <ouch!>
. typedef struct point_s
. typedef int refcnt_t
. struct zbar_symbol_s
like in the underlying sources.

Well, can it be done more elegant?
Is this just a workaround - or is it the intention behind ZBarSymbol's property zbarSymbol?
Should ZBar offer another property of type NSData, besides the NSString data?
At least it works for us!