【问题标题】:Another IKImageView Question: copying a region另一个 IKImageView 问题:复制区域
【发布时间】:2010-03-22 21:49:18
【问题描述】:

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

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

IKImageView 似乎没有复制方法,它似乎没有甚至可以告诉您所选矩形的方法!

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

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

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

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

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

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

有什么方法可以追踪到这并看看这是怎么发生的?由于显而易见的原因,以及我在 Mozilla 中执行此操作的事实,调试器无济于事,因此无论如何调试器都不是一个选项...

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

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

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

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

【问题讨论】:

  • 您绝对可以在Mozilla/Firefox等外部应用程序中调试插件。只需在您的 Xcode 项目中创建一个自定义可执行文件并将其指向您要在其中进行调试的应用程序。我已经使用 Safari、Dreamweaver、Adobe GoLive 等成功地完成了这项工作。
  • “我突然想到我发现的 copy:(id) 方法可能是复制 VIEW 而不是将一大块图像复制到剪贴板……” 不,您正在考虑 copy (注意没有参数),它返回对象的副本并且不适用于视图。 copy:(一个参数)`是一个动作,它告诉接收器(视图)将其选择复制到剪贴板。

标签: objective-c cocoa imagekit ikimageview


【解决方案1】:

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

你可以直接调用它:

[imageView copy:nil];

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

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

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

//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

【讨论】:

  • 别忘了测试imageView是否响应selectionRect。由于这是一个私有方法,Apple 可以随时重命名、更改或删除该方法,如果它无条件发送该消息会破坏您的代码。
  • 当我尝试 [imageView copy:nil] 我得到 : CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 16 位/像素; 1-分量色彩空间; kCGImageAlphaPremultipliedLast; 2624 字节/行。
  • 嗯,对我有用。您在图像视图中有什么样的图像?在将其分配给图像视图之前尝试将其转换为 32 位 RGBA 图像,然后看看是否有更多成功。这个限制可能是-copy: 方法是私有的原因。
  • 它以第 4 组 B/W TIFF 开始。我将它放入 NSImage*,然后使用 setImage:(id) 将 NSImage* 加载到视图中(这也是私有的)我做了一个快速测试,是的,看来 copy:(id) 没有与第 4 组 B/W TIFF 合作......有点奇怪......
【解决方案2】:

好的,所以 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*...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多