Macos 如何在NSView上绘制EPS数据

Macos 如何在NSView上绘制EPS数据,macos,cocoa,nsview,eps,Macos,Cocoa,Nsview,Eps,我正在努力解决在NSView上绘制eps文件的问题。 当我第一次从文件加载eps文件并使用drawInRect:绘制它时,图像显示正确。但是,当我从存档文件加载图像时,它将不会被绘制 我准备了一个肮脏的小例子,你可以复制/粘贴并试用。创建一个新的Cocoa应用程序项目,并将其添加到委托方法中 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Just a sample eps file N

我正在努力解决在
NSView
上绘制eps文件的问题。 当我第一次从文件加载eps文件并使用
drawInRect:
绘制它时,图像显示正确。但是,当我从存档文件加载图像时,它将不会被绘制

我准备了一个肮脏的小例子,你可以复制/粘贴并试用。创建一个新的Cocoa应用程序项目,并将其添加到委托方法中

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
  // Just a sample eps file
  NSURL *url = [NSURL URLWithString: @"http://embedded.eecs.berkeley.edu/concurrency/latex/figure.eps"];
  NSImage *epsImage = [[[NSImage alloc] initWithContentsOfURL: url] autorelease];

  // Encode data
  NSMutableData *mutableData = [[[NSMutableData alloc] init] autorelease];
  NSKeyedArchiver *coder = [[[NSKeyedArchiver alloc] initForWritingWithMutableData: mutableData] autorelease];
  [coder encodeObject: epsImage forKey: @"image"];
  [coder finishEncoding];
  NSString *dataFile = [@"~/Desktop/image.data" stringByExpandingTildeInPath];
  [mutableData writeToFile: dataFile atomically: YES];

  // Decode data
  NSData *data = [NSData dataWithContentsOfFile: dataFile];
  NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData: data];
  NSImage *loadedImage = [decoder decodeObjectForKey: @"image"];

  // Draw image
  NSRect rect;
  rect.origin = NSZeroPoint;
  rect.size = loadedImage.size;

  NSView *view = [[NSApp mainWindow] contentView];
  [view lockFocus];
  [loadedImage drawInRect: rect fromRect: rect operation: NSCompositeSourceOver fraction: 1.0];
  [view unlockFocus];
}
要证明第一个加载的图像绘制正确,只需将行
[loadedImage drawInRect:…]
更改为
[epsImage drawInRect:…]

我在这里使用
NSKeyedArchiver
NSKeyedUnarchiver
来模拟
encodeWithCoder:
initWithCoder:
。因此,请关注这样一个事实,即带有
NSEPSImageRep
表示的
NSImage
,它不包含预览(从资源分叉?)且仅作为eps命令加载,在
NSView
上绘制不正确


感谢您的帮助

由于缓存在
NSImage
上的工作方式,我经常发现,如果我知道NSImageRep的类型,那么实际抓取它会更有效

在我们的代码中,我们发现保存图像最可靠的方法是使用原始格式,但这需要将数据以原始格式保存到其他地方,或者从
NSImageRep
请求数据。不幸的是,
NSImageRep
没有一个通用的
-(NSData*)数据
方法,因此我们最终专门检查了各种类型的
NSImageRep
,并根据我们知道它们是什么来保存它们

幸运的是,加载很简单,因为
NSImage::initWithData:
将根据数据确定类型

这是我们长期以来的代码。基本上,它更喜欢PDF格式,而不是EPS格式,然后它会对任何它不懂的东西大吵大闹

+ (NSData*) dataWithImage:(NSImage*)image kindString:( NSString**)kindStringPtr
{
    if (!image)
        return nil;

    NSData *pdfData=nil, *newData=nil, *epsData=nil, *imageData=nil;;
    NSString *kindString=nil;
    NSArray *reps = [image representations];
    for (NSImageRep *rep in reps) {
        if ([rep isKindOfClass: [NSPDFImageRep class]]) {
            // we have a PDF, so save that
            pdfData = [(NSPDFImageRep*)rep PDFRepresentation];
            PDFDocument *doc = [[PDFDocument alloc] initWithData:pdfData];
            newData = [doc dataRepresentation];
            if (newData && ([newData length]<[pdfData length])) {
                pdfData = newData;
            }
            break;
        }
        if ([rep isKindOfClass: [NSEPSImageRep class]]) {
            epsData = [(NSEPSImageRep*)rep EPSRepresentation];
            break;
        }
    }

    if (pdfData) {
        imageData=pdfData;
        kindString= @"pdfImage";
    } else if (epsData) {
        imageData=epsData;
        kindString=@"epsImage";
    } else {
        // make a big copy
        NSBitmapImageRep *rep0 = [reps objectAtIndex:0];
        if ([rep0 isKindOfClass: [NSBitmapImageRep class]]) {
            [image setSize: NSMakeSize( [rep0 pixelsWide], [rep0 pixelsHigh])];
        }

        imageData = [image TIFFRepresentation];
        kindString=@"tiffImage";
    }

    if (kindStringPtr)
        *kindStringPtr=kindString;
    return imageData;
}

您应该已经准备好了。

loadeImage
中加载后,它附加了什么
NSImageRep
s?您应该能够
NSLog
LoadeImage
及其图像复制的描述,以查看其中的内容。Hi@gaige,它是完全相同的NSImageRep(nsepImageRep),具有完全相同的数据内容。对不起,我以前没提过。两个图像都只包含一个表示,NSEPSImageRep。这确实很奇怪。我们有一个应用程序,可以从
NSKeyedArchiver
保存/加载EPS,我们没有遇到任何问题。但是,我们会将
NSImage
突发并直接保存
NSEPSImageRep
,以确保获得最高的保真度(一旦涉及到缓存,我们就很难获得最佳版本,而不是最小版本)。其中一些问题可能出现在较旧版本的OSX上,因为该代码目前已经有3-4年的历史了。你知道这个文件是EPS吗?在这种情况下,您能否只保存
NSData
版本而不是
NSImage
?我也试过了。给定的代码是复制它的完整示例。从
NSKeyedArchiver
加载时,它肯定不会绘制。我尝试归档
NSEPSImageRep
而不是
NSImage
,并再次用加载的
NSEPSImageRep
构建了
NSImage
,但运气不佳。我以前也没有遇到过这种问题。实际的代码非常旧,以前也使用过。我猜在Xcode中将基本SDK设置为10.8之后,它就开始不起作用了(但不确定,将其更改为10.7 SDK也没有帮助)。为了澄清,我实际上并没有保存
NSEPSImageRep
,而是使用
[(NSEPSImageRep*)rep EPSRepresentation]
保存EPS数据,基本上相当于保存原始EPS数据(理论上)。这对我来说仍然有效。非常感谢。这正是我需要的。
NSImage *image = [[NSImage alloc] initWithData: savedData];