开发者

reset image in tableView imageCell is blurry

i'm trying to show an 'info' icon during a cursor 'rollover' on an NSTableView cell. i'm getting a copy of the cell's image, drawing the 'info' icon on it, and telling the cell to setImage with this copy. just drawing the icon will scale it and it won't be the same size in every one as the images in the table are different sizes. i'm not having a problem with the scaling or positioning the correct size icon.

my problem is that the replaced image is slightly blurry and it's edges are not crisp on close examination. the lack of edge makes it appear to be 'moving' slightly when the mouseEntered happens and the image is replaced.

i've tried a number of drawing techniques that doen't use lockFocus on an NSImage (drawing in CGBitmapContext, or using CIFilter compositing), and they produce the same results.

i'm using NSTableView's preparedCellAtColumn as it seems that drawing in willDisplayCell is unpredictable -- i read somewhere but can't remember where.

here is my preparedCellAtColumn method:

- (NSCell *)preparedCellAtColumn:(NSInteger)column row:(NSInteger)row
{
        NSCell *cell = [super preparedCellAtColumn:column row:row];

        if ((self.mouseOverRow == row) && column == 0) {

            NSCell * imageCell = [super preparedCellAtColumn:0 row:row];

            NSImage *sourceImage = [[imageCell image] copy];        
            NSRect cellRect = [self frameOfCellAtColumn:0 row:row];
            NSSize cellSize = cellRect.size; 

            NSSize scaledSize = [sourceImage proportionalSizeForTargetSize:cellSize];

            NSImage *outputImage = [[NSImage alloc] initWithSize:cellSize];
            [outputImage setBackgroundColor:[NSColor clearColor]];

            NSPoint drawPoint = NSZeroPoint;
            drawPoint.x = (cellSize.width - scaledSize.width) * 0.5;
            drawPoint.y = (cellSize.height - scaledSize.height) * 0.5;

            NSRect drawRect = NSMakeRect(drawPoint.x, drawPoint.y, scaledSize.width, scaledSize.height);

            NSPoint infoPoint = drawPoint;
            infoPoint.x += NSWidth(drawRect) - self.infoSize.width;

            [outputImage lockFocus]; 
            [sourceImage drawInRect:drawRect fromRect:NSZeroRect开发者_如何学运维 operation:NSCompositeSourceOver fraction:1.0];
            [self.infoImage drawAtPoint:infoPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
            [outputImage unlockFocus];

            [cell setImage:outputImage];
        }

        return cell;
}

[this is the enclosed scaling method from scott stevenson]

- (NSSize)proportionalSizeForTargetSize:(NSSize)targetSize
{
    NSSize imageSize = [self size];
    CGFloat width  = imageSize.width;
    CGFloat height = imageSize.height;

    CGFloat targetWidth  = targetSize.width;
    CGFloat targetHeight = targetSize.height;

    CGFloat scaleFactor  = 0.0;                
    CGFloat scaledWidth  = targetWidth;
    CGFloat scaledHeight = targetHeight;

    if ( NSEqualSizes( imageSize, targetSize ) == NO )
    {    
        CGFloat widthFactor;
        CGFloat heightFactor;

        widthFactor  = targetWidth / width;
        heightFactor = targetHeight / height;

        if ( widthFactor < heightFactor )
            scaleFactor = widthFactor;
        else
            scaleFactor = heightFactor;

        scaledWidth  = width  * scaleFactor;
        scaledHeight = height * scaleFactor;
    }

    return NSMakeSize(scaledWidth,scaledHeight);

}

i need to support 10.6, so can't use new groovy lion methods.

thanks for your consideration...


Your code is setting the origin of the image to non-integral coordinates. That means that the edge of the image will not be pixel-aligned, producing a fuzzy result.

You just need to do this:

NSPoint drawPoint = NSZeroPoint;
drawPoint.x = round((cellSize.width - scaledSize.width) * 0.5);
drawPoint.y = round((cellSize.height - scaledSize.height) * 0.5);

That will ensure the image origin has no fractional component.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜