Re: Scrolling List of Thumbnails?
Re: Scrolling List of Thumbnails?
- Subject: Re: Scrolling List of Thumbnails?
- From: John Pannell <email@hidden>
- Date: Fri, 18 Jun 2004 20:19:27 -0600
Hi Jerry-
Here's my understanding of what is happening with regard to memory...
when you allocate each image:
NSImage * tmp= [[NSImage
alloc]initWithContentsOfFile:(NSString*)[fileNameList
objectAtIndex:i]];
... you are creating an object the occupies the same (or more, since
NSImage decompresses image data) memory as the file on disk would.
When you give that object to the cell, it is still the same size. Each
cell retains the object given, so you can see where there will be a lot
of memory usage. The image cell scales the image to display it, but
retains the full sized object. Thus the poor performance when
scrolling or scaling the view.
I ran into the same issue, and improved things dramatically by passing
a thumbnail sized NSImage, not the full sized one. Here's a snippet of
the process:
NSAffineTransform *at = [NSAffineTransform transform];
// copy the current image to manipulate it
NSImage *sourceImage = [theImage copy];
[sourceImage setScalesWhenResized:YES];
// make a blank thumbnail image at 128 x 128
thumbImage = [[[NSImage alloc] initWithSize:NSMakeSize(128,
128)] autorelease];
// determine scaling factor to reduce source image by
heightFactor = 128.0/[sourceImage size].height;
widthFactor = 128.0/[sourceImage size].width;
if(heightFactor > widthFactor){
scale = widthFactor;
} else {
scale = heightFactor;
}
// set the scale to be used in the transform
[at scaleBy:scale];
// lock and draw in my blank NSImage
[thumbImage lockFocus];
[[NSGraphicsContext currentContext]
setImageInterpolation:NSImageInterpolationHigh];
[sourceImage setSize:[at transformSize:[sourceImage size]]];
// the math here ensures the image is centered in the available area
[sourceImage compositeToPoint:NSMakePoint((128-[sourceImage
size].width)/2 , (128-[sourceImage size].height)/2)
operation:NSCompositeCopy];
[thumbImage unlockFocus];
Hopefully the comments make clear what is happening. I then assign the
thumbImage (not the original) to the cell. I should note that my
implementation has the above code running in a separate thread - the
calculations are (relatively) time consuming, and would cause spinning
rainbows and UI lockups if running on the main thread.
HTH!
John
On Jun 18, 2004, at 6:08 PM, Jerry LeVan wrote:
>
Below is my code for creating a scrolling list of images. The cells
>
are sized to 200x200.
>
>
Regrettably, the code is not swift and uses a lot of memory. One
>
of my directories contains almost 100 images of size 9-14 MB.
>
>
Top shows VM at almost one gig ( on my one gig g4 quicksilver 2002).
>
>
I would have thought that since the images are scaled to 200x200 that
>
the memory usage would not be nearly this high...Am I missing
>
something?
>
>
"thumbArray" is really a one column matrix of "ActionImageCell"s
>
(thanks John)
>
"filesLeft" is a text field in the FileCount nib, it displays the
>
number
>
of files left to process. (displayIfNeeded was really needed :)
>
>
Jerry
>
>
- (IBAction)openFile:(id)sender
>
{
>
int fcnt; // number of files
>
int mcnt; // current size of thumbMatrix
>
int i; // counter
>
// Get list of files to process
>
NSOpenPanel *op = [NSOpenPanel openPanel];
>
[op setCanChooseDirectories:YES];
>
[op setCanChooseFiles:NO];
>
>
int returnCode = [op runModalForTypes:nil];
>
if (returnCode != NSOKButton) {
>
return;
>
}
>
NSString *path = [op filename];
>
NSMutableArray *tmp = [NSMutableArray arrayWithCapacity:10];
>
// get all of the filenames for images we understand in the
>
directory
>
[self getFileList: tmp withPath:path];
>
if([tmp count] == 0) return; // no image files
>
[fileNameList setArray: tmp];
>
// Get the size of the filenamelist array
>
fcnt = [fileNameList count];
>
//Make sure we have enough items in the matrix
>
while( fcnt < [thumbArray numberOfRows]) { [thumbArray
>
removeRow:[thumbArray numberOfRows]-1];}
>
while (fcnt > [thumbArray numberOfRows]) { [thumbArray addRow];}
>
// load the progress indicator...
>
if(!thePanel) {
>
[NSBundle loadNibNamed: @"FileCount" owner:self];
>
}
>
[thePanel orderFront:self];
>
[progressInd setUsesThreadedAnimation:YES];
>
[progressInd startAnimation:self];
>
fileCtr=fcnt;
>
for(i=0 ; i< fcnt ; i++) {
>
NSImage * tmp= [[NSImage
>
alloc]initWithContentsOfFile:(NSString*)[fileNameList
>
objectAtIndex:i]];
>
[[thumbArray cellAtRow:i column:0] setImage: tmp];
>
[[thumbArray cellAtRow:i column:0] setTarget:self];
>
[[thumbArray cellAtRow:i column:0] setAction:@selector(showMe:)];
>
[tmp release];
>
[filesLeft setIntValue: fileCtr--];
>
[filesLeft displayIfNeeded];
>
}
>
[progressInd stopAnimation:self];
>
[thePanel orderOut:self]; // hide the panel
>
if(displayedImage) { [displayedImage release]; displayedImage=NULL;}
>
[thumbArray sizeToCells];
>
[thumbArray setNeedsDisplay];
>
}
>
_______________________________________________
>
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.
_______________________________________________
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.