diff options
| -rw-r--r-- | convert.go | 54 |
1 files changed, 50 insertions, 4 deletions
@@ -12,10 +12,18 @@ import ( "strings" "golang.org/x/image/bmp" + "golang.org/x/image/draw" "golang.org/x/image/tiff" _ "golang.org/x/image/webp" ) +var ( + x = flag.Int("x", 0, "new image width") + y = flag.Int("y", 0, "new image height") + stretch = flag.Bool("stretch", false, "if resizing, whether to stretch the image rather than cropping (the default)") + format = flag.String("format", "", "output image format, default is to use the file extension") +) + func load(filename string) (image.Image, error) { file := os.Stdin if filename != "-" { @@ -35,6 +43,37 @@ func load(filename string) (image.Image, error) { return img, nil } +func divRound(n, d int) int { + return (n + d/2) / d +} + +func resize(img image.Image) image.Image { + x, y := *x, *y + if x == 0 { + x = divRound(y*img.Bounds().Dx(), img.Bounds().Dy()) + } + if y == 0 { + y = divRound(x*img.Bounds().Dy(), img.Bounds().Dx()) + } + output := image.NewRGBA64(image.Rect(0, 0, x, y)) + srcRect := img.Bounds() + if !*stretch { + if img.Bounds().Dx()*y >= img.Bounds().Dy()*x { + scaledX := divRound(img.Bounds().Dy()*x, y) + xOffset := (img.Bounds().Dx() - scaledX) / 2 + srcRect.Min.X += xOffset + srcRect.Max.X = srcRect.Min.X + scaledX + } else { + scaledY := divRound(img.Bounds().Dx()*y, x) + yOffset := (img.Bounds().Dy() - scaledY) / 2 + srcRect.Min.Y += yOffset + srcRect.Max.Y = srcRect.Min.Y + scaledY + } + } + draw.CatmullRom.Scale(output, output.Bounds(), img, srcRect, draw.Src, nil) + return output +} + func run() error { args := flag.Args() if len(args) != 2 { @@ -42,11 +81,14 @@ func run() error { } inputFileName, outputFileName := args[0], args[1] - n := strings.LastIndex(outputFileName, ".") - if n < 0 { - return errors.New("unknown output file extension") + ext := *format + if ext == "" { + n := strings.LastIndex(outputFileName, ".") + if n < 0 { + return errors.New("unknown output file extension") + } + ext = outputFileName[n+1:] } - ext := outputFileName[n+1:] switch ext { case "gif", "jpeg", "jpg", "png", "bmp", "tiff": default: @@ -58,6 +100,10 @@ func run() error { return err } + if *x != 0 || *y != 0 { + input = resize(input) + } + outputFile, err := os.Create(outputFileName) if err != nil { return err |
