为什么 Go 图像包会在像素上循环剪切和粘贴?

发布于 2024-11-19 03:45:48 字数 824 浏览 2 评论 0原文

如果你在这里查看镜像包 http://golang.org/src/pkg/image /image.go 您可以看到每个图像的 Opaque() 实现都执行相同的操作,仅在特定于像素的逻辑上有所不同。

这是有原因的吗?任何通用解决方案的效率都会较低吗?这只是一个疏忽吗?类型系统是否存在一些限制(我看不到),这会使多态 [was: generic] 方法变得困难?

[编辑] 我正在考虑的解决方案(不需要 Java 意义上的泛型)是这样的:


type ColorPredicate func(c image.Color) bool;

func AllPixels (p *image.Image, q ColorPredicate) bool {
  var r = p.Bounds()
  if r.Empty() {
    return true
  }
  for y := r.Min.Y; y < r.Max.Y; y++ {
    for x := r.Min.X; x < r.Max.X; x++ {
      if ! q(p.At(x,y)) {
        return false
      }
    }
  }
  return true
}

但是我在编译它时遇到了麻烦(对于 Go 来说仍然很新 - 它将使用图像进行编译,但是不使用图像指针!)。

是不是太难优化了? (您需要进行函数内联,但是这样就不会从循环中取出任何类型检查吗?)。另外,我现在意识到我不应该早先使用“通用”这个词——我只是以通用的方式表达它。

If you look at the image package here http://golang.org/src/pkg/image/image.go you can see that the implementation of Opaque() for every image does the same thing, differing only in the pixel-specific logic.

Is there a reason for this? Would any general solution be less efficient? Is it just an oversight? Is there some limitation (I cannot see one) to the type system that would make a polymorphic [was: generic] approach difficult?

[edit] The kind of solution I was thinking of (which does not need generics in the Java sense) would be like:


type ColorPredicate func(c image.Color) bool;

func AllPixels (p *image.Image, q ColorPredicate) bool {
  var r = p.Bounds()
  if r.Empty() {
    return true
  }
  for y := r.Min.Y; y < r.Max.Y; y++ {
    for x := r.Min.X; x < r.Max.X; x++ {
      if ! q(p.At(x,y)) {
        return false
      }
    }
  }
  return true
}

but I am having trouble getting that to compile (still very new to Go - it will compile with an image, but not with an image pointer!).

Is that too hard to optimise? (you would need to have function inlining, but then wouldn't any type checking be pulled out of the loop?). Also, I now realise I shouldn't have used the word "generic" earlier - I meant it only in a generic (ha) way.

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

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

发布评论

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

评论(2

请你别敷衍 2024-11-26 03:45:48

类型系统有一个限制,它阻止了通用解决方案(或至少使其效率非常低)。

例如,RGBA.Opaque 和 NRGBA.Opaque 的主体是相同的,因此您会认为它们可以分解为具有如下签名的第三个函数:

func opaque(pix []Color, stride int, rect Rectangle) bool

您想这样调用该函数:

func (p *RGBA) Opaque() bool {
    return opaque([]Color(p.Pix), p.Stride, p.Rect)
}

但是你不能。 p.Pix 无法转换为 []Color,因为这些类型具有不同的内存表示形式,并且规范禁止这样做。我们可以分配一个新的切片,转换 p.Pix 的每个单独元素,然后传递它,但这会非常低效。

观察 RGBAColor 和 NRGBAColor 具有完全相同的结构。也许我们可以只为这两种类型分解函数,因为像素切片的内存表示完全相同:

func opaque(pix []RGBAColor, stride int, rect Rectangle) bool

func (p *NRGBA) Opaque() bool {
    return opaque([]RGBAColor(p.Pix), p.Stride, p.Rect)
}

唉,这又是不允许的。这似乎更多是一个规范/语言问题,而不是技术问题。我确信这之前已经出现在邮件列表中,但我找不到对此的良好讨论。

这似乎是泛型可以派上用场的领域,但 Go 中还没有泛型的解决方案。

There is a limitation to the type system which prevents a general solution (or at least makes it very inefficient).

For example, the bodies of RGBA.Opaque and NRGBA.Opaque are identical, so you'd think that they could be factored out into a third function with a signature something like this:

func opaque(pix []Color, stride int, rect Rectangle) bool

You'd like to call that function this way:

func (p *RGBA) Opaque() bool {
    return opaque([]Color(p.Pix), p.Stride, p.Rect)
}

But you can't. p.Pix can't be converted to []Color because those types have different in-memory representations and the spec forbids it. We could allocate a new slice, convert each individual element of p.Pix, and pass that, but that would be very inefficient.

Observe that RGBAColor and NRGBAColor have the exact same structure. Maybe we could factor out the function for just those two types, since the in-memory representation of the pixel slices is exactly the same:

func opaque(pix []RGBAColor, stride int, rect Rectangle) bool

func (p *NRGBA) Opaque() bool {
    return opaque([]RGBAColor(p.Pix), p.Stride, p.Rect)
}

Alas, again this isn't allowed. This seems to be more of a spec/language issue than a technical one. I'm sure this has come up on the mailing list before, but I can't find a good discussion of it.

This seems like an area where generics would come in handy, but there's no solution for generics in Go yet.

怼怹恏 2024-11-26 03:45:48

为什么 Go 没有泛型
类型?

在某些地方很可能会添加泛型
观点。我们并不感到紧迫
他们,虽然我们了解一些
程序员就是这么做的。

泛型很方便,但它们来了
以类型的复杂性为代价
系统和运行时。我们还没有
找到了一个有价值的设计
与复杂性成正比,
尽管我们继续思考
它。同时,Go 的内置地图和
切片,加上使用的能力
构造空接口
容器(显式拆箱)
意味着在很多情况下可以
编写执行泛型功能的代码
将会启用,但不太顺利。

这仍然是一个悬而未决的问题。

Why does Go not have generic
types?

Generics may well be added at some
point. We don't feel an urgency for
them, although we understand some
programmers do.

Generics are convenient but they come
at a cost in complexity in the type
system and run-time. We haven't yet
found a design that gives value
proportionate to the complexity,
although we continue to think about
it. Meanwhile, Go's built-in maps and
slices, plus the ability to use the
empty interface to construct
containers (with explicit unboxing)
mean in many cases it is possible to
write code that does what generics
would enable, if less smoothly.

This remains an open issue.

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