0

Hello i'm trying to export data from an NSImageView as an EPS vector however the export doesn't appear to be vector but more like a bitmap in EPS format.

Can anyone suggest where I am going wrong and how I can make it vector?

s = [[graphicImage image] size];
offscreen = [[NSImageView alloc] initWithFrame:NSMakeRect(0,0,s.width*10, s.height)];
[offscreen setImage:[graphicImage image]];
export = [offscreen dataWithEPSInsideRect:[offscreen bounds]];
  • What are you trying to accomplish? – Willeke Oct 28 '21 at 08:44
  • I am using the following open source code to generate a QR code it's for iOS but i've adapted it to MacOS - https://github.com/arciem/iOS-QR-Code-Encoder/blob/master/Classes/QRCodeGenerator.m i've custoised the QR code to my needs in code but need to be able to export as a vector. – GeraldTheGerm Oct 28 '21 at 08:57
  • `CGBitmapContextCreate` creates a bitmap and `NSImageView` does not convert a bitmap to a vector. – Willeke Oct 28 '21 at 09:27
  • Ok is there an alternative to CGBitmapContextCreate that I can use which can support vector? – GeraldTheGerm Oct 28 '21 at 09:50
  • `CGPDFContextCreate` – Willeke Oct 28 '21 at 10:07
  • Ok so i've created a second CGContextRef for the PDF: `CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef ctx = CGBitmapContextCreate(0, size, size, 8, size * 4, colorSpace, kCGImageAlphaPremultipliedLast); NSRect rect = CGRectMake(0.0, 0.0, 750.0, 750.0); NSMutableData* outputData = [[NSMutableData alloc] init]; CGDataConsumerRef dataConsumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)outputData); CGContextRef ctx2 = CGPDFContextCreate(dataConsumer, &rect, NULL); ` Is there an alternative for CGImageRef for PDF? – GeraldTheGerm Oct 28 '21 at 11:05
  • I don't know how you are going to use the image but how about `NSImage`? If you're still trying to use `NSImageView` then you're on the wrong track. My advice is to use the answer below. – Willeke Oct 28 '21 at 12:44
  • Thanks Willeke, i'm still trying to understand the below answer - so can I confirm i'm correct in my undertstanding the NSImageView is for raster only - however the NSImage object can take a vector or raster image? So I would need to use CGPDFContextCreate to a NSImage and then draw the NSImage to a view and then use the views dataWithEPSInsideRect method? so I can export the image as a vector EPS? – GeraldTheGerm Oct 28 '21 at 13:12

1 Answers1

2

You are using an NSImageView which is a view for displaying raster images. It should not be a surprise that it returns raster data.

Quartz2D's preferred metafile format is PDF. There are some legacy routines around, likely from NextSTEP's display postscript days which focus on generating EPS from views and windows.

You might try creating an offscreen view, setting up the draw method of the view to include your graphic and then use the View's dataWithEPSInsideRect:(NSRect)rect; method. I don't know if that will yield a vector drawing, or just a raster image of the content of the view though.

It is curious to me that you are trying to generate EPS in this day in age (the post-PDF era). I remember EPS as being particularly problematic in the days I worked on Macromedia FreeHand. But best of luck!

Here is MacOS playground example of using an NSView to create a vector EPS file:

import Cocoa
import PlaygroundSupport

class  MyView : NSView {
    override func draw(_ rect: CGRect) {
        if let cgContext = NSGraphicsContext.current?.cgContext
        {
            cgContext.addRect(self.bounds.insetBy(dx: 20, dy: 20))
            cgContext.strokePath()
            cgContext.addEllipse(in: bounds.insetBy(dx: 40 , dy: 40))

            cgContext.setFillColor(NSColor.yellow.cgColor)
            cgContext.fillPath()

        }
    }
}

let myView = MyView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))

PlaygroundSupport.PlaygroundPage.current.liveView = myView

let data = myView.dataWithEPS(inside: myView.bounds)
try data.write(to: URL.init(fileURLWithPath: "/Users/sthompson/Desktop/viewContent.eps"))

@interface MyView : NSView
@end

@implementation MyView

- (void) drawRect: (CGRect) rect
{
    CGContextRef cgContext = [[NSGraphicsContext currentContext] CGContext];

    CGContextSaveGState(cgContext);
    CGContextAddRect(cgContext, CGRectInset(self.bounds, 20, 20));
    CGContextStrokePath(cgContext);
    CGContextAddEllipseInRect(cgContext, CGRectInset(self.bounds, 40, 40));
    CGContextSetFillColorWithColor(cgContext, [[NSColor yellowColor] CGColor]);
    CGContextFillPath(cgContext);
    CGContextRestoreGState(cgContext);
}

+ (void) tryItOut {
    MyView *myView = [[MyView alloc] initWithFrame: NSRectFromCGRect(CGRectMake(0, 0, 320, 480))];

    NSData *data = [myView dataWithEPSInsideRect: myView.bounds];
    [data writeToURL: [NSURL fileURLWithPath: @"/Users/sthompson/Desktop/sampleEPSFile.eps"] atomically: YES];
}
@end
Scott Thompson
  • 22,629
  • 4
  • 32
  • 34