无法使用Golangs ImageMagick库转换大图像

0lvr5msh  于 2023-03-10  发布在  Go
关注(0)|答案(1)|浏览(145)

我正在尝试加载一个大图像(780 MB)与Golangs ImageMagick库,并更改图像的格式从PNG到PTIF(金字塔tiff)。当我运行该程序时,不同的事情可能会发生:

  • 有时会关闭Vscode(内存消耗高)
  • 当它挂起的时候,它不会停止程序,但是它也不会再使用任何资源(观察htop)。
  • 有时我会得到错误runtime error: gobytes: length out of range,这似乎发生在它大于cgo中maxAlloc的值时(ImageMagick使用C代码)。错误来自https://go.dev/src/runtime/string.go第304行。
  • 它将在一段时间后停止调试,并在Vscode中显示消息“进程x已退出,状态为-9”

当我设置断点时,在StoreImage函数中的byteBuf := mim.mw.GetImageBlob()之前一切正常。
我在联想Linux笔记本电脑上有16 GB的内存,我已经把我的交换文件增加到8 GB,但这只帮助我用ImageMagick在CLI中更改格式(转换collage.png测试.ptif),它在应用程序中仍然不起作用。我猜这是内存问题,但16 GB不应该足够用于780 MB的图像吗?有什么建议吗?代码适用于较小的图像。

package main

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "os"

    "gopkg.in/gographics/imagick.v3/imagick"
)

type MyImageMagick struct {
    mw *imagick.MagickWand
}

func (mim *MyImageMagick) convert() {
    f, err := os.Open("collage.png")
    if err != nil {
        log.Fatal(err)
    }
    if err := mim.LoadImage(f); err != nil {
        log.Fatal(err)
    }
    r, err := mim.StoreImage("ptif")
    if err != nil {
        log.Fatal(err)
    }
    t, err := os.Create("testptif")
    if err != nil {
        log.Fatal(err)
    }
    n, err := io.Copy(t, r)
    if err != nil {
        log.Fatal(err)
    }
}
func (mim *MyImageMagick) LoadImage(reader io.Reader) error {
    var buf bytes.Buffer
    if _, err := buf.ReadFrom(reader); err != nil {
        return err
    }
    if err := mim.mw.ReadImageBlob(buf.Bytes()); err != nil {
        return err
    }
    return nil
}
func (mim *MyImageMagick) StoreImage(format string) (io.Reader, error) {
    if err := mim.mw.SetImageFormat(format); err != nil {
        return nil, err
    }
    byteBuf := mim.mw.GetImageBlob()
    return bytes.NewReader(byteBuf), nil
}
func main() {
    imagick.Initialize()
    defer imagick.Terminate()
    mim := &MyImageMagick{mw: imagick.NewMagickWand()}
    mim.convert()
}
jk9hmnmh

jk9hmnmh1#

libvips可以快速完成此类处理,并且使用的内存相对较少。

$ ls -l x.png
-rw-r--r-- 1 john john 995241537 Mar  8 09:01 x.png
$ vipsheader x.png
x.png: 15000x26319 uchar, 3 bands, srgb, pngload
$ /usr/bin/time -f %M:%e vips copy x.png x.tif[pyramid,tile,compression=jpeg]
213820:12.07

因此,一个1gb的PNG文件(15,000 x 26,000像素)在12秒内转换为锥形TIFF,需要210MB内存。
有几个Go语言绑定,但不幸的是,它们似乎都有各种各样的问题。也许你可以直接用vips命令来实现。转换成金字塔形tiff的例子如下:

vips copy input-file output-file.tiff[pyramid,tile,compression=jpeg]

您可以为tiff写入设置各种其他选项:
https://www.libvips.org/API/current/VipsForeignSave.html#vips-tiffsave

相关问题