Prevent resize from doing things multiple times if #CPUs > width

This commit is contained in:
jst 2012-08-23 19:36:02 +02:00
parent 5389d2694d
commit 294efa80bb
2 changed files with 21 additions and 12 deletions

View File

@ -61,7 +61,7 @@ func main() {
file.Close() file.Close()
// resize to width 1000 using Lanczos resampling // resize to width 1000 using Lanczos resampling
// and preserve aspect ration // and preserve aspect ratio
m := resize.Resize(1000, 0, img, resize.Lanczos3) m := resize.Resize(1000, 0, img, resize.Lanczos3)
out, err := os.Create("test_resized.jpg") out, err := os.Create("test_resized.jpg")

View File

@ -21,7 +21,7 @@ THIS SOFTWARE.
// utilized in the computations. // utilized in the computations.
// //
// Example: // Example:
// imgResized := resize.Resize(1000, -1, imgOld, Lanczos3) // imgResized := resize.Resize(1000, 0, imgOld, Lanczos3)
package resize package resize
import ( import (
@ -70,9 +70,9 @@ func calcFactors(width, height uint, oldWidth, oldHeight float32) (scaleX, scale
// an image // an image
type InterpolationFunction func(float32, float32, image.Image) color.RGBA64 type InterpolationFunction func(float32, float32, image.Image) color.RGBA64
// Resize an image to new width w and height h using the interpolation function interp. // Resize an image to new width and height using the interpolation function interp.
// A new image with the given dimensions will be returned. // A new image with the given dimensions will be returned.
// If one of the parameters w or h is set to 0, its size will be calculated so that // If one of the parameters width or height is set to 0, its size will be calculated so that
// the aspect ratio is that of the originating image. // the aspect ratio is that of the originating image.
// The resizing algorithm uses channels for parallel computation. // The resizing algorithm uses channels for parallel computation.
func Resize(width, height uint, img image.Image, interp InterpolationFunction) image.Image { func Resize(width, height uint, img image.Image, interp InterpolationFunction) image.Image {
@ -83,26 +83,35 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
scaleX, scaleY := calcFactors(width, height, oldWidth, oldHeight) scaleX, scaleY := calcFactors(width, height, oldWidth, oldHeight)
t := Trans2{scaleX, 0, float32(oldBounds.Min.X), 0, scaleY, float32(oldBounds.Min.Y)} t := Trans2{scaleX, 0, float32(oldBounds.Min.X), 0, scaleY, float32(oldBounds.Min.Y)}
m := image.NewRGBA64(image.Rect(0, 0, int(oldWidth/scaleX), int(oldHeight/scaleY))) resizedImg := image.NewRGBA64(image.Rect(0, 0, int(oldWidth/scaleX), int(oldHeight/scaleY)))
b := m.Bounds() b := resizedImg.Bounds()
// prevent resize from doing too much work
// if #CPUs > width
n := 1
if (NCPU < b.Dy()) {
n = NCPU
} else {
n = b.Dy()
}
c := make(chan int, NCPU) c := make(chan int, n)
for i := 0; i < NCPU; i++ { for i := 0; i < n; i++ {
go func(b image.Rectangle, c chan int) { go func(b image.Rectangle, c chan int) {
var u, v float32 var u, v float32
for y := b.Min.Y; y < b.Max.Y; y++ { for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ { for x := b.Min.X; x < b.Max.X; x++ {
u, v = t.Eval(float32(x), float32(y)) u, v = t.Eval(float32(x), float32(y))
m.SetRGBA64(x, y, interp(u, v, img)) resizedImg.SetRGBA64(x, y, interp(u, v, img))
} }
} }
c <- 1 c <- 1
}(image.Rect(b.Min.X, b.Min.Y+i*(b.Dy())/NCPU, b.Max.X, b.Min.Y+(i+1)*(b.Dy())/NCPU), c) }(image.Rect(b.Min.X, b.Min.Y+i*(b.Dy())/n, b.Max.X, b.Min.Y+(i+1)*(b.Dy())/n), c)
} }
for i := 0; i < NCPU; i++ { for i := 0; i < n; i++ {
<-c <-c
} }
return m return resizedImg
} }