2008-06-19 01:52:37 -07:00
//
// DecoderViewController . m
// ZXing
//
// Created by Christian Brunschen on 22 / 05 / 2008.
/ *
2008-06-19 13:56:24 -07:00
* Copyright 2008 ZXing authors
2008-06-19 01:52:37 -07:00
*
* 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 "DecoderViewController.h"
# import "Decoder.h"
# import "NSString+HTML.h"
2008-06-25 06:17:06 -07:00
# import "ResultParser.h"
2008-06-19 01:52:37 -07:00
# import "ParsedResult.h"
# import "ResultAction.h"
# import "Database.h"
# import "ArchiveController.h"
# import "Scan.h"
# import "TwoDDecoderResult.h"
@ implementation DecoderViewController
@ synthesize cameraBarItem ;
@ synthesize libraryBarItem ;
@ synthesize savedPhotosBarItem ;
@ synthesize archiveBarItem ;
@ synthesize actionBarItem ;
@ synthesize messageView ;
@ synthesize resultView ;
@ synthesize imageView ;
@ synthesize toolbar ;
@ synthesize decoder ;
@ synthesize result ;
@ synthesize actions ;
- ( id ) initWithNibName : ( NSString * ) nibNameOrNil bundle : ( NSBundle * ) nibBundleOrNil {
if ( self = [ super initWithNibName : nibNameOrNil bundle : nibBundleOrNil ] ) {
// Initialization code
self . title = @ "ZXing" ;
Decoder * d = [ [ Decoder alloc ] init ] ;
self . decoder = d ;
d . delegate = self ;
[ d release ] ;
}
return self ;
}
// Implement loadView if you want to create a view hierarchy programmatically
- ( void ) loadView {
[ super loadView ] ;
CGRect mViewFrame = self . resultView . bounds ;
UITextView * mView = [ [ UITextView alloc ] initWithFrame : mViewFrame ] ;
mView . backgroundColor = [ UIColor yellowColor ] ;
mView . alpha = 0.95 ;
mView . editable = false ;
mView . scrollEnabled = true ;
mView . autoresizingMask = UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin ;
self . messageView = mView ;
[ mView release ] ;
[ self . resultView addSubview : self . messageView ] ;
[ self updateToolbar ] ;
2008-06-20 06:50:07 -07:00
[ self showMessage : NSLocalizedString ( @ "Please take or choose a picture containing a barcode" , @ "" ) ] ;
2008-06-19 01:52:37 -07:00
}
- ( void ) updateToolbar {
self . cameraBarItem . enabled = [ UIImagePickerController isSourceTypeAvailable : UIImagePickerControllerSourceTypeCamera ] ;
self . savedPhotosBarItem . enabled = [ UIImagePickerController isSourceTypeAvailable : UIImagePickerControllerSourceTypeSavedPhotosAlbum ] ;
self . libraryBarItem . enabled = [ UIImagePickerController isSourceTypeAvailable : UIImagePickerControllerSourceTypePhotoLibrary ] ;
self . archiveBarItem . enabled = true ;
self . actionBarItem . enabled = ( self . result ! = nil ) && ( [ self . result actions ] ! = nil ) && ( [ self . result actions ] . count > 0 ) ;
}
// If you need to do additional setup after loading the view , override viewDidLoad .
- ( void ) viewDidLoad {
[ super viewDidLoad ] ;
}
2008-06-25 06:17:06 -07:00
- ( void ) clearImageView {
imageView . image = nil ;
NSArray * subviews = [ imageView . subviews copy ] ;
for ( UIView * view in subviews ) {
[ view removeFromSuperview ] ;
}
[ subviews release ] ;
}
2008-06-19 01:52:37 -07:00
- ( void ) pickAndDecodeFromSource : ( UIImagePickerControllerSourceType ) sourceType {
self . result = nil ;
2008-06-25 06:17:06 -07:00
[ self clearImageView ] ;
2008-06-19 01:52:37 -07:00
// Create the Image Picker
if ( [ UIImagePickerController isSourceTypeAvailable : sourceType ] ) {
UIImagePickerController * picker = [ [ UIImagePickerController alloc ] init ] ;
picker . sourceType = sourceType ;
picker . delegate = self ;
picker . allowsImageEditing = [ [ NSUserDefaults standardUserDefaults ]
boolForKey : @ "allowEditing" ] ;
// Picker is displayed asynchronously .
[ self presentModalViewController : picker animated : YES ] ;
} else {
NSLog ( @ "Attempted to pick an image with illegal source type '%d'" , sourceType ) ;
}
}
- ( IBAction ) pickAndDecode : ( id ) sender {
UIImagePickerControllerSourceType sourceType ;
int i = [ sender tag ] ;
switch ( i ) {
case 0 : sourceType = UIImagePickerControllerSourceTypeCamera ; break ;
case 1 : sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum ; break ;
case 2 : sourceType = UIImagePickerControllerSourceTypePhotoLibrary ; break ;
default : sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum ;
}
[ self pickAndDecodeFromSource : sourceType ] ;
}
- ( BOOL ) shouldAutorotateToInterfaceOrientation : ( UIInterfaceOrientation ) interfaceOrientation {
// Return YES for supported orientations
2008-06-19 07:02:47 -07:00
return ( interfaceOrientation ! = UIInterfaceOrientationPortraitUpsideDown ) ;
2008-06-19 01:52:37 -07:00
}
- ( 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 {
[ decoder release ] ;
2008-06-25 06:17:06 -07:00
[ self clearImageView ] ;
2008-06-19 01:52:37 -07:00
[ imageView release ] ;
[ actionBarItem release ] ;
[ cameraBarItem release ] ;
[ libraryBarItem release ] ;
[ savedPhotosBarItem release ] ;
[ archiveBarItem release ] ;
[ toolbar release ] ;
[ super dealloc ] ;
}
- ( void ) showMessage : ( NSString * ) message {
2008-06-24 09:24:36 -07:00
# ifdef DEBUG
NSLog ( @ "Showing message '%@'" , message ) ;
# endif
2008-06-19 01:52:37 -07:00
self . messageView . text = message ;
[ self . messageView sizeToFit ] ;
}
// DecoderDelegate methods
- ( void ) decoder : ( Decoder * ) decoder willDecodeImage : ( UIImage * ) image {
2008-06-25 06:17:06 -07:00
[ self clearImageView ] ;
2008-06-19 01:52:37 -07:00
[ self . imageView setImage : image ] ;
2008-06-20 06:50:07 -07:00
[ self showMessage : [ NSString stringWithFormat : NSLocalizedString ( @ "Decoding image (%.0fx%.0f) ..." , @ "shown while image is decoding" ) , image . size . width , image . size . height ] ] ;
2008-06-19 01:52:37 -07:00
}
- ( void ) decoder : ( Decoder * ) decoder
decodingImage : ( UIImage * ) image
usingSubset : ( UIImage * ) subset
progress : ( NSString * ) message {
2008-06-25 06:17:06 -07:00
[ self clearImageView ] ;
2008-06-19 01:52:37 -07:00
[ self . imageView setImage : subset ] ;
[ self showMessage : message ] ;
}
- ( void ) presentResultForString : ( NSString * ) resultString {
2008-06-25 06:17:06 -07:00
self . result = [ ResultParser parsedResultForString : resultString ] ;
2008-06-19 01:52:37 -07:00
[ self showMessage : [ self . result stringForDisplay ] ] ;
self . actions = self . result . actions ;
2008-06-24 09:24:36 -07:00
# ifdef DEBUG
2008-06-19 01:52:37 -07:00
NSLog ( @ "result has %d actions" , actions ? 0 : actions . count ) ;
2008-06-24 09:24:36 -07:00
# endif
2008-06-19 01:52:37 -07:00
[ self updateToolbar ] ;
2008-06-25 06:17:06 -07:00
}
- ( void ) presentResultPoints : ( NSArray * ) resultPoints
forImage : ( UIImage * ) image
usingSubset : ( UIImage * ) subset {
// CGSize imageSize = image . size ;
CGSize subsetSize = subset . size ;
CGRect viewBounds = imageView . bounds ;
float scale = fmin ( viewBounds . size . width / subsetSize . width ,
viewBounds . size . height / subsetSize . height ) ;
float xOffset = ( viewBounds . size . width - scale * subsetSize . width ) / 2.0 ;
float yOffset = ( viewBounds . size . height - scale * subsetSize . height ) / 2.0 ;
NSLog ( @ "(%f, %f) image in view with bounds (%f, %f) x (%f, %f)" ,
subsetSize . width , subsetSize . height ,
viewBounds . origin . x , viewBounds . origin . y ,
viewBounds . size . width , viewBounds . size . height ) ;
NSLog ( @ "xOffset = %f, yOffset = %f, scale = %f" , xOffset , yOffset , scale ) ;
for ( NSValue * pointValue in resultPoints ) {
CGPoint point = [ pointValue CGPointValue ] ;
float x = xOffset + scale * point . x ;
float y = yOffset + scale * point . y ;
NSLog ( @ "have result point @ (%f, %f), imageView point (%f, %f)" , point . x , point . y , x , y ) ;
CGRect frame = CGRectMake ( x - 3 , y - 3 , 7 , 7 ) ;
UIView * pointView = [ [ UIView alloc ] initWithFrame : frame ] ;
pointView . opaque = YES ;
pointView . backgroundColor = [ UIColor greenColor ] ;
pointView . autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight ;
[ imageView addSubview : pointView ] ;
[ pointView release ] ;
}
}
2008-06-19 01:52:37 -07:00
2008-06-25 06:17:06 -07:00
- ( void ) decoder : ( Decoder * ) decoder didDecodeImage : ( UIImage * ) image usingSubset : ( UIImage * ) subset withResult : ( TwoDDecoderResult * ) twoDResult {
2008-06-19 01:52:37 -07:00
[ self presentResultForString : twoDResult . text ] ;
2008-06-25 06:17:06 -07:00
[ self presentResultPoints : twoDResult . points forImage : image usingSubset : subset ] ;
2008-06-19 01:52:37 -07:00
// save the scan to the shared database
[ [ Database sharedDatabase ] addScanWithText : twoDResult . text ] ;
[ self performResultAction : self ] ;
}
2008-06-25 06:17:06 -07:00
- ( void ) decoder : ( Decoder * ) decoder failedToDecodeImage : ( UIImage * ) image usingSubset : ( UIImage * ) subset reason : ( NSString * ) reason {
2008-06-19 01:52:37 -07:00
[ self showMessage : reason ] ;
[ self updateToolbar ] ;
}
// UIImagePickerControllerDelegate methods
- ( void ) imagePickerController : ( UIImagePickerController * ) picker
didFinishPickingImage : ( UIImage * ) image
editingInfo : ( NSDictionary * ) editingInfo
{
2008-06-25 06:17:06 -07:00
UIImage * imageToDecode = image ;
2008-06-24 09:24:36 -07:00
# ifdef DEBUG
2008-06-19 01:52:37 -07:00
NSLog ( @ "picked image size = (%f, %f)" , image . size . width , image . size . height ) ;
2008-06-25 06:17:06 -07:00
# endif
2008-06-19 01:52:37 -07:00
if ( editingInfo ) {
UIImage * originalImage = [ editingInfo objectForKey : UIImagePickerControllerOriginalImage ] ;
if ( originalImage ) {
2008-06-25 06:17:06 -07:00
# ifdef DEBUG
2008-06-19 01:52:37 -07:00
NSLog ( @ "original image size = (%f, %f)" , originalImage . size . width , originalImage . size . height ) ;
2008-06-25 06:17:06 -07:00
# endif
NSValue * cropRectValue = [ editingInfo objectForKey : UIImagePickerControllerCropRect ] ;
if ( cropRectValue ) {
CGRect cropRect = [ cropRectValue CGRectValue ] ;
# ifdef DEBUG
NSLog ( @ "crop rect = (%f, %f) x (%f, %f)" , CGRectGetMinX ( cropRect ) , CGRectGetMinY ( cropRect ) , CGRectGetWidth ( cropRect ) , CGRectGetHeight ( cropRect ) ) ;
# endif
UIGraphicsBeginImageContext ( cropRect . size ) ;
[ originalImage drawAtPoint : CGPointMake ( - CGRectGetMinX ( cropRect ) ,
- CGRectGetMinY ( cropRect ) ) ] ;
imageToDecode = UIGraphicsGetImageFromCurrentImageContext ( ) ;
UIGraphicsEndImageContext ( ) ;
}
2008-06-19 01:52:37 -07:00
}
}
[ [ picker parentViewController ] dismissModalViewControllerAnimated : YES ] ;
2008-06-25 06:17:06 -07:00
[ imageToDecode retain ] ;
2008-06-19 01:52:37 -07:00
[ picker release ] ;
2008-06-25 06:17:06 -07:00
[ self . decoder decodeImage : imageToDecode ] ;
[ imageToDecode release ] ;
2008-06-19 01:52:37 -07:00
[ self updateToolbar ] ;
}
- ( void ) imagePickerControllerDidCancel : ( UIImagePickerController * ) picker
{
[ picker dismissModalViewControllerAnimated : YES ] ;
[ picker release ] ;
[ self updateToolbar ] ;
}
- ( void ) navigationController : ( UINavigationController * ) navigationController
didShowViewController : ( UIViewController * ) viewController
animated : ( BOOL ) animated {
// no - op
}
- ( void ) navigationController : ( UINavigationController * ) navigationController
willShowViewController : ( UIViewController * ) viewController
animated : ( BOOL ) animated {
// no - op
}
2008-06-24 07:18:11 -07:00
- ( void ) performAction : ( ResultAction * ) action {
[ action performActionWithController : self shouldConfirm : NO ] ;
}
- ( void ) confirmAndPerformAction : ( ResultAction * ) action {
[ action performActionWithController : self shouldConfirm : YES ] ;
}
2008-06-19 01:52:37 -07:00
- ( IBAction ) performResultAction : ( id ) sender {
if ( self . result = = nil ) {
NSLog ( @ "no result to perform an action on!" ) ;
return ;
}
if ( self . actions = = nil || self . actions . count = = 0 ) {
NSLog ( @ "result has no actions to perform!" ) ;
return ;
}
if ( self . actions . count = = 1 ) {
ResultAction * action = [ self . actions lastObject ] ;
2008-06-24 09:24:36 -07:00
# ifdef DEBUG
2008-06-19 01:52:37 -07:00
NSLog ( @ "Result has the single action, (%@) '%@', performing it" ,
NSStringFromClass ( [ action class ] ) , [ action title ] ) ;
2008-06-24 09:24:36 -07:00
# endif
2008-06-24 07:18:11 -07:00
[ self performSelector : @ selector ( confirmAndPerformAction : )
withObject : action
2008-06-19 01:52:37 -07:00
afterDelay : 0.0 ] ;
} else {
2008-06-24 09:24:36 -07:00
# ifdef DEBUG
2008-06-19 01:52:37 -07:00
NSLog ( @ "Result has multiple actions, popping up an action sheet" ) ;
2008-06-24 09:24:36 -07:00
# endif
2008-06-19 01:52:37 -07:00
UIActionSheet * actionSheet = [ [ UIActionSheet alloc ] initWithFrame : self . view . bounds ] ;
for ( ResultAction * action in self . actions ) {
[ actionSheet addButtonWithTitle : [ action title ] ] ;
}
2008-06-20 06:50:07 -07:00
int cancelIndex = [ actionSheet addButtonWithTitle : NSLocalizedString ( @ "Cancel" , @ "" ) ] ;
2008-06-19 01:52:37 -07:00
actionSheet . cancelButtonIndex = cancelIndex ;
actionSheet . delegate = self ;
[ actionSheet showFromToolbar : self . toolbar ] ;
}
}
- ( void ) actionSheet : ( UIActionSheet * ) actionSheet clickedButtonAtIndex : ( NSInteger ) buttonIndex {
if ( buttonIndex < self . actions . count ) {
int actionIndex = buttonIndex ;
ResultAction * action = [ self . actions objectAtIndex : actionIndex ] ;
2008-06-24 07:18:11 -07:00
[ self performSelector : @ selector ( performAction : )
withObject : action
2008-06-19 01:52:37 -07:00
afterDelay : 0.0 ] ;
}
}
- ( IBAction ) showArchive : ( id ) sender {
ArchiveController * archiveController = [ [ ArchiveController alloc ] initWithDecoderViewController : self ] ;
[ [ self navigationController ] pushViewController : archiveController animated : true ] ;
[ archiveController release ] ;
}
- ( void ) showScan : ( Scan * ) scan {
2008-06-25 06:17:06 -07:00
[ self clearImageView ] ;
2008-06-19 01:52:37 -07:00
[ self presentResultForString : scan . text ] ;
2008-06-24 03:04:08 -07:00
[ [ self navigationController ] popToViewController : self animated : YES ] ;
2008-06-19 01:52:37 -07:00
}
@ end