1

我正在尝试使用 IKImageView 的选择和复制功能。如果您只想拥有一个带有图像的应用程序,选择一个部分并将其复制到剪贴板,这很容易。您将复制菜单选择设置为第一响应者的 copy:(id) 方法,神奇地一切正常。

但是,如果你想要更复杂的东西,比如你想复制作为其他操作的一部分,我似乎找不到执行此操作的方法。

IKImageView 似乎没有复制方法,它似乎没有一个方法,甚至可以告诉你选择的矩形!

我已经阅读了 Hillegass 的书,所以我了解剪贴板的工作原理,而不是如何将图像的一部分移出视图......

现在,我开始认为我将我的项目基于 IKImageView 时犯了一个错误,但它是 Preview 的基础(或者我已经读过),所以我认为它必须是稳定的......无论如何,现在为时已晚,我太深了,无法重新开始......

那么,除了不使用 IKImageView 之外,关于如何手动将选择区域复制到剪贴板的任何建议?

编辑实际上,我找到了 copy(id) 方法,但是当我调用它时,我得到了

 <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 16 bits/pixel; 1-component color space; kCGImageAlphaPremultipliedLast; 2624 bytes/row.

当我通过第一响应者进行正常复制时,这显然不会发生......我理解错误消息,但我不确定它从哪里获取这些参数......

有什么方法可以追踪并查看这是如何发生的?由于显而易见的原因,调试器无济于事,而且我在 Mozilla 中这样做,所以调试器无论如何都不是一个选项......

编辑 2我发现我发现的 copy:(id) 方法可能是复制 VIEW 而不是将图像的一部分复制到剪贴板,这正是我所需要的。

我认为它是剪贴板副本的原因是,在另一个项目中,我直接从编辑菜单从 IKImageView 复制到剪贴板,它只是将副本:(id)发送到 firstResponder,但我不是实际上确定第一响应者用它做了什么......

编辑 3似乎 CGBitmapContextCreate 错误来自[imageView image]错误,奇怪的是,它是一个记录的方法。

有可能发生这种情况是因为我使用 setImage:(id) 方法将图像放入其中,并将其传递给 NSImage*... 是否有其他更聪明的方法可以将 NSImage 放入 IKImageView?

4

2 回答 2

0

in的-copy:方法和IKImageView其他-copy:方法一样:它将当前选择复制到剪贴板。但是,由于IKImageView某种原因,它被实现为私有方法。

您可以直接调用它:

[imageView copy:nil];

这会将当前选择的任何内容复制到剪贴板。

我认为没有办法IKImageView使用公共方法直接访问当前选择的图像内容,这是一个很好的错误报告/功能请求的候选者。

但是,您可以使用私有方法-selectionRect获取CGRect当前选择的 a 并使用它来提取图像的选定部分:

//stop the compiler from complaining when we call a private method
@interface IKImageView (CompilerSTFU)
- (CGRect)selectionRect
@end

@implementation YourController
//imageView is an IBOutlet connected to your IKImageView
- (NSImage*)selectedImage
{
    //get the current selection
    CGRect selection = [imageView selectionRect];

    //get the portion of the image that the selection defines
    CGImageRef selectedImage = CGImageCreateWithImageInRect([imageView image],(CGRect)selection);

    //convert it to an NSBitmapImageRep
    NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithCGImage:selectedImage] autorelease];
    CGImageRelease(selectedImage);

    //create an image from the bitmap data
    NSImage* image = [[[NSImage alloc] initWithData:[bitmap TIFFRepresentation]] autorelease];

    //in 10.6 you can skip converting to an NSBitmapImageRep by doing this:
    //NSImage* image = [[NSImage alloc] initWithCGImage:selectedImage size:NSZeroSize];     
    return image;
}
@end
于 2010-03-25T01:45:30.650 回答
0

好的,所以 copy: nil 失败,并且 [imageView image] 失败,但事实证明,当我首先将它添加到视图中时,我有另一个 NSImage 副本,所以我可以这样做。此外,CGImageCreateWithImageInRect 需要 CGImageRef 而不是 NSImage*,所以我必须进行一些转换。

此外,由于某种原因,选择矩形被翻转,要么是底部起源,图像是顶部,要么相反,所以我不得不翻转它。

出于某种原因,编译器突然开始抱怨 NSRect 与 CGRect 类型不同(这意味着它突然从 32 位变为 64 位或其他什么......不知道为什么......)

无论如何,这是我的 selectedImage 副本:

- (NSImage*)selectedImage
{
    //get the current selection
    CGRect selection = flipCGRect(imageView, [imageView selectionRect]);

    //get the portion of the image that the selection defines
    struct CGImage * full = [[doc currentImage] CGImageForProposedRect: NULL context: NULL hints: NULL];

    CGImageRef selectedImage = CGImageCreateWithImageInRect( full, selection);


    //convert it to an NSBitmapImageRep
    NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithCGImage:selectedImage] autorelease];
    CGImageRelease(selectedImage);

//     //create an image from the bitmap data
    NSImage* image = [[[NSImage alloc] initWithData:[bitmap TIFFRepresentation]] autorelease];

//     //in 10.6 you can skip converting to an NSBitmapImageRep by doing this:
    //NSImage* image = [[NSImage alloc] initWithCGImage:selectedImage size:NSZeroSize];     
    return image;

}

我写了flipCGRect,[doc currentImage]返回一个NSImage* ...

于 2010-03-25T22:33:30.473 回答