如何调整NSImage的大小

hoc*_*man 21 macos jpeg objective-c nsimage

NSBitmapImageRepWX H的大小.我创造NSImage并做addRepresentation:.然后我需要调整大小NSImage.我试过setSize方法,但它不起作用.我该怎么办?

Tho*_*yer 35

编辑: 由于这个答案仍然是接受的答案,但是在没有Retina屏幕的情况下编写,我将直接链接到更好的解决方案进一步下线:https://stackoverflow.com/a/38442746/1277898


因为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;
}
Run Code Online (Sandbox Code Playgroud)

  • [sourceImage setScalesWhenResized:YES]; 已弃用,因为不再需要它.你可以删除它,这个例程非常有效. (3认同)
  • 请注意,这会调整大小到屏幕点,而不是像素尺寸.在Retina屏幕上,生成的图像将是请求大小的两倍(以像素为单位).要在Retina屏幕上精确调整像素大小,请使用以下方法:http://stackoverflow.com/a/38442746/30480 (2认同)

Mar*_*rco 29

Thomas Johannesmeyer使用的答案lockFocus不适用于你可能想要的Retina/HiDPI屏幕:它调整到屏幕原生尺度所需的,而不是像素.

  • 如果要调整屏幕上的显示大小,请使用该方法.
  • 如果您正在调整具有精确像素尺寸的文件的大小,则在Retina(2x DPI)屏幕上运行时,它将是两倍大.

这个方法从各种答案拼凑而成,包括相关问题中的一些,无论当前屏幕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;
}
Run Code Online (Sandbox Code Playgroud)


Par*_*iya 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;
}
Run Code Online (Sandbox Code Playgroud)

其次是这样的:

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
Run Code Online (Sandbox Code Playgroud)


Eri*_*ner 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
}
Run Code Online (Sandbox Code Playgroud)


Ati*_*ika 12

@MarcoSwift 4中的回答:

extension NSImage {
    func resized(to newSize: NSSize) -> NSImage? {
        if let bitmapRep = NSBitmapImageRep(
            bitmapDataPlanes: nil, pixelsWide: Int(newSize.width), pixelsHigh: Int(newSize.height),
            bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false,
            colorSpaceName: .calibratedRGB, bytesPerRow: 0, bitsPerPixel: 0
        ) {
            bitmapRep.size = newSize
            NSGraphicsContext.saveGraphicsState()
            NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: bitmapRep)
            draw(in: NSRect(x: 0, y: 0, width: newSize.width, height: newSize.height), from: .zero, operation: .copy, fraction: 1.0)
            NSGraphicsContext.restoreGraphicsState()

            let resizedImage = NSImage(size: newSize)
            resizedImage.addRepresentation(bitmapRep)
            return resizedImage
        }

        return nil
    }
}

let targetSize = NSSize(width: 256.0, height: 256.0)
let newImageResized = myimage.resized(to: targetSize)
Run Code Online (Sandbox Code Playgroud)

  • 别再看了:我现在已经测试了几乎所有在此处或其他地方给出的“如何调整图像大小而不管分辨率如何”的答案,这是唯一适用于不同图像分辨率的方法,无论您是否有 RetinaDisplay . (3认同)

Lia*_*m R 5

这是Thomas Johannesmeyer 的答案的 Swift 4 版本:

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!)!
}
Run Code Online (Sandbox Code Playgroud)

Marco 的回答的 Swift 4 版本:

func resize(image: NSImage, w: Int, h: Int) -> NSImage {
    let destSize = NSMakeSize(CGFloat(w), CGFloat(h))
    let rep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(destSize.width), pixelsHigh: Int(destSize.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .calibratedRGB, bytesPerRow: 0, bitsPerPixel: 0)
    rep?.size = destSize
    NSGraphicsContext.saveGraphicsState()
    if let aRep = rep {
        NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: aRep)
    }
    image.draw(in: NSMakeRect(0, 0, destSize.width, destSize.height),     from: NSZeroRect, operation: NSCompositingOperation.copy, fraction: 1.0)
    NSGraphicsContext.restoreGraphicsState()
    let newImage = NSImage(size: destSize)
    if let aRep = rep {
        newImage.addRepresentation(aRep)
    }
    return newImage
}
Run Code Online (Sandbox Code Playgroud)