Creating a Scaled NSView Screen Image

I have an off-screen sequence of NSViews in a Cocoa application that are used to create PDFs for printing. Views are not in NSWindow or are visible in any way.

I would like to be able to create miniature images of this view, just like it would look in PDF format, but reduced to the size of a specific pixel (limited by width or height). It should be as fast as possible, so I would like to avoid rendering to PDF, and then convert to raster and scaling - I would like to go straight to the raster.

At the moment I am doing:

NSBitmapImageRep *bitmapImageRep = [pageView bitmapImageRepForCachingDisplayInRect:pageView.bounds]; [pageView cacheDisplayInRect:pageView.bounds toBitmapImageRep:bitmapImageRep]; NSImage *image = [[NSImage alloc] initWithSize:bitmapImageRep.size]; [image addRepresentation:bitmapImageRep]; 

This approach works well, but I can't decide how to apply scaling to the NSView before rendering bitmapImageRep. I want to avoid using scaleUnitSquareToSize because, as far as I understand, this only changes the borders, not the NSView frame.

Any suggestions on the best way to do this?

+6
source share
2 answers

This is what I ended up working great. We draw directly in NSBitmapImageRep , but scale the context explicitly using CGContextScaleCTM in advance. graphicsContext.graphicsPort gives the CGContextRef handle for NSGraphicsContext .

 NSView *pageView = [self viewForPageIndex:pageIndex]; float scale = width / pageView.bounds.size.width; float height = scale * pageView.bounds.size.height; NSRect targetRect = NSMakeRect(0.0, 0.0, width, height); NSBitmapImageRep *bitmapRep; bitmapRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil pixelsWide:targetRect.size.width pixelsHigh:targetRect.size.height bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace bitmapFormat:0 bytesPerRow:(4 * targetRect.size.width) bitsPerPixel:32]; [NSGraphicsContext saveGraphicsState]; NSGraphicsContext *graphicsContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:bitmapRep]; [NSGraphicsContext setCurrentContext:graphicsContext]; CGContextScaleCTM(graphicsContext.graphicsPort, scale, scale); [pageView displayRectIgnoringOpacity:pageView.bounds inContext:graphicsContext]; [NSGraphicsContext restoreGraphicsState]; NSImage *image = [[NSImage alloc] initWithSize:bitmapRep.size]; [image addRepresentation:bitmapRep]; return image; 
+6
source

How about using scaleUnitSquareToSize: and then passing a smaller rectangle to bitmapImageRepForCachingDisplayInRect: and cacheDisplayInRect:toBitmapImageRep: :?

So, if you reduce it by 2 times, you will get a rectangle and a half with borders and height.

0
source

Source: https://habr.com/ru/post/919943/


All Articles