Подтвердить что ты не робот

IOS для Mac GraphicContext Объяснение/преобразование

Я программировал в течение двух лет на iOS и никогда на Mac. Я работаю над небольшой утилитой для обработки некоторых простых потребностей в изображении, которые у меня есть в моей iOS-разработке. Во всяком случае, у меня есть рабочий код в iOS, который работает отлично, но я совершенно не знаю, какие эквиваленты для Mac.

Я пробовал кучу разных вещей, но я действительно не понимаю, как начать графический контекст на Mac вне метода "drawRect:". На iPhone я бы просто использовал UIGraphicsBeghinImageContext(). Я знаю, что другой пост сказал использовать lockFocus/unlockFocus, но я не уверен, как именно сделать эту работу для моих нужд. О, и я действительно скучаю по UIImage "CGImage". Я не понимаю, почему NSImage не может его иметь, хотя это звучит немного сложнее, чем просто.

Вот мой рабочий код на iOS - он просто создает отраженное изображение из маски и объединяет их:

    UIImage *mask = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"Mask_Image.jpg" ofType:nil]];
    UIImage *image = [UIImage imageNamed::@"Test_Image1.jpg"];
    UIGraphicsBeginImageContextWithOptions(mask.size, NO, [[UIScreen mainScreen]scale]);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, 0.0, mask.size.height);
    CGContextScaleCTM(ctx, 1.f, -1.f);
    [image drawInRect:CGRectMake(0.f, -mask.size.height, image.size.width, image.size.height)];
    UIImage *flippedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGImageRef maskRef = mask.CGImage;
    CGImageRef maskCreate = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                              CGImageGetHeight(maskRef),
                                              CGImageGetBitsPerComponent(maskRef),
                                              CGImageGetBitsPerPixel(maskRef),
                                              CGImageGetBytesPerRow(maskRef),
                                              CGImageGetDataProvider(maskRef), NULL, false);
    CGImageRef masked = CGImageCreateWithMask([flippedImage CGImage], maskCreate);

    CGImageRelease(maskCreate);

    UIImage *maskedImage = [UIImage imageWithCGImage:masked];
    CGImageRelease(masked);

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(image.size.width, image.size.height + (image.size.height * .5)), NO, [[UIScreen mainScreen]scale]);

    [image drawInRect:CGRectMake(0,0, image.size.width, image.size.height)];
    [maskedImage drawInRect:CGRectMake(0, image.size.height, maskedImage.size.width, maskedImage.size.height)];

    UIImage *anotherImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext(); 

//do something with anotherImage

Любые предложения по достижению этого (просто) на Mac?

4b9b3361

Ответ 1

Вот простой пример, который рисует синий круг в NSImage (я использую ARC в этом примере, добавляю сохранение/релизы по вкусу)

NSSize size = NSMakeSize(50, 50);

NSImage* im = [[NSImage alloc] initWithSize:size];
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc]
                            initWithBitmapDataPlanes:NULL
                                          pixelsWide:size.width
                                          pixelsHigh:size.height
                                       bitsPerSample:8
                                     samplesPerPixel:4
                                            hasAlpha:YES
                                            isPlanar:NO
                                      colorSpaceName:NSCalibratedRGBColorSpace
                                         bytesPerRow:0
                                        bitsPerPixel:0];

[im addRepresentation:rep];

[im lockFocus];

CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
CGContextClearRect(ctx, NSMakeRect(0, 0, size.width, size.height));
CGContextSetFillColorWithColor(ctx, [[NSColor blueColor] CGColor]);
CGContextFillEllipseInRect(ctx, NSMakeRect(0, 0, size.width, size.height));

[im unlockFocus];

[[im TIFFRepresentation] writeToFile:@"/Users/USERNAME/Desktop/foo.tiff" atomically:NO];

Основное отличие состоит в том, что в ОС X вам сначала нужно создать изображение, затем вы можете начать рисовать его; на iOS вы создаете контекст, а затем извлекаете из него изображение.

В принципе, lockFocus делает текущий контекст изображением, и вы рисуете непосредственно на нем, а затем используете изображение.

Я не совсем уверен, отвечает ли это на весь ваш вопрос, но я думаю, что это хотя бы одна его часть.

Ответ 2

Ну, вот записка на UIGraphicsBeginImageContextWithOptions:

UIGraphicsBeginImageContextWithOptions

Создает графический контекст на основе растрового изображения с указанными параметрами.

эквивалент OS X, который также доступен в iOS (и UIGraphicsBeginImageContextWithOptions, возможно, является оболочкой), CGBitmapContextCreate:

Объявлено как:

CGContextRef CGBitmapContextCreate (
   void *data,
   size_t width,
   size_t height,
   size_t bitsPerComponent,
   size_t bytesPerRow,
   CGColorSpaceRef colorspace,
   CGBitmapInfo bitmapInfo
);

Хотя это API C, вы можете думать о CGBitmapContext как подклассе CGContext. Он отображает буфер пикселей, тогда как CGContext отображает абстрактное назначение.

Для UIGraphicsGetImageFromCurrentImageContext вы можете использовать CGBitmapContextCreateImage и передать свой растровый контекст для создания CGImage.

Ответ 3

Вот версия версии Cobbal для Swift (2.1/10.11 API-совместимая версия)

    let size = NSMakeSize(50, 50);
    let im = NSImage.init(size: size)

    let rep = NSBitmapImageRep.init(bitmapDataPlanes: nil,
        pixelsWide: Int(size.width),
        pixelsHigh: Int(size.height),
        bitsPerSample: 8,
        samplesPerPixel: 4,
        hasAlpha: true,
        isPlanar: false,
        colorSpaceName: NSCalibratedRGBColorSpace,
        bytesPerRow: 0,
        bitsPerPixel: 0)

    im.addRepresentation(rep!)
    im.lockFocus()

    let rect = NSMakeRect(0, 0, size.width, size.height)
    let ctx = NSGraphicsContext.currentContext()?.CGContext
    CGContextClearRect(ctx, rect)
    CGContextSetFillColorWithColor(ctx, NSColor.blackColor().CGColor)
    CGContextFillRect(ctx, rect)

    im.unlockFocus()

Ответ 4

Swift3 версия Cobbal answer

   let size = NSMakeSize(50, 50);
    let im = NSImage.init(size: size)

    let rep = NSBitmapImageRep.init(bitmapDataPlanes: nil,
                                    pixelsWide: Int(size.width),
                                    pixelsHigh: Int(size.height),
                                    bitsPerSample: 8,
                                    samplesPerPixel: 4,
                                    hasAlpha: true,
                                    isPlanar: false,
                                    colorSpaceName: NSCalibratedRGBColorSpace,
                                    bytesPerRow: 0,
                                    bitsPerPixel: 0)


   im.addRepresentation(rep!)
    im.lockFocus()

    let rect = NSMakeRect(0, 0, size.width, size.height)
    let ctx = NSGraphicsContext.current()?.cgContext
    ctx!.clear(rect)
    ctx!.setFillColor(NSColor.black.cgColor)
    ctx!.fill(rect)

    im.unlockFocus()