在 PyObjC 中的 NSImage 上绘制文本时出错

发布于 2024-07-29 22:45:25 字数 2444 浏览 1 评论 0原文

我正在尝试使用 PyObjC 用一些文本覆盖图像,同时努力回答我的问题, “使用 OS X 内置的工具对图像进行注释”。 通过引用 CocoaMagic,这是 RMagick,我想出了这个:

#!/usr/bin/env python

from AppKit import *

source_image = "/Library/Desktop Pictures/Nature/Aurora.jpg"
final_image = "/Library/Desktop Pictures/.loginwindow.jpg"
font_name = "Arial"
font_size = 76
message = "My Message Here"

app = NSApplication.sharedApplication()  # remove some warnings

# read in an image
image = NSImage.alloc().initWithContentsOfFile_(source_image)
image.lockFocus()

# prepare some text attributes
text_attributes = NSMutableDictionary.alloc().init()
font = NSFont.fontWithName_size_(font_name, font_size)
text_attributes.setObject_forKey_(font, NSFontAttributeName)
text_attributes.setObject_forKey_(NSColor.blackColor, NSForegroundColorAttributeName)

# output our message
message_string = NSString.stringWithString_(message)
size = message_string.sizeWithAttributes_(text_attributes)
point = NSMakePoint(400, 400)
message_string.drawAtPoint_withAttributes_(point, text_attributes)

# write the file
image.unlockFocus()
bits = NSBitmapImageRep.alloc().initWithData_(image.TIFFRepresentation)
data = bits.representationUsingType_properties_(NSJPGFileType, nil)
data.writeToFile_atomically_(final_image, false)

当我运行它时,我得到这个:

Traceback (most recent call last):
  File "/Users/clinton/Work/Problems/TellAtAGlance/ObviouslyTouched.py", line 24, in <module>
    message_string.drawAtPoint_withAttributes_(point, text_attributes)
ValueError: NSInvalidArgumentException - Class OC_PythonObject: no such selector: set

在文档中查找drawAtPoint: withAttributes:,它说,“你应该只在 NSView 具有焦点时调用此方法。” NSImage 不是 NSView 的子类,但我希望这能起作用,并且非常相似的东西似乎可以在 Ruby 示例中起作用。

我需要改变什么才能使这项工作正常进行?


我重写了代码,逐行忠实地将其转换为 Objective-C 基础工具。 它可以工作,没有问题。 [如果有理由的话,我很乐意在这里发帖。]

那么问题就变成了:

[message_string drawAtPoint:point withAttributes:text_attributes];

与 有何不同

message_string.drawAtPoint_withAttributes_(point, text_attributes)

? 有没有办法知道哪个“OC_PythonObject”引发 NSInvalidArgumentException?

I'm trying to overlay an image with some text using PyObjC, while striving to answer my question, "Annotate images using tools built into OS X". By referencing CocoaMagic, a RubyObjC replacement for RMagick, I've come up with this:

#!/usr/bin/env python

from AppKit import *

source_image = "/Library/Desktop Pictures/Nature/Aurora.jpg"
final_image = "/Library/Desktop Pictures/.loginwindow.jpg"
font_name = "Arial"
font_size = 76
message = "My Message Here"

app = NSApplication.sharedApplication()  # remove some warnings

# read in an image
image = NSImage.alloc().initWithContentsOfFile_(source_image)
image.lockFocus()

# prepare some text attributes
text_attributes = NSMutableDictionary.alloc().init()
font = NSFont.fontWithName_size_(font_name, font_size)
text_attributes.setObject_forKey_(font, NSFontAttributeName)
text_attributes.setObject_forKey_(NSColor.blackColor, NSForegroundColorAttributeName)

# output our message
message_string = NSString.stringWithString_(message)
size = message_string.sizeWithAttributes_(text_attributes)
point = NSMakePoint(400, 400)
message_string.drawAtPoint_withAttributes_(point, text_attributes)

# write the file
image.unlockFocus()
bits = NSBitmapImageRep.alloc().initWithData_(image.TIFFRepresentation)
data = bits.representationUsingType_properties_(NSJPGFileType, nil)
data.writeToFile_atomically_(final_image, false)

When I run it, I get this:

Traceback (most recent call last):
  File "/Users/clinton/Work/Problems/TellAtAGlance/ObviouslyTouched.py", line 24, in <module>
    message_string.drawAtPoint_withAttributes_(point, text_attributes)
ValueError: NSInvalidArgumentException - Class OC_PythonObject: no such selector: set

Looking in the docs for drawAtPoint:withAttributes:, it says, "You should only invoke this method when an NSView has focus." NSImage is not a subclass of NSView, but I would hope this would work, and something very similar seems to work in the Ruby example.

What do I need to change to make this work?


I rewrote the code, converting it faithfully, line for line, into an Objective-C Foundation tool. It works, without problems. [I would be happy to post if here if there is a reason to do so.]

The question then becomes, how does:

[message_string drawAtPoint:point withAttributes:text_attributes];

differ from

message_string.drawAtPoint_withAttributes_(point, text_attributes)

? Is there a way to tell which "OC_PythonObject" is raising the NSInvalidArgumentException?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

香草可樂 2024-08-05 22:45:25

以下是上面代码中的问题:

text_attributes.setObject_forKey_(NSColor.blackColor, NSForegroundColorAttributeName)
->
text_attributes.setObject_forKey_(NSColor.blackColor(), NSForegroundColorAttributeName)

bits = NSBitmapImageRep.alloc().initWithData_(image.TIFFRepresentation)
data = bits.representationUsingType_properties_(NSJPGFileType, nil)
->
bits = NSBitmapImageRep.imageRepWithData_(image.TIFFRepresentation())
data = bits.representationUsingType_properties_(NSJPEGFileType, None)

确实有轻微的拼写错误。

请注意,代码的中间部分可以替换为这个更具可读性的变体:

# prepare some text attributes
text_attributes = { 
    NSFontAttributeName : NSFont.fontWithName_size_(font_name, font_size),
    NSForegroundColorAttributeName : NSColor.blackColor() 
}

# output our message 
NSString.drawAtPoint_withAttributes_(message, (400, 400), text_attributes)

我通过查看 NodeBox< 的源代码了解到了这一点/a>,psyphography.py 的十二行和cocoa.py,特别是保存和_getImageData 方法。

Here are the problems in the above code:

text_attributes.setObject_forKey_(NSColor.blackColor, NSForegroundColorAttributeName)
->
text_attributes.setObject_forKey_(NSColor.blackColor(), NSForegroundColorAttributeName)

bits = NSBitmapImageRep.alloc().initWithData_(image.TIFFRepresentation)
data = bits.representationUsingType_properties_(NSJPGFileType, nil)
->
bits = NSBitmapImageRep.imageRepWithData_(image.TIFFRepresentation())
data = bits.representationUsingType_properties_(NSJPEGFileType, None)

Minor typos indeed.

Note that the middle portion of the code can be replaced with this more-readable variant:

# prepare some text attributes
text_attributes = { 
    NSFontAttributeName : NSFont.fontWithName_size_(font_name, font_size),
    NSForegroundColorAttributeName : NSColor.blackColor() 
}

# output our message 
NSString.drawAtPoint_withAttributes_(message, (400, 400), text_attributes)

I learned this by looking at the source code to NodeBox, the twelve lines of psyphography.py and cocoa.py, particularly the save and _getImageData methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文