开发者

Why does the Go image package cut+paste looping over pixels?

开发者 https://www.devze.com 2023-03-19 11:43 出处:网络
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 pix开发者_如何

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 pix开发者_如何学编程el-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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消