Mercurial > mercurial > hgweb_golang.cgi
view src/IMGmanip.go @ 47:169936fed61b
small changes.
author | pyon@macmini |
---|---|
date | Tue, 21 Apr 2020 22:43:55 +0900 |
parents | 9072560fc0f2 |
children |
line wrap: on
line source
/* Image Manipulator - ver 0.3 ( Last Change: 2016-10-27 Thu 20:38:25.) */ package main import( "errors" "flag" "fmt" "image" "image/jpeg" "image/png" "io" "os" "strings" "strconv" ) func main() { ver := "0.3" // arguments kind := flag.String( "t", "", "file type : jpeg / png" ) resize := flag.String( "s", "", "new size : 600x800 / 320x0 / ..." ) crop := flag.String( "c", "", "crop size : 300x200+10+35" ) angle := flag.Uint( "r", 0, "rotate : 90 / 180 / 270" ) dump := flag.Bool( "d", false, "dump RGBA : [no argument]") flag.Parse() if flag.NFlag() == 0 { fmt.Fprintf( os.Stderr, "\n=== Image-Manipulator - version %s ===", ver ) fmt.Fprintf( os.Stderr, "\n$ imgmanip [option parameter] < infile > outfile\n" ) flag.PrintDefaults() os.Exit( 1 ) } switch { // convert case *kind != "" : err := Convert( os.Stdin, os.Stdout, *kind ); if err != nil { fmt.Fprintf( os.Stderr, "%s: %v\n", *kind, err ) os.Exit( 1 ) } // resize case *resize != "" : err := Resize( os.Stdin, os.Stdout, *resize ); if err != nil { fmt.Fprintf( os.Stderr, "resize: %v\n", err ) os.Exit( 1 ) } // crop case *crop != "" : err := Crop( os.Stdin, os.Stdout, *crop ); if err != nil { fmt.Fprintf( os.Stderr, "crop: %v\n", err ) os.Exit( 1 ) } // rotate case *angle != 0 : err := Rotate( os.Stdin, os.Stdout, *angle ); if err != nil { fmt.Fprintf( os.Stderr, "rotate: %v\n", err ) os.Exit( 1 ) } // dump case *dump : err := Dump( os.Stdin ); if err != nil { fmt.Fprintf( os.Stderr, "dump: %v\n", err ) os.Exit( 1 ) } } } func Convert( in io.Reader, out io.Writer, kind string ) error { img, _, err := image.Decode( in ); if err != nil { return err } switch kind { case "jpeg": return jpeg.Encode( out, img, &jpeg.Options{ Quality: 100 } ) case "png": return png.Encode( out, img ) } return errors.New( "image-type is not supported") } func Resize( in io.Reader, out io.Writer, size string ) error { img, kind, err := image.Decode( in ); if err != nil { return err } srcW := img.Bounds().Max.X srcH := img.Bounds().Max.Y wh := strings.Split( size, "x" ) w, err := strconv.Atoi( wh[0] ); if err != nil || w < 0 { return errors.New( "invalid width" ) } h, err := strconv.Atoi( wh[1] ); if err != nil || h < 0 { return errors.New( "invalid height" ) } if w == 0 && h == 0 { return errors.New( "invalid size" ) } if w == 0 { w = h * srcW / srcH } if h == 0 { h = w * srcH / srcW } dst := image.NewNRGBA( image.Rect( 0, 0, w, h ) ) for x := 0; x < w; x++ { for y := 0; y < h; y++ { dst.Set( x, y, img.At( x * srcW / w, y * srcH / h ) ) } } switch kind { case "jpeg": return jpeg.Encode( out, dst, &jpeg.Options{ Quality: 100 } ) case "png": return png.Encode( out, dst ) } return errors.New( "image-type is not supported") } func Crop( in io.Reader, out io.Writer, geo string ) error { img, kind, err := image.Decode( in ); if err != nil { return err } srcW := img.Bounds().Max.X srcH := img.Bounds().Max.Y buf := strings.Split( geo, "x" ) w, err := strconv.Atoi( buf[0] ); if err != nil || w < 0 || w > srcW { return errors.New( "invalid width" ) } buf = strings.Split( buf[1], "+" ) h, err := strconv.Atoi( buf[0] ); if err != nil || h < 0 || h > srcH { return errors.New( "invalid height" ) } x0, err := strconv.Atoi( buf[1] ); if err != nil || x0 < 0 { return errors.New( "invalid x" ) } y0, err := strconv.Atoi( buf[2] ); if err != nil || y0 < 0 { return errors.New( "invalid y" ) } var dst *image.NRGBA dst = image.NewNRGBA( image.Rect( 0, 0, w, h ) ) for x := 0; x < x0 + w; x++ { for y := 0; y < y0 + h; y++ { dst.Set( x, y, img.At( x0 + x, y0 + y ) ) } } switch kind { case "jpeg": return jpeg.Encode( out, dst, &jpeg.Options{ Quality: 100 } ) case "png": return png.Encode( out, dst ) } return errors.New( "image-type is not supported") } func Rotate( in io.Reader, out io.Writer, angle uint ) error { img, kind, err := image.Decode( in ); if err != nil { return err } srcW := img.Bounds().Max.X srcH := img.Bounds().Max.Y var dst *image.NRGBA switch angle { case 90: dst = image.NewNRGBA( image.Rect( 0, 0, srcH, srcW ) ) for x := 0; x < srcH; x++ { for y := 0; y < srcW; y++ { dst.Set( x, y, img.At( y, srcH - x ) ) } } case 180: dst = image.NewNRGBA( image.Rect( 0, 0, srcW, srcH ) ) for x := 0; x < srcW; x++ { for y := 0; y < srcH; y++ { dst.Set( x, y, img.At( srcW - x, srcH - y ) ) } } case 270: dst = image.NewNRGBA( image.Rect( 0, 0, srcH, srcW ) ) for x := 0; x < srcH; x++ { for y := 0; y < srcW; y++ { dst.Set( x, y, img.At( y, x ) ) } } default: return errors.New( "bad angle" ) } switch kind { case "jpeg": return jpeg.Encode( out, dst, &jpeg.Options{ Quality: 100 } ) case "png": return png.Encode( out, dst ) } return errors.New( "image-type is not supported") } func Dump( in io.Reader ) error { img, _, err := image.Decode( in ); if err != nil { return err } bounds := img.Bounds() for y:= bounds.Min.Y; y < bounds.Max.Y; y++ { for x:= bounds.Min.X; x < bounds.Max.X; x++ { r, g, b, a := img.At( x, y ).RGBA() fmt.Printf( "(%d,%d) = %d,%d,%d,%d\n", x, y, r>>8, g>>8, b>>8, a>>8 ) } } return nil }