NSBitmapImageRep
x W
サイズのH
があります。
NSImage
を作成してaddRepresentation:
を呼び出します。次に、NSImage
のサイズを変更する必要があります。
setSize
メソッドを試しましたが、機能しません。私は何をすべきか?
編集:この回答はまだ受け入れられている回答ですが、Retina画面を考慮せずに書かれているため、より良い解決策へのリンクをさらに下に向けます。スレッド: Objective-CSwift 4
Pareshの方法は完全に正しいですが、10.8以降非推奨になっているため、動作する10.8コードを以下に投稿します。しかし、パレシュの答えはすべて信用しています。
- (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;
}
lockFocus
を使用したThomasJohannesmeyerの回答は、Retina/HiDPI画面で意図したとおりに機能しません。画面のネイティブスケールでは、 points にサイズ変更されます。 pixel 。
このメソッドは、 この関連する質問 を含むいくつかの回答を組み合わせて、現在の画面のDPIに関係なく、指定された pixel dimension にサイズ変更します。
+ (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;
}
[〜#〜] edit [〜#〜]以下の関数を使用して画像のサイズを変更できます。
- (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
@ Marcoの答えSwift 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)
実際には、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
}
これがSwift 4バージョンの Thomas Johannesmeyerの答え :
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!)!
}
そして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
}
完了Swift 3回答(@Erik Aignerから変更 上記 ):
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
}
}
これが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!)!
}
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]など)の上に直接描画すると、NSBitmapImageRepではなくNSCGImageSnapshotRepが作成されます。