diff options
Diffstat (limited to 'iphone/ZBarImage.m')
-rw-r--r-- | iphone/ZBarImage.m | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/iphone/ZBarImage.m b/iphone/ZBarImage.m new file mode 100644 index 0000000..f723e7a --- /dev/null +++ b/iphone/ZBarImage.m @@ -0,0 +1,306 @@ +//------------------------------------------------------------------------ +// Copyright 2009-2010 (c) Jeff Brown <spadix@users.sourceforge.net> +// +// This file is part of the ZBar Bar Code Reader. +// +// The ZBar Bar Code Reader is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// The ZBar Bar Code Reader is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser Public License for more details. +// +// You should have received a copy of the GNU Lesser Public License +// along with the ZBar Bar Code Reader; if not, write to the Free +// Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// http://sourceforge.net/projects/zbar +//------------------------------------------------------------------------ + +#import <UIKit/UIKit.h> +#import <ZBarSDK/ZBarImage.h> +#import "debug.h" + +static void image_cleanup(zbar_image_t *zimg) +{ + ZBarImage *image = zbar_image_get_userdata(zimg); + [image cleanup]; +} + +@implementation ZBarImage + +@dynamic format, sequence, size, crop, data, dataLength, symbols, zbarImage, + UIImage; + ++ (unsigned long) fourcc: (NSString*) format +{ + return(zbar_fourcc_parse([format UTF8String])); +} + +- (id) initWithImage: (zbar_image_t*) image +{ + if(!image) { + [self release]; + return(nil); + } + if(self = [super init]) { + zimg = image; + zbar_image_ref(image, 1); + zbar_image_set_userdata(zimg, self); + } + return(self); +} + +- (id) init +{ + zbar_image_t *image = zbar_image_create(); + self = [self initWithImage: image]; + zbar_image_ref(image, -1); + return(self); +} + +- (void) dealloc +{ + if(zimg) { + zbar_image_ref(zimg, -1); + zimg = NULL; + } + [super dealloc]; +} + +- (id) initWithCGImage: (CGImageRef) image + crop: (CGRect) crop + size: (CGSize) size +{ + if(!(self = [self init])) + return(nil); + uint64_t t_start = timer_now(); + + unsigned int w = size.width + 0.5; + unsigned int h = size.height + 0.5; + + unsigned long datalen = w * h; + uint8_t *raw = malloc(datalen); + if(!raw) { + [self release]; + return(nil); + } + + zbar_image_set_data(zimg, raw, datalen, zbar_image_free_data); + zbar_image_set_format(zimg, zbar_fourcc('Y','8','0','0')); + zbar_image_set_size(zimg, w, h); + + // scale and crop simultaneously + CGFloat scale = size.width / crop.size.width; + crop.origin.x *= -scale; + crop.size.width = scale * (CGFloat)CGImageGetWidth(image); + scale = size.height / crop.size.height; + CGFloat height = CGImageGetHeight(image); + // compensate for wacky origin + crop.origin.y = height - crop.origin.y - crop.size.height; + crop.origin.y *= -scale; + crop.size.height = scale * height; + + // generate grayscale image data + CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray(); + CGContextRef ctx = + CGBitmapContextCreate(raw, w, h, 8, w, cs, kCGImageAlphaNone); + CGColorSpaceRelease(cs); + CGContextSetAllowsAntialiasing(ctx, 0); + + CGContextDrawImage(ctx, crop, image); + +#if 0 + zlog(@"convert image %dx%d: crop %g,%g %gx%g size %gx%g (%dx%d)", + CGImageGetWidth(image), CGImageGetHeight(image), + crop.origin.x, crop.origin.y, crop.size.width, crop.size.height, + size.width, size.height, w, h); + CGImageRef cgdump = CGBitmapContextCreateImage(ctx); + UIImage *uidump = [[UIImage alloc] + initWithCGImage: cgdump]; + CGImageRelease(cgdump); + UIImageWriteToSavedPhotosAlbum(uidump, nil, nil, NULL); + [uidump release]; +#endif + + CGContextRelease(ctx); + + t_convert = timer_elapsed(t_start, timer_now()); + return(self); +} + +- (id) initWithCGImage: (CGImageRef) image + size: (CGSize) size +{ + CGRect crop = CGRectMake(0, 0, + CGImageGetWidth(image), + CGImageGetHeight(image)); + return([self initWithCGImage: image + crop: crop + size: size]); +} + +- (id) initWithCGImage: (CGImageRef) image +{ + CGRect crop = CGRectMake(0, 0, + CGImageGetWidth(image), + CGImageGetHeight(image)); + return([self initWithCGImage: image + crop: crop + size: crop.size]); +} + +- (zbar_image_t*) image +{ + return(zimg); +} + +- (unsigned long) format +{ + return(zbar_image_get_format(zimg)); +} + +- (void) setFormat: (unsigned long) format +{ + zbar_image_set_format(zimg, format); +} + +- (unsigned) sequence +{ + return(zbar_image_get_sequence(zimg)); +} + +- (void) setSequence: (unsigned) seq +{ + zbar_image_set_sequence(zimg, seq); +} + +- (CGSize) size +{ + unsigned w, h; + zbar_image_get_size(zimg, &w, &h); + return(CGSizeMake(w, h)); +} + +- (void) setSize: (CGSize) size +{ + zbar_image_set_size(zimg, size.width + .5, size.height + .5); +} + +- (CGRect) crop +{ + unsigned x, y, w, h; + zbar_image_get_crop(zimg, &x, &y, &w, &h); + return(CGRectMake(x, y, w, h)); +} + +- (void) setCrop: (CGRect) crop +{ + zbar_image_set_crop(zimg, crop.origin.x + .5, crop.origin.y + .5, + crop.size.width + .5, crop.size.height + .5); +} + +- (ZBarSymbolSet*) symbols +{ + return([[[ZBarSymbolSet alloc] + initWithSymbolSet: zbar_image_get_symbols(zimg)] + autorelease]); +} + +- (void) setSymbols: (ZBarSymbolSet*) symbols +{ + zbar_image_set_symbols(zimg, [symbols zbarSymbolSet]); +} + +- (const void*) data +{ + return(zbar_image_get_data(zimg)); +} + +- (unsigned long) dataLength +{ + return(zbar_image_get_data_length(zimg)); +} + +- (void) setData: (const void*) data + withLength: (unsigned long) length +{ + zbar_image_set_data(zimg, data, length, image_cleanup); +} + +- (zbar_image_t*) zbarImage +{ + return(zimg); +} + +- (UIImage*) UIImageWithOrientation: (UIImageOrientation) orient +{ + unsigned long format = self.format; + size_t bpc, bpp; + switch(format) + { + case zbar_fourcc('R','G','B','3'): + bpc = 8; + bpp = 24; + break; + case zbar_fourcc('R','G','B','4'): + bpc = 8; + bpp = 32; + break; + case zbar_fourcc('R','G','B','Q'): + bpc = 5; + bpp = 16; + break; + default: + NSLog(@"ERROR: format %.4s(%08lx) is unsupported", + (char*)&format, format); + assert(0); + return(nil); + }; + + unsigned w = zbar_image_get_width(zimg); + unsigned h = zbar_image_get_height(zimg); + const void *data = zbar_image_get_data(zimg); + size_t datalen = zbar_image_get_data_length(zimg); + CGDataProviderRef datasrc = + CGDataProviderCreateWithData(self, data, datalen, (void*)CFRelease); + CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); + CGImageRef cgimg = + CGImageCreate(w, h, bpc, bpp, ((bpp + 7) >> 3) * w, cs, + kCGBitmapByteOrderDefault | + kCGImageAlphaNoneSkipFirst, + datasrc, NULL, YES, kCGRenderingIntentDefault); + CGColorSpaceRelease(cs); + CGDataProviderRelease(datasrc); + + UIImage *uiimg = + [UIImage imageWithCGImage: cgimg + scale: 1 + orientation: orient]; + CGImageRelease(cgimg); + return(uiimg); +} + +- (UIImage*) UIImage +{ + return([self UIImageWithOrientation: UIImageOrientationUp]); +} + +- (void) cleanup +{ +} + +#if 0 +- (ZBarImage*) convertToFormat: (unsigned long) format +{ + zbar_image_t *zdst = zbar_image_convert(zimg, format); + ZBarImage *image = ; + return([[[ZBarImage alloc] initWithImage: zdst] autorelease]); +} +#endif + +@end |