PageRenderTime 176ms CodeModel.GetById 51ms app.highlight 42ms RepoModel.GetById 2ms app.codeStats 0ms

/XeeImageIOLoader.m

https://code.google.com/p/xee/
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