Отсечение NSImage вокруг определенного NSRect
У меня есть NSImage с разными изображениями внутри. Положение изображений внутри него будет оставаться неизменным все время, поэтому мне нужно указать прямоугольник, чтобы получить подизображение в положении прямоугольника внутри изображения. Как это можно сделать?
1 ответ
Почему внутри одного изображения несколько изображений? Преждевременная оптимизация?
В любом случае, когда вы рисуете изображение, один из параметров, которые вы передаете, - это часть изображения, которую вы хотите. Обычно вы передаете либо границы изображения, либо нулевой прямоугольник (оба значения означают одно и то же), но при желании вы можете пройти под прямоугольник.
Если целевой прямоугольник больше исходного прямоугольника, он будет увеличиваться (не пропорционально); если он меньше, он будет уменьшаться (непропорционально). Отрегулируйте размер прямоугольника назначения, чтобы он соответствовал размеру исходного прямоугольника, если вы не хотите масштабирования.
Если вы хотите оставить чертеж на NSImageView, создайте пустой NSImage нужного размера, затем нарисуйте его, а затем передайте это изображение в представление изображений. Это, вероятно, разрушает любое преимущество в производительности, которое вы надеялись получить, смешав все это в одном изображении.
Вы также можете создать собственный подкласс NSView, NSImageView или CALayer, который имеет свойство для NSImage и свойство для исходного прямоугольника и рисует только этот раздел.
Это просто, начиная с macOS 10.6. Этот код берет эталонное изображение, содержащее несколько клипов, и извлекает часть этого эталона для создания вырезанного изображения.
// 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;
Совет: используя петлю, макет "N" NSImageViews
(где "N" - количество клипов), извлеките каждый клип в один из этих imageView и выясните, как вычислить xPos, yPos и размер клипа (clipRect) для каждого клипа. Это проще, когда вы можете видеть все клипы сразу.