我的NSBitmapImageRep
大小为W
x H
。我创建NSImage
并执行addRepresentation:
。然后我需要调整NSImage
的大小。我尝试了setSize
方法,但它不起作用。我该怎么办?
答案 0 :(得分:35)
修改强> 由于这个答案仍然是公认的答案,但是在没有Retina屏幕的情况下编写,我将直接链接到更好的解决方案:Objective-C Swift 4
因为Paresh的方法完全正确但从10.8开始不推荐使用,我将在下面发布10.8代码。所有这些都归功于Paresh的答案。
- (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:NSCompositeCopy fraction:1.0];
[smallImage unlockFocus];
return smallImage;
}
return nil;
}
答案 1 :(得分:26)
Thomas Johannesmeyer使用lockFocus
的答案不适用于您在Retina / HiDPI屏幕上的意图:它会在屏幕的原始比例中调整为所需的点,而不是像素强>
此方法从各种答案(包括this related question中的一些答案拼凑而成)调整为指定的像素尺寸,与当前屏幕DPI无关:
+ (NSImage *)resizedImage:(NSImage *)sourceImage toPixelDimensions:(NSSize)newSize
{
if (! sourceImage.isValid) return nil;
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:newSize.width
pixelsHigh:newSize.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bytesPerRow:0
bitsPerPixel:0];
rep.size = newSize;
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:rep]];
[sourceImage drawInRect:NSMakeRect(0, 0, newSize.width, newSize.height) fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
[NSGraphicsContext restoreGraphicsState];
NSImage *newImage = [[NSImage alloc] initWithSize:newSize];
[newImage addRepresentation:rep];
return newImage;
}
答案 2 :(得分:16)
编辑您可以使用以下功能调整图片大小:
- (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] autorelease];
[smallImage lockFocus];
[sourceImage setSize: newSize];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[sourceImage compositeToPoint:NSZeroPoint operation:NSCompositeCopy];
[smallImage unlockFocus];
return smallImage;
}
return nil;
}
其次是这样的:
NSData *imageData = [yourImg TIFFRepresentation]; // converting img into data
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData]; // converting into BitmapImageRep
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.9] forKey:NSImageCompressionFactor]; // any number betwwen 0 to 1
imageData = [imageRep representationUsingType:NSJPEGFileType properties:imageProps]; // use NSPNGFileType if needed
NSImage *resizedImage = [[NSImage alloc] initWithData:imageData]; // image created from data
答案 3 :(得分:14)
实际上无需来修改size
等任何源图像参数。以下代码片段已经在Swift中,但我认为您可以从中推断出Objective-C版本:
func resized(to: CGSize) -> NSImage {
let img = NSImage(size: to)
img.lockFocus()
defer {
img.unlockFocus()
}
if let ctx = NSGraphicsContext.current {
ctx.imageInterpolation = .high
draw(in: NSRect(origin: .zero, size: to),
from: NSRect(origin: .zero, size: size),
operation: .copy,
fraction: 1)
}
return img
}
答案 4 :(得分:9)
">click here</a>...),
答案 5 :(得分:4)
这里是Thomas Johannesmeyer's answer的Swift 4版本:
var oModel = this.getView().getModel("myJsonModel");
this.getView().getModel().read("/Meetups", {
success: function(oData) {
oModel.setData(oData);
}
});
Swift 4版Marco's answer:
func resize(image: NSImage, w: Int, h: Int) -> NSImage {
var destSize = NSMakeSize(CGFloat(w), CGFloat(h))
var newImage = NSImage(size: destSize)
newImage.lockFocus()
image.draw(in: NSMakeRect(0, 0, destSize.width, destSize.height), from: NSMakeRect(0, 0, image.size.width, image.size.height), operation: NSCompositingOperation.sourceOver, fraction: CGFloat(1))
newImage.unlockFocus()
newImage.size = destSize
return NSImage(data: newImage.tiffRepresentation!)!
}
答案 6 :(得分:3)
完成Swift 3的答案(修改自@Erik Aigner above):
extension NSImage {
func resizeImage(width: CGFloat, _ height: CGFloat) -> NSImage {
let img = NSImage(size: CGSize(width:width, height:height))
img.lockFocus()
let ctx = NSGraphicsContext.current()
ctx?.imageInterpolation = .high
self.draw(in: NSMakeRect(0, 0, width, height), from: NSMakeRect(0, 0, size.width, size.height), operation: .copy, fraction: 1)
img.unlockFocus()
return img
}
}
答案 7 :(得分:2)
2020年| SWIFT 4和5:
用法:
let resizedImg = someImage.resizedCopy(w: 500.0, h:500.0)
let scaledImg = someImage.scaledCopy( sizeOfLargerSide: 1000.0)
//and bonus:
scaledImg.writePNG(toURL: someUrl )
代码:
extension NSImage {
func scaledCopy( sizeOfLargerSide: CGFloat) -> NSImage {
var newW: CGFloat
var newH: CGFloat
var scaleFactor: CGFloat
if ( self.size.width > self.size.height) {
scaleFactor = self.size.width / sizeOfLargerSide
newW = sizeOfLargerSide
newH = self.size.height / scaleFactor
}
else{
scaleFactor = self.size.height / sizeOfLargerSide
newH = sizeOfLargerSide
newW = self.size.width / scaleFactor
}
return resizedCopy(w: newW, h: newH)
}
func resizedCopy( w: CGFloat, h: CGFloat) -> NSImage {
let destSize = NSMakeSize(w, h)
let newImage = NSImage(size: destSize)
newImage.lockFocus()
self.draw(in: NSRect(origin: .zero, size: destSize),
from: NSRect(origin: .zero, size: self.size),
operation: .copy,
fraction: CGFloat(1)
)
newImage.unlockFocus()
guard let data = newImage.tiffRepresentation,
let result = NSImage(data: data)
else { return NSImage() }
return result
}
public func writePNG(toURL url: URL) {
guard let data = tiffRepresentation,
let rep = NSBitmapImageRep(data: data),
let imgData = rep.representation(using: .png, properties: [.compressionFactor : NSNumber(floatLiteral: 1.0)]) else {
Swift.print("\(self) Error Function '\(#function)' Line: \(#line) No tiff rep found for image writing to \(url)")
return
}
do {
try imgData.write(to: url)
}catch let error {
Swift.print("\(self) Error Function '\(#function)' Line: \(#line) \(error.localizedDescription)")
}
}
}
答案 8 :(得分:0)
这是一个保持图像的Swift 3版本比例,只需将minimumSize设置为您想要的最小高度或宽度:
func imageResized(image: NSImage) -> NSImage {
let ratio = image.size.height / image.size.width
let width: CGFloat
let height: CGFloat
// We keep ratio of image
if ratio > 1 {
width = minimumSize
height = minimumSize * ratio
} else {
width = minimumSize
height = minimumSize * (1 / ratio)
}
let destSize = NSSize(width: width, height: height)
let newImage = NSImage(size: destSize)
newImage.lockFocus()
image.draw(in: NSRect(x: 0, y: 0, width: destSize.width, height: destSize.height), from: NSRect(x: 0, y: 0, width: image.size.width, height: image.size.height), operation: .sourceOver, fraction: 1.0)
newImage.unlockFocus()
newImage.size = destSize
return NSImage(data: newImage.tiffRepresentation!)!
}
答案 9 :(得分:0)
仅用于缩放NSBitmapImageRep
static NSBitmapImageRep *i_scale_bitmap(const NSBitmapImageRep *bitmap, const uint32_t width, const uint32_t height)
{
NSBitmapImageRep *new_bitmap = NULL;
CGImageRef dest_image = NULL;
CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGContextRef context = CGBitmapContextCreate(NULL, (size_t)width, (size_t)height, PARAM(bitsPerComponent, 8), PARAM(bytesPerRow, (size_t)(width * 4)), space, kCGImageAlphaPremultipliedLast);
CGImageRef src_image = [bitmap CGImage];
CGRect rect = CGRectMake((CGFloat)0.f, (CGFloat)0.f, (CGFloat)width, (CGFloat)height);
CGContextDrawImage(context, rect, src_image);
dest_image = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(space);
new_bitmap = [[NSBitmapImageRep alloc] initWithCGImage:dest_image];
CGImageRelease(dest_image);
return new_bitmap;
}
并用于基于NSBitmapImageRep缩放NSImage
ImageImp *imgimp_create_scaled(const ImageImp *image, const uint32_t new_width, const uint32_t new_height)
{
NSImage *src_image = (NSImage*)image;
NSBitmapImageRep *src_bitmap, *dest_bitmap;
NSImage *scaled_image = nil;
cassert_no_null(src_image);
cassert([[src_image representations] count] == 1);
cassert([[[src_image representations] objectAtIndex:0] isKindOfClass:[NSBitmapImageRep class]]);
src_bitmap = (NSBitmapImageRep*)[[(NSImage*)image representations] objectAtIndex:0];
cassert_no_null(src_bitmap);
dest_bitmap = i_scale_bitmap(src_bitmap, new_width, new_height);
scaled_image = [[NSImage alloc] initWithSize:NSMakeSize((CGFloat)new_width, (CGFloat)new_height)];
[scaled_image addRepresentation:dest_bitmap];
cassert([scaled_image retainCount] == 1);
[dest_bitmap release];
return (ImageImp*)scaled_image;
}
直接在NSImage上绘制([NSImage lockFocus]等)将创建NSCGImageSnapshotRep而不是NSBitmapImageRep。