NSImage Getting Resized when I draw Text on it
This is a different approach using a temporary NSView
to draw the image and the text and cache the result in a new image (code is Swift 4). The benefit it you don't need to deal with pixels
class ImageView : NSView {
var image : NSImage
var text : String
init(image: NSImage, text: String)
{
self.image = image
self.text = text
super.init(frame: NSRect(origin: NSZeroPoint, size: image.size))
}
required init?(coder decoder: NSCoder) { fatalError() }
override func draw(_ dirtyRect: NSRect) {
let font = NSFont.boldSystemFont(ofSize: 18)
let textRect = CGRect(x: 5, y: 5, width: image.size.width - 5, height: image.size.height - 5)
image.draw(in: dirtyRect)
text.draw(in: textRect, withAttributes: [.font: font, .foregroundColor: NSColor.white])
}
var outputImage : NSImage {
let imageRep = bitmapImageRepForCachingDisplay(in: frame)!
cacheDisplay(in: frame, to:imageRep)
let tiffData = imageRep.tiffRepresentation!
return NSImage(data : tiffData)!
}
}
To use it, initialize a view
let image = ... // get some image
let view = ImageView(image: image, text: "Sample Text")
and get the new image
let imageWithText = view.outputImage
Note:
The paragraph style is not used at all, but if you want to create a mutable paragraph style just write
let textStyle = NSMutableParagraphStyle()
How to resize NSImage?
Edit:
Since this answer is still the accepted answer, but was written without Retina screens in mind, I will straight up link to a better solution further down the thread: Objective-C Swift 4
Because the method of Paresh is totally correct but deprecated since 10.8 I'll post the working 10.8 code below. All credit to Paresh's answer though.
- (NSImage *)imageResize:(NSImage*)anImage newSize:(NSSize)newSize {
NSImage *sourceImage = anImage;
[sourceImage setScalesWhenResized:YES];
// Report an error if the source isn't a valid image
if (![sourceImage isValid]){
NSLog(@"Invalid Image");
} else {
NSImage *smallImage = [[NSImage alloc] initWithSize: newSize];
[smallImage lockFocus];
[sourceImage setSize: newSize];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[sourceImage drawAtPoint:NSZeroPoint fromRect:CGRectMake(0, 0, newSize.width, newSize.height) operation:NSCompositingOperationCopy fraction:1.0];
[smallImage unlockFocus];
return smallImage;
}
return nil;
}
Resized NSImageView not redrawing
So I found a way around this, however it is fairly hackish.
As mentioned in the edit, this bug only occurs with ImageFrameStyle set to NSImageFrameNone. When I set the ImageFrameStyle to something else, then resize it, then set it to NSImageFrameNone again after resizing, things work fine:
[coverImage setImageFrameStyle: NSImageFramePhoto];
coverImage.frame = CGRectMake((1280 - 869) / 2, 0, 869 * percentage, 800);
[coverImage setImageFrameStyle: NSImageFrameNone];
This works but isn't very pretty. Thus I'll leave the question open for a couple more days in hope to find a better answer.
Related Topics
Waiting for Alamofire in Unit Tests
Play Local Audio File with Avaudioplayer
Accessor Gives the Wrong Value in Swift 1.2/2.0 Release Build Only
Adding Items to Array as a Dictionary Value
What Happens When You Run Deprecated Code in Swift
For Loop for Dictionary Don't Follow It's Order in Swift
Add Environmentobject in Swiftui 2.0
How to Create Uicollectionviewcell Programmatically
Setting Backgroundcolor of Custom Nsview
Swift & Firebase - How to Store More User Data Other Than Email and Password
Use of Undeclared Type 'Attributedstring'
How to Use Trailing Closure in If Condition
Swift: How to Get Form Values Using Eureka Form Builder
Firebase Uid VS Document-Id and Firestore Rules
Physics Detecting Collision Multiple Times
Swift 5 Table View Cell with Uiimage Appears Very Tall and Image Extremely Zoomed