Re: Scrolling List of Thumbnails?
Re: Scrolling List of Thumbnails?
- Subject: Re: Scrolling List of Thumbnails?
- From: Jerry LeVan <email@hidden>
- Date: Fri, 18 Jun 2004 22:32:21 -0400
John
I sorta came to the same conclusion.
I currently am scaling with the following code prior
to assigning to a cell ( then I release it).
Memory usage was dramatically improved.
Jerry
-(NSImage *) makeThumb: (NSString*) pathName
{
float maxDim;
float scaleFactor;
NSSize scaledRect;
NSImage * bigOne = [[NSImage alloc]initWithContentsOfFile:pathName];
NSSize bigRect = [bigOne size];
maxDim = bigRect.width>bigRect.height?bigRect.width:bigRect.height;
if (maxDim == 0.0) { scaleFactor = 1.0;}
else
{ scaleFactor = 200.0/maxDim;}
[bigOne setScalesWhenResized:YES];
scaledRect.width= bigRect.width*scaleFactor;
scaledRect.height=bigRect.height*scaleFactor;
[bigOne setSize:scaledRect];
return bigOne;
}
On Jun 18, 2004, at 10:19 PM, John Pannell wrote:
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.