Creating NSmages from NSMovies for display in an NSOutlineView
Creating NSmages from NSMovies for display in an NSOutlineView
- Subject: Creating NSmages from NSMovies for display in an NSOutlineView
- From: Arved von Brasch <email@hidden>
- Date: Sat, 7 Dec 2002 19:55:21 +1100
Hi,
One of the projects I'm working on involves several Quicktime movies.
To make things easier, I'm working on an application to help sort them
for later use. Everything was working fine until I decided it would be
useful to have a preview of the movie appear in an NSOutlineView along
with its name to help identify the particular movie.
The way my NSOutlineView is setup is to connect itself to objects that
contains various text information about the movie. These are the items
the movie asks about. I tried creating a preview of the image in this
object, but found it to be too slow. As each movie can be guaranteed
to have a unique file name, I decided to create a NSMutableDicitionary,
with the filename of the movie as the key, and the preview image as the
object. This way, the plan was to query the dictionary for a
particular movie based when the NSOutlineView asks its datasource for
the cell value. If no preview existed, then one could be generated.
This seems to work well for the most part (although it's still a little
slow), in that when the outlineview first appears on the screen, all
the previews appear correctly. However, clicking on the first row in
the outlineview causes the application to crash, with either a signal
10 or 11. Sounds like I've got one too many releases. I haven't been
able to track down the problem.
In my search for the cause for the problem, I came across somethings
that are quite strange. The first image to be displayed in the
outlineview seems to have a retain count of one less than the others.
I don't know how this can be, as the images are created on the fly. If
another row in the outlineview is clicked first, and then the first row
is clicked, the application doesn't crash, but all the values of all
the cells of the outlineview disappear and I get a message in Project
Builder that an NSImageCell must contain an image. I've been able to
determine that this happens when the outlineview is querying the
dictionary for an image that is already contained in it. Finally, I
created a new project, and made it work with pure images instead of
movies, because I thought my Quicktime handling routines might have
been at fault. This worked fine, no runtime problems. I then went
back and tried writing the frame to a file and then rereading it in as
an image. The file produced was a perfectly valid image, but this
still didn't work.
Any help on this matter would be greatly appreciated,
Arved von Brasch
OutlineView datasource method in question:
NSMutableDictionary *previews; // The preview dictionary. Created in
init with 0 capacity, and released in dealloc
- (id)outlineView:(NSOutlineView *)outlineView
objectValueForTableColumn:(NSTableColumn *)tableColumn
byItem:(id)displayItem {
if ([[tableColumn identifier] hasPrefix: @"p"]) {
// p for preview
if (![displayItem isExpandable]) {
// Movies can be categorized, but a category doesn't contain a
movie.
NSImage *image = [previews objectForKey: [displayItem fileName]];
if (image != nil) {
return image; // A preview has already been created.
}
else {
[self makePreview: displayItem];
image = [previews objectForKey: [displayItem fileName]];
return image;
}
}
else {
if ([displayItem numberOfChildren] > 0) { // A category gets its
preview from its first child (if one exists).
return [self outlineView:outlineView
objectValueForTableColumn:tableColumn byItem:[displayItem childAtIndex:
0]];
}
else {
return nil;
}
}
}
else {
// return stuff in other columns.
}
}
The make a preview routine:
- (void)makePreview:(OutlineItem *)displayItem {
NSString *path = [folderPath stringByAppendingFormat: @"/%@",
[displayItem fileName]]; // folderPath is the path of the folder
containing the movies
[previews setObject: [self makeThumbnail: path] forKey:
[displayItem fileName]];
}
The thumbnail making routine:
- (NSImage *)makeThumbnail:(NSString *)fromPath {
NSURL *url = [[NSURL alloc] initFileURLWithPath: fromPath];
NSMovie *movie = [[NSMovie alloc] initWithURL: url
byReference:YES]; // Open Movie
[url release];
PicHandle picHandle = (PicHandle)GetMoviePict([movie QTMovie],
GetMovieDuration([movie QTMovie])); // Get last frame of movie
[movie release];
NSData *imageData = [NSData dataWithBytes: (*picHandle) length:
GetHandleSize((Handle)picHandle)];
KillPicture(picHandle);
NSPICTImageRep *imageRep = [NSPICTImageRep imageRepWithData:
imageData];
NSImage *image = [[[NSImage alloc] initWithSize:[imageRep size]]
autorelease];
[image lockFocus];
[imageRep drawAtPoint:NSMakePoint(0,0)]; // Convert frame into a
useable image.
[image unlockFocus]; // For pure images everything below this is
kept, and the image is initWithContentsOfFile here.
float width = [image size].width;
float height = [image size].height;
imageData = [image TIFFRepresentation];
NSBitmapImageRep *imageBitmap = [NSBitmapImageRep
imageRepWith
Data:imageData];
[image release];
if (width > height) {
height = height*40/width;
width = 40;
}
else {
width = width*40/height;
height = 40;
}
image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
// Scale image to a max of 40x40 to save runtime memory.
[image setScalesWhenResized:YES];
[image addRepresentation:imageBitmap];
[image lockFocusOnRepresentation:imageBitmap];
imageData = [[image TIFFRepresentation] retain];
[image unlockFocus];
[image release];
image = [[NSImage alloc] initWithData: imageData];
[imageData release];
return [image autorelease];
}
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.