【问题标题】:How to draw EPS data on NSView如何在 NSView 上绘制 EPS 数据
【发布时间】:2013-06-10 08:28:13
【问题描述】:

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

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

- (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:...]

我在这里使用NSKeyedArchiverNSKeyedUnarchiver 来模拟encodeWithCoder:initWithCoder:。因此,请注意 NSImageNSEPSImageRep 表示形式(不包含预览(来自资源分支?)并且纯粹作为 eps 命令加载)未正确绘制在 NSView 上的事实。

感谢任何帮助。

【问题讨论】:

  • 在你加载loadedImage之后,NSImageReps 是附加在它上面的吗?您应该能够NSLog loadedImage 及其图像代表的描述以查看其中的内容。
  • 嗨@gaige,它是完全相同的NSImageRep(NSEPSImageRep),具有完全相同的数据内容。对不起,我之前没有提到它。两幅图像都只包含一种表示形式,即 NSEPSImageRep。
  • 这绝对是奇怪的。我们有一个应用程序可以从NSKeyedArchiver 保存/加载 EPS,而且我们没有遇到任何问题。但是,我们确实爆破了NSImage 并直接保存了NSEPSImageRep,以确保我们获得最高保真度(一旦涉及到缓存,我们在获得最佳版本而不是最小版本时遇到了问题)。其中一些问题可能出现在旧版本的 OSX 上,因为此时该代码已有 3-4 年的历史。你知道文件是EPS吗?在这种情况下,您可以只保存NSData 版本而不是NSImage 吗?
  • 我也试过了。给定的代码是重现它的完整示例。从NSKeyedArchiver 加载时肯定不会绘制。我试图归档NSEPSImageRep 而不是NSImage 并再次使用加载的NSEPSImageRep 构造NSImage,但没有运气。我之前也没有遇到过这种问题。实际的代码很旧并且以前工作过。我想在 Xcode 中将 Base SDK 设置为 10.8 后它开始不起作用(但不确定,将其更改为 10.7 SDK 也无济于事)。
  • 澄清一下,我实际上并没有保存NSEPSImageRep,而是使用[(NSEPSImageRep*)rep EPSRepresentation]保存EPS数据,基本上相当于保存原始EPS数据(理论上)。这对我仍然有效。

标签: macos cocoa nsview eps


【解决方案1】:

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

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

幸运的是,加载很简单,NSImage::initWithData: 会根据数据找出类型。

这是我们长期以来的代码。基本上,它更喜欢 PDF 而不是 EPS,然后它将任何它不理解的东西制作成 TIFF。

+ (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;
}

一旦我们有了NSData*,就可以将其保存在密钥存档中,写入磁盘或其他任何东西。

在回来的路上,加载NSData*然后

NSImage *image = [[NSImage alloc] initWithData: savedData];

你应该准备好了。

【讨论】:

  • 非常感谢。这正是我所需要的。
猜你喜欢
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2016-01-24
  • 1970-01-01
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
相关资源
最近更新 更多