/XeeImageIOLoader.m
Objective C | 284 lines | 221 code | 60 blank | 3 comment | 40 complexity | f3e144a5e485e3aa3fac258e8dc16346 MD5 | raw file
1#import "XeeImageIOLoader.h" 2#import "XeeCGImage.h" 3 4 5@implementation XeeImageIOImage 6 7static size_t XeeImageIOGetBytes(void *info, void *buffer, size_t count) { return [(CSHandle *)info readAtMost:count toBuffer:buffer]; } 8static void XeeImageIOSkipBytes(void *info, size_t count) { [(CSHandle *)info skipBytes:count]; } 9static void XeeImageIORewind(void *info) { [(CSHandle *)info seekToFileOffset:0]; } 10static void XeeImageIOReleaseInfo(void *info) { [(CSHandle *)info release]; } 11 12+(NSArray *)fileTypes 13{ 14 return [NSBitmapImageRep imageFileTypes]; 15} 16 17+(BOOL)canOpenFile:(NSString *)name firstBlock:(NSData *)block attributes:(NSDictionary *)attributes 18{ 19 return floor(NSAppKitVersionNumber)>NSAppKitVersionNumber10_3; 20} 21 22-(SEL)initLoader 23{ 24 source=NULL; 25 26 NSMutableDictionary *options=[NSMutableDictionary dictionaryWithObjectsAndKeys: 27 [NSNumber numberWithBool:YES],kCGImageSourceShouldAllowFloat, 28 nil]; 29 30 if(ref) 31 { 32 NSString *type=[(NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 33 (CFStringRef)[[self filename] pathExtension],CFSTR("public.data")) autorelease]; 34 //if([type isEqual:(NSString *)kUTTypePICT]) return NULL; 35 [options setObject:type forKey:(NSString *)kCGImageSourceTypeIdentifierHint]; 36 } 37 38 39// CGDataProviderRef provider=CGDataProviderCreateWithURL((CFURLRef)[NSURL fileURLWithPath:[self filename]]); 40 CGDataProviderCallbacks callbacks= 41 { XeeImageIOGetBytes,XeeImageIOSkipBytes,XeeImageIORewind,XeeImageIOReleaseInfo }; 42 CGDataProviderRef provider=CGDataProviderCreate([[self handle] retain],&callbacks); 43 if(!provider) return NULL; 44 45 source=CGImageSourceCreateWithDataProvider(provider,(CFDictionaryRef)options); 46 CGDataProviderRelease(provider); 47 if(!source) return NULL; 48 49 NSDictionary *cgproperties=[(id)CGImageSourceCopyPropertiesAtIndex(source,0,(CFDictionaryRef)options) autorelease]; 50 if(!cgproperties) return NULL; 51 52 width=[[cgproperties objectForKey:(NSString *)kCGImagePropertyPixelWidth] intValue]; 53 height=[[cgproperties objectForKey:(NSString *)kCGImagePropertyPixelHeight] intValue]; 54 55 [self setDepthForImage:self properties:cgproperties]; 56 [self setFormat:[self formatForType:(NSString *)CGImageSourceGetType(source)]]; 57 58 NSNumber *orientnum=[cgproperties objectForKey:(NSString *)kCGImagePropertyOrientation]; 59 if(orientnum) [self setCorrectOrientation:[orientnum intValue]]; 60 61 [properties addObjectsFromArray:[self convertCGProperties:cgproperties]]; 62 63 current_image=0; 64 65 if(thumbonly) return @selector(loadThumbnail); 66 return @selector(loadImage); 67} 68 69-(void)deallocLoader 70{ 71 if(source) CFRelease(source); 72} 73 74-(SEL)loadImage 75{ 76 int count=CGImageSourceGetCount(source); 77 if(current_image==count) return @selector(loadThumbnail); 78 79 NSDictionary *options=[NSDictionary dictionaryWithObjectsAndKeys: 80 [NSNumber numberWithBool:YES],kCGImageSourceShouldAllowFloat, 81 [NSNumber numberWithBool:NO],kCGImageSourceShouldCache, 82 nil]; 83 84 CGImageRef cgimage=CGImageSourceCreateImageAtIndex(source,current_image++,(CFDictionaryRef)options); 85 if(!cgimage) return @selector(loadImage); 86 87 NSDictionary *cgproperties=[(id)CGImageSourceCopyPropertiesAtIndex(source,current_image-1,(CFDictionaryRef)options) autorelease]; 88 89 CFStringRef colormodel=(CFStringRef)[cgproperties objectForKey:(NSString *)kCGImagePropertyColorModel]; 90 NSNumber *isindexed=[cgproperties objectForKey:(NSString *)kCGImagePropertyIsIndexed]; 91 NSNumber *hasalpha=[cgproperties objectForKey:(NSString *)kCGImagePropertyHasAlpha]; 92 //int framedepth=[[cgproperties objectForKey:(NSString *)kCGImagePropertyDepth] intValue]; 93 94 XeeBitmapImage *image=nil; 95 96 if(colormodel!=kCGImagePropertyColorModelCMYK&&colormodel!=kCGImagePropertyColorModelLab 97 &&!(isindexed&&[isindexed boolValue])) 98 { 99 image=[[[XeeCGImage alloc] initWithCGImage:cgimage] autorelease]; 100 101 NSNumber *photometric=[[cgproperties objectForKey:@"{TIFF}"] objectForKey:@"PhotometricInterpretation"]; 102 if(photometric&&[photometric intValue]==0) [(XeeCGImage *)image invertImage]; 103 } 104 105 if(!image) 106 { 107 int type; 108 if(hasalpha&&[hasalpha boolValue]) type=XeeBitmapTypePremultipliedARGB8; 109 else if(colormodel==kCGImagePropertyColorModelGray) type=XeeBitmapTypeLuma8; 110 else type=XeeBitmapTypeNRGB8; 111 112 int pixelwidth=CGImageGetWidth(cgimage); 113 int pixelheight=CGImageGetHeight(cgimage); 114 115 image=[[[XeeBitmapImage alloc] initWithType:type width:pixelwidth height:pixelheight] autorelease]; 116 117 if(image) 118 { 119 CGContextRef cgcontext=[image createCGContext]; 120 if(cgcontext) 121 { 122 CGContextDrawImage(cgcontext,CGRectMake(0,0,pixelwidth,pixelheight),cgimage); 123 CGContextRelease(cgcontext); 124 } 125 else image=nil; 126 } 127 } 128 129 CGImageRelease(cgimage); 130 131 if(!image) return @selector(loadImage); 132 133 [self setDepthForImage:image properties:cgproperties]; 134 135 NSNumber *orientnum=[cgproperties objectForKey:(NSString *)kCGImagePropertyOrientation]; 136 if(orientnum) [image setCorrectOrientation:[orientnum intValue]]; 137 138 [self addSubImage:image]; 139 [image setCompleted]; 140 141 return @selector(loadImage); 142} 143 144-(SEL)loadThumbnail 145{ 146 loaded=!thumbonly; 147 148 NSDictionary *options=[NSDictionary dictionaryWithObjectsAndKeys: 149 [NSNumber numberWithBool:NO],kCGImageSourceShouldCache, 150 [NSNumber numberWithBool:thumbonly],kCGImageSourceCreateThumbnailFromImageIfAbsent, 151 nil]; 152 153 CGImageRef cgimage=CGImageSourceCreateThumbnailAtIndex(source,0,(CFDictionaryRef)options); 154 if(!cgimage) return NULL; 155 156 NSDictionary *cgproperties=[(id)CGImageSourceCopyPropertiesAtIndex(source,0,(CFDictionaryRef)options) autorelease]; 157 XeeCGImage *image=[[[XeeCGImage alloc] initWithCGImage:cgimage] autorelease]; 158 159 NSNumber *photometric=[[cgproperties objectForKey:@"{TIFF}"] objectForKey:@"PhotometricInterpretation"]; 160 if(photometric&&[photometric intValue]==0) [image invertImage]; 161 162 CGImageRelease(cgimage); 163 164 if(!image) return NULL; 165 166 [self setDepthForImage:image properties:cgproperties]; 167 [self addSubImage:image]; 168 [image setCompleted]; 169 170 loaded=YES; 171 return NULL; 172} 173 174-(void)setDepthForImage:(XeeImage *)image properties:(NSDictionary *)cgproperties 175{ 176 CFStringRef colormodel=(CFStringRef)[cgproperties objectForKey:(NSString *)kCGImagePropertyColorModel]; 177 NSNumber *indexednum=[cgproperties objectForKey:(NSString *)kCGImagePropertyIsIndexed]; 178 NSNumber *floatnum=[cgproperties objectForKey:(NSString *)kCGImagePropertyIsFloat]; 179 NSNumber *alphanum=[cgproperties objectForKey:(NSString *)kCGImagePropertyHasAlpha]; 180 int framedepth=[[cgproperties objectForKey:(NSString *)kCGImagePropertyDepth] intValue]; 181 BOOL isindexed=indexednum&&[indexednum boolValue]; 182 BOOL isfloat=floatnum&&[floatnum boolValue]; 183 BOOL hasalpha=alphanum&&[alphanum boolValue]; 184 185 if(isindexed) [image setDepthIndexed:1<<framedepth]; 186 else if(colormodel==kCGImagePropertyColorModelGray) [image setDepthGrey:framedepth alpha:hasalpha floating:isfloat]; 187 else if(colormodel==kCGImagePropertyColorModelRGB) [image setDepthRGB:framedepth alpha:hasalpha floating:isfloat]; 188 else if(colormodel==kCGImagePropertyColorModelCMYK) [image setDepthCMYK:framedepth alpha:hasalpha]; 189 else if(colormodel==kCGImagePropertyColorModelLab) [image setDepthLab:framedepth alpha:hasalpha]; 190} 191 192-(NSString *)formatForType:(NSString *)type 193{ 194 static NSDictionary *formatdict=nil; 195 if(!formatdict) formatdict=[[NSDictionary dictionaryWithObjectsAndKeys: 196 @"TIFF",@"public.tiff", 197 @"BMP",@"com.microsoft.bmp", 198 @"GIF",@"com.compuserve.gif", 199 @"JPEG",@"public.jpeg", 200 @"PICT",@"com.apple.pict", 201 @"PNG",@"public.png", 202 @"QTIF",@"com.apple.quicktime-image", 203 @"TGA",@"com.truevision.tga-image", 204 @"SGI",@"com.sgi.sgi-image", 205 @"PSD",@"com.adobe.photoshop-image", 206 @"PNTG",@"com.apple.macpaint-image", 207 @"FPX",@"com.kodak.flashpix-image", 208 @"JPEG2000",@"public.jpeg-2000", 209 @"ICO",@"com.microsoft.ico", 210 @"XBM",@"public.xbitmap-image", 211 @"EXR",@"com.ilm.openexr-image", 212 @"Fax",@"public.fax", 213 @"Icns",@"com.apple.icns", 214 @"Radiance",@"public.radiance", 215 @"PCX",@"cx.c3.pcx", 216 @"IFF ILBM",@"com.ea.iff-ilbm", 217 @"DNG",@"com.adobe.raw-image", 218 @"Leica",@"com.leica.raw-image", 219 @"RAW",@"com.panasonic.raw-image", 220 @"DCR",@"com.kodak.raw-image", 221 @"CR2",@"com.canon.cr2-raw-image", 222 @"CRW",@"com.canon.crw-raw-image", 223 @"MRW",@"com.konicaminolta.raw-image", 224 @"RAF",@"com.fuji.raw-image", 225 @"NEF",@"com.nikon.raw-image", 226 @"ORF",@"com.olympus.raw-image", 227 @"SRF",@"com.sony.raw-image", 228 @"PEF",@"com.pentax.raw-image", 229 nil] retain]; 230 231 NSString *shortformat=[formatdict objectForKey:type]; 232 if(shortformat) return shortformat; 233 else return type; 234} 235 236-(NSArray *)convertCGProperties:(NSDictionary *)cgproperties 237{ 238 NSMutableArray *array=[NSMutableArray array]; 239 NSBundle *imageio=[NSBundle bundleWithIdentifier:@"com.apple.ImageIO.framework"]; 240 241 NSEnumerator *enumerator=[cgproperties keyEnumerator]; 242 NSString *key; 243 while(key=[enumerator nextObject]) 244 { 245 id value=[cgproperties objectForKey:key]; 246 if(![value isKindOfClass:[NSDictionary class]]) continue; 247 248 NSString *keyname=[imageio localizedStringForKey:key value:key table:@"CGImageSource"]; 249 250 [array addObject:[XeePropertyItem itemWithLabel:keyname 251 value:[self convertCGPropertyValues:value imageIOBundle:imageio] 252 identifier:[NSString stringWithFormat:@"%@.%@",@"imageio",key]]]; 253 } 254 255 [array sortUsingSelector:@selector(compare:)]; 256 257 [array addObject:[XeePropertyItem itemWithLabel: 258 NSLocalizedString(@"More properties",@"More properties (from ImageIO.framework) section title") 259 value:[self convertCGPropertyValues:cgproperties imageIOBundle:imageio]]]; 260 261 return array; 262} 263 264-(NSArray *)convertCGPropertyValues:(NSDictionary *)cgproperties imageIOBundle:(NSBundle *)imageio 265{ 266 NSMutableArray *array=[NSMutableArray array]; 267 NSEnumerator *enumerator=[cgproperties keyEnumerator]; 268 NSString *key; 269 while(key=[enumerator nextObject]) 270 { 271 id value=[cgproperties objectForKey:key]; 272 key=[imageio localizedStringForKey:key value:key table:@"CGImageSource"]; 273 274 if([value isKindOfClass:[NSDictionary class]]) continue; 275 else if([value isKindOfClass:[NSArray class]]) 276 [array addObjectsFromArray:[XeePropertyItem itemsWithLabel:key valueArray:value]]; 277 else 278 [array addObject:[XeePropertyItem itemWithLabel:key value:value]]; 279 } 280 [array sortUsingSelector:@selector(compare:)]; 281 return array; 282} 283 284@end