Clipping NSImage around certain NSRect
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.
精彩评论