Using ZXing in OSX to get QRCode data - objective-c

I'm looking to implement a class that will be able to read a QR Code from a file (jpeg, bmp, whatever) and output that information as an NSString.
The problem I'm having is that every project seems to revolve around getting the iPhone to do this with the camera.
I am looking to do this on an OSX Desktop with an Image File. I've attempted to use the Objective-C OSX project included with ZXing, but I have been unable to get it to play nice with my own projects.
Has anybody had any success in doing this? Thanks!

So here was what I came up with and it seems to work for me.
- (NSString*) movieFrameAsString:(CGImageRef)targetMovieFrame
{
#try
{
ZXCGImageLuminanceSource* luminancesource = [[ZXCGImageLuminanceSource alloc] initWithCGImage:targetMovieFrame];
ZXHybridBinarizer* binarizerInput = [[ZXHybridBinarizer alloc] init];
[binarizerInput initWithSource:luminancesource];
ZXBinaryBitmap* binarybitmapInput = [[ZXBinaryBitmap alloc] initWithBinarizer:binarizerInput];
ZXDecodeHints* decodehints = [[ZXDecodeHints alloc] init];
ZXQRCodeReader* qrcodereader = [[ZXQRCodeReader alloc] init];
ZXResult* results = [qrcodereader decode:binarybitmapInput hints:decodehints];
[luminancesource release];
[binarizerInput release];
[binarybitmapInput release];
[decodehints release];
[qrcodereader release];
return [results text];
}
#catch (ZXReaderException* rex)
{
if (![rex.reason isEqualToString:#"Could not find three finder patterns"])
{
//NSLog(#"failed to decode, caught ReaderException '%#'", rex.reason);
}
}
#catch (ZXIllegalArgumentException* iex)
{
//NSLog(#"failed to decode, caught IllegalArgumentException '%#'", iex.reason);
}
#catch (id ue)
{
//NSLog(#"Caught unknown exception: %#", ue);
}
return 0;
}
The targetMovieFrame is brought in, it runs it through the cocktail of filters to produce a binary image. It produces results by decoding the image using hints, and using a method included in the QRCodeReader object. Then I return the results, which is an NSString. Everything else is just exceptions being caught and returned.

Related

can't load Safari contentBlocker. because can't access app group's NSUserDefault

I am making iOS 9 Safari AdBlocker app.
I am using the module of AdBlockPlusSafari.
App works good on simulator.
But when try to run it on device(iPhone6), it fails to reload contentBlocker.
[SFContentBlockerManager
reloadContentBlockerWithIdentifier:self.contentBlockerIdentifier
completionHandler:^(NSError *error) {
if (error) {
NSLog(#"Error in reloadContentBlocker: %#", error);
}
dispatch_async(dispatch_get_main_queue(), ^{
wSelf.reloading = NO;
[wSelf checkActivatedFlag];
if (completion) {
completion(error);
}
});
}];
it gives error
Error Domain=ContentBlockerErrorDomain Code=3 "(null)"
It caused by accessing the values in NSUserDefault (App Group).
- (instancetype)init
{
if (self = [super init])
{
_bundleName = [[[[[NSBundle mainBundle] bundleIdentifier] componentsSeparatedByString:#"."] subarrayWithRange:NSMakeRange(0, 2)] componentsJoinedByString:#"."];
NSString *group = [NSString stringWithFormat:#"group.%#.%#", _bundleName, #"AdBlockerPro"];
NSLog(#"Group name: %#", group);
_adblockProDetails = [[NSUserDefaults alloc] initWithSuiteName:group];
[_adblockProDetails registerDefaults:
#{ AdblockProActivated: #NO,
AdblockProEnabled: #YES
}];
_enabled = [_adblockProDetails boolForKey:AdblockProEnabled];
_activated = [_adblockProDetails boolForKey:AdblockProActivated];
}
return self;
}
The App Group name in host app and safari extension is same.
But in Safari extension, when app accesses the setting in NSUserDefault, it gives me the error.
In Project setting/Capabilities, I did all for App Group. In app id, it involves app group name exactly.
This happens on only device. On simulator, it works good. I can't find the reason of this error.
Please help me if you are experienced this.
Looking forward to your help.
I found the reason myself.
I have put something (NSMutableDictionary) in app group container and did something to write file to extension bundle.
It is prohibited by Apple.
So I deleted all from AdBlockManager (interacts with app group) except flag variables (Boolean type).
And I proceeded the file management using NSFileManager.
http://www.atomicbird.com/blog/sharing-with-app-extensions
Finally, app extension is working for me on device.
Good luck!

EXC_BAD_ACCESS using iCloud on multiple devices

I'm creating an app with iCloud. But I have some problem. It creates directory on iCloud using NSFileWrapper, then it creates NSData (container) file in NSFileWrapper directory. I'm using this code to convert NSFileWrapper to NSMutableArray:
NSFileWrapper *MyWrapper=[[[MyDocument data] fileWrappers] objectForKey:#"myFile.doh"];
    NSData *MyData=[NSData dataWithData:[MyWrapper regularFileContents]];
    NSMutableArray *MyList=[NSPropertyListSerialization propertyListFromData:MyData mutabilityOption:NSPropertyListMutableContainers format:nil errorDescription:nil];
And it works correctly only on the device, which has created this container. On other devices the result of this code is BAD_ACCESS (in the second line of the code, where I start doing something with data). While debugging, function "regularFileContents" returns correct object with correct data size, but when I try to read this data, BAD_ACEESS(code=10) happens.
I'm using ARC, so it's not an error of memory management.
May be the problem is in some project/code sign settings? Any ideas?
Thanks!
I ran into this as well and after much experimentation I've found that even though the outer wrapper has downloaded the inner contents have not actually downloaded yet and that causes the call to regularFileContents to fail.
I've been calling startDownloadingUbiquitousItemAtURL on MyWrapper and once that completes the error is gone. Here's a method that checks the downloaded status of a file (assuming you know the url to your MyWrapper) and starts the download if it isn't downloaded yet.
-(BOOL)downloadFileIfNotAvailable:(NSURL*)fileURL
{
NSNumber *isInCloud = nil;
if ([fileURL getResourceValue:&isInCloud forKey:NSURLIsUbiquitousItemKey error:nil])
{
if ([isInCloud boolValue]) {
NSNumber *isDownloaded = nil;
if ([fileURL getResourceValue:&isDownloaded forKey:NSURLUbiquitousItemIsDownloadedKey error:nil])
{
if ([isDownloaded boolValue])
{
return YES;
}
NSError *error = nil;
[[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:fileURL error:&error];
if (error)
{
NSLog(#"Download Failed :: %#", error);
}
return NO;
}
}
}
return YES;
}

Calling Obj-C Code from JavaScript via Console: Arguments get dropped?

Having a heck of a time with this one.
I've got a super-simple Cocoa app containing one WebView, a WebScripting API defined in the page, and a single NSObject defined on that API. When I turn on the debugger tools (in the embedded WebView), I can see the API on the JavaScript window object, and I can see my "api" property defined on that -- but when I call the API's "get" method, the arguments aren't being serialized -- when the Obj-C method gets called, the arguments are missing. See below, which hopefully illustrates:
I've combed through the docs, I've (apparently) set the appropriate methods to expose everything that needs to be exposed, and I can see the method being called. There has to be something stupid I'm missing, but as a relative newbie to this environment, I'm not seeing it.
Thanks in advance for your help!
Have you set WebKitDeveloperExtras to YES in your default user defaults when you send -[NSUserDefaults registerDefaults:]?
Depending on what version of Xcode you're using you could be getting a known error. If you're using LLDB on anything but the most recent version, it might not be giving you the right variables in the debugger. The solution has been to use GDB instead of LLDB until Apple fixes the problem. But I think they fixed the problem in the latest version. I'd change the debugger to use GDB and see if you're getting the right variables in Xcode. (Product-> Edit Scheme...-> Run -> Debugger). I came across this problem in iOS, though, so I don't know its applicability to OSX. Worth a try anyway.
I originally came across the problem here: https://stackoverflow.com/a/9485349/1147934
I process javascript in the main thread of my app from a local file stored in the apps directory. I check for beginning and ending tokens for the js functions I am executing and whether the function contains a variable.
Hopefully this can give you some good ideas for your issue. You could also do alerts in the js to see if the values post correctly as you run the app (I am sure you thought of that already, but it's worth mentioning.) Happy coding! I hope this helps!
in the .h file define:
NSMutableString *processedCommand;
NSArray *commandArguments;
In the .m file:
// tokens
#define kOpenToken #"<%%"
#define kCloseToken #"%%>"
// this will throw
-(void)executeJScriptCommand:(NSString *)aCommand {
[self performSelectorOnMainThread:#selector(executeThisCommand:) withObject:aCommand waitUntilDone:YES];
}
// this will throw
-(NSString *)executeCommand:(NSString *)command {
NSString *aCommand = [[[command stringByReplacingOccurrencesOfString:kOpenToken withString:#""]
stringByReplacingOccurrencesOfString:kCloseToken withString:#""]
stringByTrimmingLeadingAndTrailingWhitespaces];
if ([aCommand hasPrefix:#"="])
{
// variable. get value
[self getVariableFromCommand:aCommand];
}
else {
[self executeThisCommand:aCommand];
}
NSString *returnValue = [NSString stringWithString:processedCommand];
self.processedCommand = nil;
self.commandArguments = nil;
return returnValue;
}
-(void)executeThisCommand:(NSString *)aCommand {
BOOL hasError = NO;
// clear result
self.processedCommand = nil;
self.commandArguments = nil;
BOOL isFromJS = NO;
NSString *function = nil;
NSMutableArray *commandParts = nil;
#try {
// first, break the command into its parts and extract the function that needs to be called, and the (optional) arguments
commandParts = [[NSMutableArray alloc] initWithArray:[aCommand componentsSeparatedByString:#":"]];
if ([[[commandParts objectAtIndex:0] lowercaseString] isEqualToString:#"js-call"]) {
isFromJS = YES;
[commandParts removeObjectAtIndex:0];
}
// get our function, arguments
function = [[commandParts objectAtIndex:0] retain];
[commandParts removeObjectAtIndex:0];
if ([commandParts count] > 0){
if (isFromJS == YES) {
NSString *arguments = [[commandParts objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([arguments length] > 0) {
self.commandArguments = [arguments JSONValue];
}
}
else {
self.commandArguments = [NSArray arrayWithArray:commandParts];
}
}
// build invoke
SEL sel = NSSelectorFromString(function);
if ([self respondsToSelector:sel]) {
[self performSelectorOnMainThread:sel withObject:nil waitUntilDone:YES];
// using invocation causes a SIGABORT because the try/catch block was not catching the exception.
// using perform selector fixed the problem (i.e., the try/catch block now correctly catches the exception, as expected)
}
else {
[appDelegate buildNewExceptionWithName:#"" andMessage:[NSString stringWithFormat:#"Object does not respond to selector %#", function]];
}
}
#catch (NSException * e) {
hasError = YES;
[self updateErrorMessage:[NSString stringWithFormat:#"Error processing command %#: %#", aCommand, [e reason]]];
}
#finally {
[function release];
[commandParts release];
}
if (hasError == YES) {
[appDelegate buildNewExceptionWithName:#"executeThisCommand" andMessage:self.errorMessage];
}
}
// this can return nil
-(NSString *)getQueryStringValue:(NSString *)name {
NSString *returnValue = nil;
if (queryString != nil) {
returnValue = [queryString objectForKey:[name lowercaseString]];
}
return returnValue;
}

QTCaptureDecompressedVideoOutput with FireWire

I'm trying to create a custom patch for Quartz Composer that captures from a FireWire input. I can open the device and add the input successfully. I even disable the audio inputs as per the QTKit documentation. I suspect my problem is either adding the output (although it adds without error). Every time the frame runs it crashes when it appears the imageBuffer is empty. It has no dimensions or anything. I'm using the standard captureOutput:didOutputVideoFrame:withSampleBuffer:fromConnection from the documentation.
[mCaptureDecompressedVideoOutput release];
mCaptureDecompressedVideoOutput = [[QTCaptureDecompressedVideoOutput alloc] init];
NSLog(#"allocated mCaptureDecompressedVideoOutput");
[mCaptureDecompressedVideoOutput setPixelBufferAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferOpenGLCompatibilityKey,
[NSNumber numberWithLong:k32ARGBPixelFormat], kCVPixelBufferPixelFormatTypeKey, nil]];
[mCaptureDecompressedVideoOutput setDelegate:self];
success = [mCaptureSession addOutput:mCaptureDecompressedVideoOutput error:&error];
if (!success) {
NSLog(#"Failed to add output");
self.outputImage = nil;
if (mCaptureSession) {
[mCaptureSession release];
mCaptureSession= nil;
}
if (mCaptureDeviceInput) {
[mCaptureDeviceInput release];
mCaptureDeviceInput= nil;
}
if (mCaptureDecompressedVideoOutput) {
[mCaptureDecompressedVideoOutput release];
mCaptureDecompressedVideoOutput= nil;
}
return YES;
}
[mCaptureSession startRunning];
_currentDevice= self.inputDevice;
}
CVImageBufferRef imageBuffer = CVBufferRetain(mCurrentImageBuffer);
if (imageBuffer) {
CVPixelBufferLockBaseAddress(imageBuffer, 0);
NSLog(#"ColorSpace: %#", CVImageBufferGetColorSpace(imageBuffer));
id provider= [context outputImageProviderFromBufferWithPixelFormat:QCPlugInPixelFormatARGB8
pixelsWide:CVPixelBufferGetWidth(imageBuffer)
pixelsHigh:CVPixelBufferGetHeight(imageBuffer)
baseAddress:CVPixelBufferGetBaseAddress(imageBuffer)
bytesPerRow:CVPixelBufferGetBytesPerRow(imageBuffer)
releaseCallback:_BufferReleaseCallback
releaseContext:imageBuffer
colorSpace:CVImageBufferGetColorSpace(imageBuffer)
shouldColorMatch:YES];
What could I be doing wrong? This code works great for video only inputs, but not for FireWire (muxed) inputs.
I managed to get this patch to work with both Video and Muxed inputs by removing the kCVPixelBufferOpenGLCompatibilityKey from mCaptureDecompressedVideoOutput. While that allows the patch to work perfectly inside Quartz Composer, my intent is to run this patch in a composition that is used inside CamTwist, which appears not to need OpenGL support. Right now, it just displays a black screen with wither Video or Muxed inputs, where it was working with Video inputs before. So, I'm going to convert my CVImageBufferRef to an OpenGL texture and see if I can get that to work with
outputImageProviderFromTextureWithPixelFormat:pixelsWide:pixelsHigh:name:flipped:releaseCallback:releaseContext:colorSpace:shouldColorMatch

AssetsLibrary does not get images saved in the Camera roll when I run the program on the device

I wrote a simple iOS program to get number of photo images which are saved in the camera roll by using 'Assets Library' framework provided in the SDK4.2.
The program worked well as I expected when I ran it on the iPhone simulator.
But, it didn't retrieve any images when I ran on the 'real' iPhone device (iPhone 3GS with iOS 4.2.1).
This problem looks like as same as the problem discussed in the below article:
Assets Library Framework not working correctly on 4.0 and 4.2
So, I added the "dispatch_async(dispatch_get_main_queue()..." function as below, But I couldn't solve the problem.
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray assets = [[NSMutableArray array] retain]; // Prepare array to have retrieved images by Assets Library.
void (^assetEnumerator)(struct ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) {
if(asset != NULL) {
[assets addObject:asset];
dispatch_async(dispatch_get_main_queue(), ^{
// show number of retrieved images saved in the Camera role.
// The [assets count] returns always 0 when I run this program on iPhone device although it worked OK on the simulator.
NSLog(#"%i", [assets count]);
});
}
};
void (^assetGroupEnumerator)(struct ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) {
if(group != nil) {
[group enumerateAssetsUsingBlock:assetEnumerator];
}
};
// Create instance of the Assets Library.
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos // Retrieve the images saved in the Camera role.
usingBlock:assetGroupEnumerator
failureBlock: ^(NSError *error) {
NSLog(#"Failed.");
}];
}
Could you please tell me if you have any ideas to solve it?
I have 1 update:
To get error code, I modified the failureBlock of the enumerateGroupsWithTypes as below, and then reproduced the symptom again.
Then, the app returned the error code -3311 (ALAssetsLibraryAccessUserDeniedError).
However I didn't any operation to deny while my reproducing test.
What's the possible cause of the err#=-3311?
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
usingBlock:assetGroupEnumerator
failureBlock: ^(NSError *error) {
NSLog(#"Failed");
resultMsg = [NSString stringWithFormat:#"Failed: code=%d", [error code]]; }];
It is strange that location services should be involved when accessing saved photos. Maybe it has to do with geo-tagging information on the photos. Anyways Apple says that enabling location services is required when using enumerateGroupsWithTypes:usingBlock:failureBlock:
Special Considerations
This method will fail with error ALAssetsLibraryAccessGloballyDeniedError if the user has not enabled Location Services (in Settings > General)."