Изменить размер и сохранить NSImage? - PullRequest
5 голосов
/ 10 марта 2011

У меня есть NSImageView, для которого я получаю изображение из NSOpenPanel.Это прекрасно работает.

Теперь, как мне взять этот NSImage, наполовину его размер и сохранить его в том же формате в том же каталоге, что и оригинал?

Если вы можете помочь ввсе, что я ценю, спасибо.

Ответы [ 7 ]

7 голосов
/ 10 марта 2011

Проверьте пример проекта ImageCrop от Мэтта Джеммелла:
http://mattgemmell.com/source/

Хороший пример, как изменить размер / обрезать изображения.
Наконец, вы можете использовать что-то вроде этого для сохранения результата (грязный пример):

// Write to TIF
[[resultImg TIFFRepresentation] writeToFile:@"/Users/Anne/Desktop/Result.tif" atomically:YES];

// Write to JPG
NSData *imageData = [resultImg  TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.9] forKey:NSImageCompressionFactor];
imageData = [imageRep representationUsingType:NSJPEGFileType properties:imageProps];
[imageData writeToFile:@"/Users/Anne/Desktop/Result.jpg" atomically:NO];
4 голосов
/ 10 марта 2011

Поскольку объекты NSImage являются неизменяемыми, вам необходимо:

  1. Создание базового графического контекста размером с новое изображение.
  2. Нарисуйте NSImage в CGContext. Он должен автоматически масштабироваться для вас.
  3. Создать NSImage из этого контекста
  4. Выпиши новый NSImage
  5. Не забудьте освободить любые временные объекты, которые вы выделили.

Определенно есть и другие варианты, но это первое, что пришло на ум.

3 голосов
/ 19 июля 2012
+(NSImage*) resize:(NSImage*)aImage scale:(CGFloat)aScale
{
    NSImageView* kView = [[NSImageView alloc] initWithFrame:NSMakeRect(0, 0, aImage.size.width * aScale, aImage.size.height* aScale)];
    [kView setImageScaling:NSImageScaleProportionallyUpOrDown];
    [kView setImage:aImage];

    NSRect kRect = kView.frame;
    NSBitmapImageRep* kRep = [kView bitmapImageRepForCachingDisplayInRect:kRect];
    [kView cacheDisplayInRect:kRect toBitmapImageRep:kRep];

    NSData* kData = [kRep representationUsingType:NSJPEGFileType properties:nil];
    return [[NSImage alloc] initWithData:kData];
}
2 голосов
/ 24 мая 2012

Вот конкретная реализация

-(NSImage*)resizeImage:(NSImage*)input by:(CGFloat)factor
{    
    NSSize size = NSZeroSize;      
    size.width = input.size.width*factor;
    size.height = input.size.height*factor; 

    NSImage *ret = [[NSImage alloc] initWithSize:size];
    [ret lockFocus];
    NSAffineTransform *transform = [NSAffineTransform transform];
    [transform scaleBy:factor];  
    [transform concat]; 
    [input drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];    
    [ret unlockFocus];        

    return [ret autorelease];
}

Имейте в виду, что это основано на пикселях, с HiDPI нужно учитывать масштабирование, его просто получить:

-(CGFloat)pixelScaling
{
    NSRect pixelBounds = [self convertRectToBacking:self.bounds];
    return pixelBounds.size.width/self.bounds.size.width;
}
0 голосов
/ 06 апреля 2016

Чтобы изменить размер изображения

- (NSImage *)scaleImage:(NSImage *)anImage newSize:(NSSize)newSize
{
    NSImage *sourceImage = anImage;
    if ([sourceImage isValid])
    {
        if (anImage.size.width == newSize.width && anImage.size.height == newSize.height && newSize.width <= 0 && newSize.height <= 0) {
            return anImage;
        }

        NSRect oldRect = NSMakeRect(0.0, 0.0, anImage.size.width, anImage.size.height);
        NSRect newRect = NSMakeRect(0,0,newSize.width,newSize.height);
        NSImage *newImage = [[NSImage alloc] initWithSize:newSize];

        [newImage lockFocus];
        [sourceImage drawInRect:newRect fromRect:oldRect operation:NSCompositeCopy fraction:1.0];
        [newImage unlockFocus];

        return newImage;
    }
}
0 голосов
/ 19 октября 2012

Вот код, который более широко использует Core Graphics, чем другие ответы.Это сделано в соответствии с подсказками в Ответ Марка Талмана на этот вопрос.

Этот код уменьшает NSImage в зависимости от целевой ширины изображения.Это несколько неприятно, но все же полезно в качестве дополнительного примера для документирования, как нарисовать NSImage в CGContext и как записать содержимое CGBitmapContext и CGImage в файл.

Youможет захотеть добавить дополнительную проверку ошибок.Мне не нужно это для моего случая использования.

- (void)generateThumbnailForImage:(NSImage*)image atPath:(NSString*)newFilePath forWidth:(int)width
{
    CGSize size = CGSizeMake(width, image.size.height * (float)width / (float)image.size.width);
    CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();

    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
    CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, size.width * 4, rgbColorspace, bitmapInfo);
    NSGraphicsContext * graphicsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO];
    [NSGraphicsContext setCurrentContext:graphicsContext];

    [image drawInRect:NSMakeRect(0, 0, size.width, size.height) fromRect:NSMakeRect(0, 0, image.size.width, image.size.height) operation:NSCompositeCopy fraction:1.0];

    CGImageRef outImage = CGBitmapContextCreateImage(context);
    CFURLRef outURL = (CFURLRef)[NSURL fileURLWithPath:newFilePath];
    CGImageDestinationRef outDestination = CGImageDestinationCreateWithURL(outURL, kUTTypeJPEG, 1, NULL);
    CGImageDestinationAddImage(outDestination, outImage, NULL);
    if(!CGImageDestinationFinalize(outDestination))
    {
        NSLog(@"Failed to write image to %@", newFilePath);
    }
    CFRelease(outDestination);
    CGImageRelease(outImage);
    CGContextRelease(context);
    CGColorSpaceRelease(rgbColorspace);
}
0 голосов
/ 21 сентября 2011

Apple имеет исходный код для уменьшения масштаба и сохранения изображений, найденный здесь http://developer.apple.com/library/mac/#samplecode/Reducer/Introduction/Intro.html

...