// // ZebraScanViewController.m // ZebraScan // // Created by Simon Urbanek on 2/19/09. // Copyright __MyCompanyName__ 2009. All rights reserved. // #import "ZebraScanViewController.h" #import "TCPConnection.h" #if 0 @interface CameraController : NSObject { } + (CameraController*) sharedInstance; - (void) capturePhoto; - (void) setDelegate: (NSObject*) delegate; @end #endif static void zebra_image_data_handler(zebra_image_t *image, const void *userdata) { ZebraScanViewController *zc = (ZebraScanViewController*) userdata; const zebra_symbol_t *sym = zebra_image_first_symbol(image); NSLog(@"zi-handler invoked"); int n = 0; for(; sym; sym = zebra_symbol_next(sym)) { if(zebra_symbol_get_count(sym)) continue; zebra_symbol_type_t type = zebra_symbol_get_type(sym); zc->textView.text = [zc->textView.text stringByAppendingFormat: @"%s%s:%s\n", zebra_get_symbol_name(type), zebra_get_addon_name(type), zebra_symbol_get_data(sym)]; NSLog(@"barcode result: %s%s:%s", zebra_get_symbol_name(type), zebra_get_addon_name(type), zebra_symbol_get_data(sym)); n++; } } static void free_zebra_image(zebra_image_t *zi) { NSLog(@"free_zebra_image called"); } static CGContextRef CreateY8BitmapContext (CGImageRef inImage) { CGContextRef context = NULL; CGColorSpaceRef colorSpace; void * bitmapData; int bitmapByteCount; int bitmapBytesPerRow; // Get image width, height. We'll use the entire image. size_t pixelsWide = CGImageGetWidth(inImage); size_t pixelsHigh = CGImageGetHeight(inImage); // Declare the number of bytes per row. Each pixel in the bitmap in this // example is represented by 4 bytes; 8 bits each of red, green, blue, and // alpha. bitmapBytesPerRow = pixelsWide; bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); // Use the generic RGB color space. colorSpace = CGColorSpaceCreateDeviceGray(); //(kCGColorSpaceGenericGray); if (colorSpace == NULL) { fprintf(stderr, "Error allocating color space\n"); return NULL; } // Allocate memory for image data. This is the destination in memory // where any drawing to the bitmap context will be rendered. bitmapData = malloc( bitmapByteCount ); if (bitmapData == NULL) { fprintf (stderr, "Memory not allocated!"); CGColorSpaceRelease( colorSpace ); return NULL; } // Create the bitmap context. We want pre-multiplied ARGB, 8-bits // per component. Regardless of what the source image format is // (CMYK, Grayscale, and so on) it will be converted over to the format // specified here by CGBitmapContextCreate. context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8, // bits per component bitmapBytesPerRow, colorSpace, kCGImageAlphaNone); if (context == NULL) { free (bitmapData); fprintf (stderr, "Context not created!"); } // Make sure and release colorspace before returning CGColorSpaceRelease( colorSpace ); return context; } #define fourcc(a, b, c, d) \ ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) @implementation ZebraScanViewController /* // The designated initializer. Override to perform setup that is required before the view is loaded. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { // Custom initialization } return self; } */ /* // Implement loadView to create a view hierarchy programmatically, without using a nib. - (void)loadView { } */ // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; scanner = zebra_image_scanner_create(); zebra_image_scanner_set_data_handler(scanner, zebra_image_data_handler, self); textView.text = @"ZebraScan loaded\n"; } /* // Override to allow orientations other than the default portrait orientation. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } */ - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview // Release anything that's not essential, such as cached data } - (void)dealloc { [super dealloc]; } // Implement this method in your code to do something with the image. - (void)useImage:(UIImage*)theImage { CGImageRef cgi = [theImage CGImage]; // Create the bitmap context CGContextRef cgctx = CreateY8BitmapContext(cgi); if (cgctx == NULL) return; // Get image width, height. We'll use the entire image. size_t w = CGImageGetWidth(cgi); size_t h = CGImageGetHeight(cgi); CGRect rect = {{0,0},{w,h}}; // Draw the image to the bitmap context. Once we draw, the memory // allocated for the context for rendering will then contain the // raw image data in the specified color space. CGContextDrawImage(cgctx, rect, cgi); // Now we can get a pointer to the image data associated with the bitmap // context. void *data = CGBitmapContextGetData(cgctx); if (data != NULL) { NSLog(@"got data (%d x %d)", w, h); unsigned char dmin = 255, dmax = 0, *d = (unsigned char*) data, *ds = d + w * h; while (d < ds) { if (*d > dmax) dmax = *d; if (*d < dmin) dmin = *d; d++; } NSLog(@" - range: %d - %d", (int)dmin, (int)dmax); if (dmax - dmin > 0) { /* proceed only if the image is not completely blank */ int dmid = ((int) dmax + (int) dmin) / 2; if (dmax - dmin < 255) { // unsigned int k = 0xff80 / (dmax - dmin); NSLog(@" - increasing constrast"); for (d = (unsigned char*) data; d < ds; d++) { int v = 128 + (((int) *d) - dmid) * 2; if (v < 0) v = 0; else if (v > 255) v = 255; *d = (unsigned char) v; } } #ifdef LOG_SCANS NSLog(@" - send to server"); TCPConnection *conn = [TCPConnection connectToHost:[NSHost hostWithName:@"urbanek.info"] port:1174 error:nil]; if (conn) { [conn write:data maxLength:w * h]; [conn close]; } #endif NSLog(@" - creating zebra image"); zebra_image_t *zi = zebra_image_create(); zebra_image_set_size(zi, w, h); zebra_image_set_format(zi, fourcc('Y','8','0','0')); // that is the only format natively supported by zebra zebra_image_set_data(zi, data, w * h, free_zebra_image); NSLog(@"calling zebra scanner"); int r = zebra_scan_image(scanner, zi); textView.text = [textView.text stringByAppendingFormat:@" scanner result: %d\n", r]; NSLog(@" - scanner result: %d", r); NSLog(@"scanner done, releasing image"); zebra_image_destroy(zi); } } // When finished, release the context CGContextRelease(cgctx); // Free image data memory for the context -- nope, zebra will do it //if (data) free(data); } - (void)imagePickerController:(UIImagePickerController *)aPicker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo { if (aPicker != picker) return; // ignore unknown pickers textView.text = @"picker delivered an image, processing\n"; [self useImage:image]; // Remove the picker interface and release the picker object. [[picker parentViewController] dismissModalViewControllerAnimated:YES]; [picker release]; picker = nil; textView.text = [textView.text stringByAppendingString:@"picker dismissed after delivering an image\n"]; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)aPicker { if (aPicker != picker) return; // ignore unknown pickers [[picker parentViewController] dismissModalViewControllerAnimated:YES]; [picker release]; picker = nil; textView.text = @"picker dismissed with cancel\n"; } - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { } - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { } - (BOOL)respondsToSelector:(SEL)aSelector { BOOL res = [UIViewController instancesRespondToSelector:aSelector]; NSLog(@"respondsToSelector: %@ -> %@", NSStringFromSelector(aSelector), res ? @"yes" : @"no"); return res; } - (IBAction) showCamera: (id) sender { #if 0 CameraController *cc = [CameraController sharedInstance]; NSLog(@"shared camera: %@", cc); if (cc) { NSLog(@" - set delegate"); [cc setDelegate:self]; NSLog(@" - capture photo"); [cc capturePhoto]; NSLog(@" - done"); } #else if (picker) { textView.text = @"showCamera: picker already present, ignoring"; return; } picker = [[ZSCameraController alloc] init]; picker.sourceType = UIImagePickerControllerSourceTypeCamera; picker.delegate = self; picker.allowsImageEditing = NO; [self presentModalViewController:picker animated:YES]; #endif } @end