在Go语言中将图像编码为JPEG

6
我是一名有用的助手,可以为您进行文本翻译。
我有一个名为SpriteImage的结构体,其定义如下:
type SpriteImage struct {
    dimentions      image.Point
    lastImgPosition image.Point
    sprite          *image.NRGBA
}

在我的流程中,我首先初始化一个新的这样的结构体:
func NewSpriteImage(width, height int) SpriteImage {
    c := color.RGBA{0xff, 0xff, 0xff, 0xff}
    blankImage := imaging.New(width, height, c)

    return SpriteImage{
        dimentions:      image.Point{X: width, Y: height},
        lastImgPosition: image.Point{X: 0, Y: 0},
        sprite:          blankImage,
    }
}

然后我像这样向SpriteImage添加图像:
func (s *SpriteImage) AddImage(img image.Image) error {
    imgWidth := img.Bounds().Dx()
    imgHeight := img.Bounds().Dy()

    // Make sure new image will fit into the sprite.
    if imgWidth != s.dimentions.X {
        return fmt.Errorf("image width %d mismatch sprite width %d", imgWidth, s.dimentions.X)
    }

    spriteHeightLeft := s.dimentions.Y - s.lastImgPosition.Y
    if imgHeight > spriteHeightLeft {
        return fmt.Errorf("image height %d won't fit into sprite, sprite free space %d ", imgHeight, s.dimentions.Y)
    }

    // add image to sprite
    s.sprite = imaging.Paste(s.sprite, img, s.lastImgPosition)

    // update next image position within sprite
    s.lastImgPosition = s.lastImgPosition.Add(image.Point{X: 0, Y: imgHeight})

    return nil
}

最终,我希望将这个 SpriteImage 编码为 JPEG 格式。但是似乎行不通。 原生的JPEG编码函数 接受一个图像,但我只有一个 image.NRGBA 类型的图像。所以我使用了 github.com/disintegration/imaging 库,代码如下:
func (s SpriteImage) GetBytes() ([]byte, error) {
    var b bytes.Buffer
    w := bufio.NewWriter(&b)

    if s.sprite == nil {
        return nil, fmt.Errorf("sprite is nil")
    }

    if err := imaging.Encode(w, s.sprite, imaging.JPEG); err != nil {
        return nil, err
    }

    return b.Bytes(), nil
}

然而,看起来返回的字节实际上不是JPEG格式的。原生的Go JPEG库将无法将这些字节解码为Go图像结构体。如果我尝试这样解码这些字节到图像:

     m, _, err := image.Decode(reader)
     if err != nil {
        log.Fatal(err)
     }

我遇到了一个错误:

图像: 未知格式

有什么想法吗?

2个回答

3

看起来这可能是与 github.com/disintegration/imaging 库有关的问题。我在该库的页面上发布了一个问题。

如果我将我的 GetBytes() 函数更改为以下内容,则可以获得有效的JPEG:

func (s SpriteImage) GetBytes() ([]byte, error) {
    var b bytes.Buffer
    w := bufio.NewWriter(&b)

    if s.sprite == nil {
        return nil, fmt.Errorf("sprite is nil")
    }

    im := s.sprite
    err := jpeg.Encode(w, im, &jpeg.Options{jpegCompression})

    if err != nil {
        fmt.Println(err)
    }

    return b.Bytes(), nil
}

1
也许有些需要检查的地方:当您没有包含image/jpeg库并特别使用它进行解码时,image: unknown format是一种常见错误。
import (
  "image/jpeg"
  "io"
)

...    
  img, err := jpeg.Decode(r)
  if err != nil {
     return err
  }
...

有些人尝试使用image.Decode,但仍需要包含image/jpeg库。
我相信它可以通过盲目包含来实现:
import (
  _ "image/jpeg"
  "image"
  "io"
)

...    
  img, err := image.Decode(r)
  if err != nil {
     return err
  }
...

1
谢谢您的建议,这正是我的问题所在。我想知道为什么image.Decode文档中没有提到这一点。 - Sebastiaan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接