objective-cmacosnsdatansimageviewnsrect

How to make dataWithEPSInsideRect vector rather than bitmap in vector format?


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]];

Solution

  • 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