Programmatically determine dimensions of image files in bundle - iphone

I have a large number of image files in my iPhone app bundle (~3000) and I want to determine the dimensions at runtime rather than store this data in the database or an xml manifest for the images.
Is there a way to do this programmatically?

UIImage has the size property that returns the dimensions of the image, however I wouldn't recommend loading all 3000 of your images in your iPhone app. Pre-generating that information at build time would give you much better results. Failing that you might possibly use some sort of naming convention for your images that encodes the image size in the file name, however this is really not that different to storing the information in some sort of database or XML file ;)

The file Unix utility uses the header information on the file to determine the size. It basically requires loading in the first block of the file and sifting through the information (varies by file type but presumably you'll only have one to implement since you control the images).

As of iOS 4, it is possible to access image properties without actually loading image in memory.
You'll need ImageIO.framework and #import < ImageIO/ImageIO.h>
NSURL *imageFileURL = [NSURL fileURLWithPath:imagePath];
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageFileURL, NULL);
if (imageSource == NULL)
{
// Error loading image ...
}
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], (NSString *)kCGImageSourceShouldCache, nil];
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (CFDictionaryRef)options);
NSNumber *mImageWidth;
NSNumber *mImageHeight;
if (imageProperties)
{
mImageWidth = (NSNumber *)CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth);
mImageHeight = (NSNumber *)CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
CFRelease(imageProperties);
}

Related

How to change sprite image with array of images cocos2d?

I am learning Cocos2d and building an application where i have sprite at one end and I need to through it on the other side and with the same I am removing the sprite from the screen and after some time, I am displaying the same.
Now I have a folder of images in my application and I need to load different images each time in random order from the same folder and maintain a log that these images do not repeat again and again. I am able to load images from the folder with :
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundleRoot error:nil];
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self ENDSWITH '.jpg'"]];
Now how would I call this array and display different images each time and also maintain a log that images don't get repeat. I have already went through links like this and this but in vail. Any clue will be really very helpful. Thank you for the help in advance.
The best way to do this is by creating a spriteSheet. first of all you can get http://zwoptexapp.com/ , its free and you can create your spritesheet for using with cocos (on the exporter make sure you select cocos2d to create the proper plist)
You want to pack all your image in 1 big texture so you can add it to your project with the plist (zwoptex will create both for you)
then you can load your texture with
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"your_plist"];
switching textures is slow operation, so having all the images in the same texture will boost the openGL performance, after you've done that changing the texture for a sprite is very easy
[yourSprite setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"FRAME_NAME"]];
where FRAME_NAME is the name of the frame in the plist (you can see it by selecting the plist inside xcode.
to cycle in a random way without repeating images...
(i'll write some pseudocode directly in here, let me do inits inside class declaration and inline implementations :) )
//WARNING THIS IS PSEUDO CODE :)
#interface Randomizer {
//an array of NSStrings containing all you images names
NSMutableArray *allImagesFrameNames = [NSMutableArray arrayWithCapacity:NUM_FRAMES];
CCSprite *sprite = alloc init
}
-(void) resetAllFrames {
[allImagesFrameNames removeAllobjects];
[allImagesFrameName addObject:#"FIRST_IMAGE"];
[allImagesFrameName addObject:#"SECOND_IMAGE"]; //add all your images
}
#end
And to display a random frame:
-(void) display a randomImage {
//if the array is empty, all images are already been randomly displayed, so we reset the array
if([allImagesFrameName count] == 0)
[self resetAllFrames];
//we choose a random index
int randomIndex = arc4random %[allImagesFrameName count];
//we get the frame name at that index
NSString *imageFrameName = [allImagesFrameNames objectAtIndex:randomIndex];
//and we display the frame
[sprite setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:imageFrameName]];
[allImagesFrameNames removeObjectAtIndex:randomIndex];
}

Using built-in icons for mime type or UTI type in iOS

Problem:
I would like to be able to use the built-in iOS icons for standard mime types (or UTI types) in my listing of binary file content.
Background:
I have looked into using the new (since 3.2) document architecture, but using the UIDocumentInteractionController it seems that the assumption is that the actual binaries are already on the local device.
In my case I have a file listing from a remote server and know the mime type, name, title, etc for the remote file so I just want to show a file listing with icons (the actual binary is only loaded as needed).
The meta data I get from the server contains proper mime types for the binaries so in theory I just want to get the system icon based on the type.
Work around?
I have tried the following "hack" as a proof of concept and it seems to work but this doesn't seem like the best way to go...
//Need to initialize this way or the doc controller doesn't work
NSURL*fooUrl = [NSURL URLWithString:#"file://foot.dat"];
UIDocumentInteractionController* docController = [[UIDocumentInteractionController interactionControllerWithURL:fooUrl] retain];
UIImage* thumbnail = nil;
//Need to convert from mime type to a UTI to be able to get icons for the document
NSString *uti = [NSMakeCollectable(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (CFStringRef)self.contentType, NULL)) autorelease];
//Tell the doc controller what UTI type we want
docController.UTI = uti;
//The doc controller now seems to have icon(s) for the type I ask for...
NSArray* icons = docController.icons;
if([icons count] > 0) {
thumbnail = [icons objectAtIndex:0];
}
return thumbnail;
You can create a UIDocumentInteractionController without needing to specify a URL. The header for the class says the icons are determined by name if set, URL otherwise.
UIDocumentInteractionController* docController = [[UIDocumentInteractionController alloc] init];
docController.name = #"foo.dat";
NSArray* icons = docController.icons;
// Do something with icons
...
[docController release];
I tried Ben Lings's solution, but it didn't work on iOS6.1 in either the simulator or on my iPad3. You need to provide an NSURL to the UIDocumentInteractionController, but that URL doesn't need to exist. Its last path component just needs to have the extension that you want.
The following code worked for me
NSString *extension = #"pptx"; // or something else
NSString *dummyPath = [#"~/foo" stringByAppendingPathExtension:extension]; // doesn't exist
NSURL *URL = [NSURL fileURLWithPath:dummyPath];
UIDocumentInteractionController *documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:URL];
NSArray *systemIconImages = documentInteractionController.icons;
return systemIconImages;
So we are talking about hacks uh? I did this by doing some bad stuff, but it's working...
I copied the icons from /system/library/frameworks/QuickLook.framework and added to my project. Inside this same folder, there is some property lists, that make the link between the UTI/extension/mime-type with the png file. With the plist and the pngs, all you have to do is make a logic to read the plists and show the correct png.

iphone: Smart way to cache large number of images?

I have a UITableView that displays hundreds of images that are downloaded from the web. Of course I don't want to keep all the images in the RAM - I need to create a small "cache" of images in the RAM and write the images that I don't need right now to the "disk". Of course I don't want this mechanism to hinder the UI (Too many reads and writes to the disk/flash drive on the main thread). What's the best and easy way to implement such a thing? Are there any open source projects that use such a thing, I can look at?
Check out the Three20 library, especially the TTURLRequest, TTURLCache and TTImageView classes.
I ended up using SDWebImage
Very easy and elegant.
I have a class that stores the UIImage in a NSMutableDictionary. If the UIImage already exists in the dictionary then I just return that object rather than creating a new UIImage.
#import “Cache.h"
#implementation Cache
static NSMutableDictionary *dict;
+ (UIImage*)loadImageFromWeb:(NSString*)imageName{
if (!dict) dict = [[NSMutableDictionary dictionary] retain];
UIImage* image = [dict objectForKey:imageName];
if (!image)
{
image = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: imageName]]];
if (image)
{
[dict setObject:image forKey:imageName];
}
}
return image;
}

Animated-GIF images received as NSData through NSSocket unable to split frames

I'm having trouble with the way iOS handles animated-GIF's. I know that you cannot use animated-GIF's on an UIImageView and you have to use custom animations on the UIImageView.
But..
I have a Java server that sends GIF images through a socketstream. The iOS (iPhone) receives that stream and converts it into an NSData type. I've succeeded in capturing and displaying this image in a UIImageView but as many of you already know.. it only displays the first frame.
I Also found some code to decode that GIF into separate images, but that code works from a GIF file and not NSData.
Question: How do i convert the NSData file into separate images and place them in an NSArray to use it as animation?
Note: In the NSData that is received are both an image and some text separated by a rare character. so the NSData looks like this: [image] [separator] [text].
Hope somebody can give me some pointers or some samples to work with..
Thanks in advance, i will keep searching untill you or me finds an answer :)
Unless you're targeting devices before IOS 4, use ImageIO.
NSMutableArray *frames = nil;
CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)data, NULL);
if (src) {
size_t l = CGImageSourceGetCount(src);
frames = [NSMutableArray arrayWithCapacity:l];
for (size_t i = 0; i < l; i++) {
CGImageRef img = CGImageSourceCreateImageAtIndex(src, i, NULL);
if (img) {
[frames addObject:[UIImage imageWithCGImage:img]];
CGImageRelease(img);
}
}
CFRelease(src);
}
I made a wrapper that also handles animation time based on the code from Anomie
https://gist.github.com/3894888

Cocoa - Add Video Watermark General Info

Just looking for how to programmatically add a watermark or some sort of overlay to video using cocoa. Not looking for a step by step ( although that would awesome ), but more or less looking for where I should start looking to learn how. Are there frameworks developed to work for this. Would like something native to cocoa or objective-c or c because I would like to eventually give this a go on the iPhone. Any help would be great.
I'm not sure if you mean just for playback, or if you'd like to export a video with a watermark that'll show up on other players.
If you mean just for playback, you can probably just add a view on top of the player view on Mac and iPhone that contains the watermark.
If you'd like a watermark on the video itself, this is hard on the Mac and probably impossible on the iPhone without essentially rewriting QuickTime.
On the Mac, the code might look like this (you need to import QTKit):
// Make a new movie so we don't destroy the existing one
QTMovie* movie = [[QTMovie alloc] initWithMovie:currentMovie
timeRange:QTMakeTimeRange(QTMakeTime(0,1000), [currentMovie duration])
error:nil];
// Make it editable
[movie setAttribute:[NSNumber numberWithBool:YES]
forKey:QTMovieEditableAttribute];
//Get the size
NSValue *value = [movie attributeForKey:QTMovieNaturalSizeAttribute];
NSSize size = [value sizeValue];
// Add a new track to the movie and make it the frontmost layer
QTTrack *track = [movie addVideoTrackWithSize:size];
[track setAttribute:[NSNumber numberWithShort:-1] forKey:QTTrackLayerAttribute];
// Create a codec dictionary for the image we're about to add
NSDictionary *imageDict = [NSDictionary dictionaryWithObjectsAndKeys:
#"tiff", QTAddImageCodecType,
[NSNumber numberWithLong:codecHighQuality], QTAddImageCodecQuality, nil];
// Get the video length in QT speak
QTTime qttime = [currentMovie duration];
NSTimeInterval reftime;
QTGetTimeInterval(qttime, &reftime);
//Add the image for the entire duration of the video
[track addImage:image forDuration:qttime withAttributes:imageDict];
// Finally, tell the track that it should use its alpha correctly
MediaHandler media = GetMediaHandler([[track media] quickTimeMedia]);
MediaSetGraphicsMode(media, graphicsModeStraightAlpha, NULL);
... And that's it! Your movie now has a watermark, and you can export it to file.