开发者

Clipping NSImage around certain NSRect

开发者 https://www.devze.com 2023-01-08 21:32 出处:网络
I have an NSImage with different images inside it. The positions of the images inside 开发者_开发百科of it will stay the same all the time, so I need to specify a rectangle to get a subimage at the po

I have an NSImage with different images inside it. The positions of the images inside 开发者_开发百科of it will stay the same all the time, so I need to specify a rectangle to get a subimage at the position of the rectangle is inside of the image. How could this be done?


Why are there multiple images inside of one image? Premature optimization?

In any case, when you draw the image, one of the parameters you pass is the section of the image you want. Normally, you pass either the bounds of the image or the zero rect (which both mean the same thing), but you can pass a subrectangle if you want.

If the destination rectangle is larger than the source rectangle, it will scale up (non-proportionally); if it's smaller, it will scale down (non-proportionally). Adjust the size of the destination rectangle to match that of the source rectangle if you don't want any scaling.

If you want to leave the drawing to an NSImageView, create an empty NSImage of the desired size, then draw into it, then pass that image to the image view. This probably destroys whatever performance advantage you'd hoped to gain by mashing these all together into one image.

You could also create a custom subclass of NSView, NSImageView, or CALayer that has a property for the NSImage and a property for the source rectangle, and draws only that section.


This is easy as of macOS 10.6. This code takes a master image containing multiple clips and extracts part of that master to produce a clipped image.

// masterImage is the source image that contains multipe clips
NSImage *masterImage = [NSImage imageNamed:@"multiple_images.jpg"];
NSRect mFrame = NSMakeRect(0, 0, masterImage.size.width, masterImage.size.height);
NSImageRep *representation = [masterImage bestRepresentationForRect:mFrame
                                                            context:nil
                                                              hints:nil];

#define TARGET_IMAGE_SIZE    40 // NSImageView size (where the clip will be used)
NSSize targetSize = NSMakeSize(TARGET_IMAGE_SIZE, TARGET_IMAGE_SIZE);
NSImage *clippedImage = [NSImage imageWithSize:targetSize
                                       flipped:NO
                                drawingHandler:^BOOL(NSRect dstRect) {

    // set clipRect according to which clip you want:
    float xPos = 0; // compute these ...
    float yPos = 0; // ... positions of the clip within masterImage
    float clipSize = 50; // assumes each clip is square
    NSRect clipRect = NSMakeRect(xPos, yPos, clipSize, clipSize);

    BOOL ret = [representation drawInRect:dstRect
                                 fromRect:clipRect
                                operation:NSCompositingOperationCopy
                                 fraction:1.0 // alpha
                           respectFlipped:NO
                                    hints:nil];
    return ret; // ret from drawingHandler
}];

NSRect ivFrame = NSMakeRect( 0, 0, TARGET_IMAGE_SIZE, TARGET_IMAGE_SIZE);
NSImageView *clipImageView = [[NSImageView alloc] initWithFrame:ivFrame];
clipImageView.image = clippedImage;

Tip: using a loop, layout 'N' NSImageViews (where 'N' is the number of clips), extract each clip into one of those imageViews, and figure out how to compute the xPos, yPos, and clip size (clipRect) for each clip. It's easier when you can see all of the clips at once.

0

精彩评论

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

关注公众号