gpt4 book ai didi

image-processing - 如何在 Go 中快速缩放和锐化图像?

转载 作者:IT王子 更新时间:2023-10-29 00:38:13 26 4
gpt4 key购买 nike

我目前正在将一个非常基本的画廊应用程序从 PHP 移植到 Go。此应用程序具有自动生成每张图像的缩略图和中等尺寸版本的功能。

在 PHP 中,我使用 GD,因为它随附并且工作得很好。 (代码在问题的末尾)。我想我可以在 Go 中复制它并从 https://github.com/bolknote/go-gd 中找到 go-gd (同样,代码在最后)。它可以工作,但大约慢 10 倍(使用 time wget $URL 测量)。 PHP 实现从 10 MP 图像生成 1024x768 版本大约需要 1 秒,而 Go 代码需要将近 10 秒。

有没有什么方法可以加快它的速度,或者有什么其他的 Go 图像处理库可以在相当快的情况下实现缩放和卷积?

PHP 代码

public function saveThumb($outName, $options) {
$this->img = imagecreatefromjpeg($filename);
if (!is_dir(dirname($outName))) {
mkdir(dirname($outName), 0777, true);
}

$width = imagesx($this->img);
$height = imagesy($this->img);

if ($options["keep_aspect"]) {
$factor = min($options["size_x"]/$width, $options["size_y"]/$height);
$new_width = round($factor*$width);
$new_height = round($factor*$height);
} else {
$new_width = $options["size_x"];
$new_height = $options["size_y"];
}

// create a new temporary image
$tmp_img = imagecreatetruecolor($new_width, $new_height);

// copy and resize old image into new image
imagecopyresampled($tmp_img, $this->img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

if ($options["sharpen"]) {
// define the sharpen matrix
$sharpen = array(
array(-1, -1.7, -1),
array(-1.7, 20, -1.7),
array(-1, -1.7, -1)
);

// calculate the sharpen divisor
$divisor = array_sum(array_map('array_sum', $sharpen));

// apply the matrix
imageconvolution($tmp_img, $sharpen, $divisor, 0);
}

// save thumbnail into a file
imagejpeg($tmp_img, $outName);
}

Go 代码

func (entry *entry) GenerateThumb(options ImageType, overwrite bool) os.Error {
targetFilename := entry.Filename(imageType)
sourceFilename := entry.Filename(IMAGE_TYPE_FULL)
targetDirname, _ := filepath.Split(targetFilename)
os.MkdirAll(targetDirname, 0777)

targetFi, errT := os.Stat(targetFilename)
sourceFi, errS := os.Stat(sourceFilename)

image := gd.CreateFromJpeg(sourceFilename)
if image == nil {
return os.NewError("Image could not be loaded")
}

var targetX, targetY int = 0, 0

if options.KeepAspect {
factor := math.Fmin(float64(options.SizeX)/float64(image.Sx()), float64(options.SizeY)/float64(image.Sy()))
targetX = int(factor*float64(image.Sx()))
targetY = int(factor*float64(image.Sy()))
} else {
targetX = options.SizeX
targetY = options.SizeY
}
tmpImage := gd.CreateTrueColor(targetX, targetY)
image.CopyResampled(tmpImage, 0, 0, 0, 0, tmpImage.Sx(), tmpImage.Sy(), image.Sx(), image.Sy())

if options.Sharpen {
sharpenMatrix := [3][3]float32{
{-1, -1.7, -1},
{-1.7, 20, -1.7},
{-1, -1.7, -1} }
tmpImage.Convolution(sharpenMatrix, 9.2, 0)
}
tmpImage.Jpeg(targetFilename, 90)

return nil
}

编辑:使用 resize.go 进行 Go 代码(参见答案)

func (entry *entry) GenerateThumb(options ImageType, overwrite bool) os.Error {
targetFilename := entry.Filename(imageType)
sourceFilename := entry.Filename(IMAGE_TYPE_FULL)
targetDirname, _ := filepath.Split(targetFilename)
os.MkdirAll(targetDirname, 0777)

targetFi, errT := os.Stat(targetFilename)
sourceFi, errS := os.Stat(sourceFilename)

if errT == nil && errS == nil {
if targetFi.Mtime_ns > sourceFi.Mtime_ns && !overwrite {
// already up-to-date, nothing to do
return nil
}
}

log.Printf("Generate(\"%v\", %v)\n", imageType, overwrite)

inFile, fErr := os.Open(sourceFilename)
if fErr != nil {
log.Fatal(fErr)
}
defer inFile.Close()

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

var targetX, targetY int
if options.KeepAspect {
factor := math.Fmin(float64(options.SizeX)/float64(img.Bounds().Max.X), float64(options.SizeY)/float64(img.Bounds().Max.Y))
targetX = int(factor*float64(img.Bounds().Max.X))
targetY = int(factor*float64(img.Bounds().Max.Y))
} else {
targetX = curType.SizeX
targetY = curType.SizeY
}
newImg := resize.Resample(img, image.Rect(0, 0, img.Bounds().Max.X, img.Bounds().Max.Y), targetX, targetY)

var outFile *os.File
outFile, fErr = os.Create(targetFilename)
if fErr != nil {
log.Fatal(fErr)
}
defer outFile.Close()

err = jpeg.Encode(outFile, newImg, &jpeg.Options{90})
if err != nil {
log.Fatal(err)
}
return nil
}

最佳答案

你应该看看这个调整大小的库:github.com/nfnt/resize .它有6个不错的插值函数可供选择。

关于image-processing - 如何在 Go 中快速缩放和锐化图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7309355/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com