From 676d7e2bd9f8149129d9c8a7beb29f69ed3c61b1 Mon Sep 17 00:00:00 2001 From: Andrey Ivanov Date: Thu, 29 Oct 2020 15:16:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B2=D0=B8=D1=81=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82=20=D0=B8=20=D0=B2?= =?UTF-8?q?=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D1=8F=D0=B5=D1=82=20=D1=81=D0=B2?= =?UTF-8?q?=D0=BE=D1=8E=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=8E.=20?= =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=B8=D1=82=D1=8C=20=D0=BC?= =?UTF-8?q?=D0=BE=D0=B6=D0=BD=D0=BE=20=D0=BD=D0=B0=20=D1=84=D0=B0=D0=B9?= =?UTF-8?q?=D0=BB=D0=B5=20project=5Ftest.html?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- previewer/application/handlers.go | 4 +- previewer/application/query.go | 5 +- previewer/converter/converter.go | 77 ++++++++++++++++++------------- project_test.html | 10 ++-- 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/previewer/application/handlers.go b/previewer/application/handlers.go index 455dab7..007c37e 100644 --- a/previewer/application/handlers.go +++ b/previewer/application/handlers.go @@ -24,7 +24,7 @@ func handler(c cache.Cache) http.Handler { writeResponse(w, nil, pic) return } - pic, h, err := q.fromOrigin() + pic, _, err = q.fromOrigin() if err != nil { http.Error(w, "Pic not found in origin", http.StatusNotFound) return @@ -35,7 +35,7 @@ func handler(c cache.Cache) http.Handler { return } c.Set(cache.Key(q.id()), pic) - writeResponse(w, h, pic) + writeResponse(w, nil, pic) }) } diff --git a/previewer/application/query.go b/previewer/application/query.go index aad79a6..4cb3c9a 100644 --- a/previewer/application/query.go +++ b/previewer/application/query.go @@ -11,13 +11,16 @@ import ( ) type Query struct { - Height int Width int + Height int URL *url.URL } func buildQuery(u *url.URL) (q Query, err error) { t := strings.Split(u.Path, "/") + if len(t) < 5 { + return Query{}, errors.New("need more params") + } q.Width, err = strconv.Atoi(t[2]) if err != nil { return Query{}, errors.New("width must be an integer") diff --git a/previewer/converter/converter.go b/previewer/converter/converter.go index 7679092..7fad1bb 100644 --- a/previewer/converter/converter.go +++ b/previewer/converter/converter.go @@ -19,45 +19,56 @@ type Image struct { func SelectType(width int, height int, b []byte) ([]byte, error) { contentType := http.DetectContentType(b) - var decode func(reader *bytes.Reader) (image.Image, error) + var decode func(b []byte) (image.Image, error) var encode func(m image.Image) ([]byte, error) switch contentType { - case "image/png": - decode = func(reader *bytes.Reader) (image.Image, error) { - return png.Decode(bytes.NewReader(b)) + case "image/jpeg": + decode = func(b []byte) (image.Image, error) { + tb := bytes.NewBuffer(b) + return jpeg.Decode(tb) } - encode = func(m image.Image) (res []byte, err error) { - err = png.Encode(bytes.NewBuffer(res), m) - return res, err + encode = func(m image.Image) ([]byte, error) { + res := bytes.NewBuffer([]byte{}) + err := jpeg.Encode(res, m, &jpeg.Options{Quality: 80}) + return res.Bytes(), err + } + case "image/png": + decode = func(b []byte) (image.Image, error) { + tb := bytes.NewBuffer(b) + return png.Decode(tb) + } + encode = func(m image.Image) ([]byte, error) { + res := bytes.NewBuffer([]byte{}) + err := png.Encode(res, m) + return res.Bytes(), err } case "image/gif": - decode = func(reader *bytes.Reader) (image.Image, error) { - return gif.Decode(bytes.NewReader(b)) + decode = func(b []byte) (image.Image, error) { + tb := bytes.NewBuffer(b) + return gif.Decode(tb) } - encode = func(m image.Image) (res []byte, err error) { - err = gif.Encode(bytes.NewBuffer(res), m, nil) - return res, err + encode = func(m image.Image) ([]byte, error) { + res := bytes.NewBuffer([]byte{}) + err := gif.Encode(res, m, nil) + return res.Bytes(), err } default: - decode = func(reader *bytes.Reader) (image.Image, error) { - return jpeg.Decode(bytes.NewReader(b)) + decode = func(b []byte) (image.Image, error) { + return nil, errors.New("unknown format") } - encode = func(m image.Image) (res []byte, err error) { - err = jpeg.Encode(bytes.NewBuffer(res), m, nil) - return res, err + encode = func(m image.Image) ([]byte, error) { + return nil, errors.New("unknown format") } } - i, err := decode(bytes.NewReader(b)) + i, err := decode(b) + if err != nil { + return nil, err + } m := Image{i} - if err != nil { + if err = m.convert(width, height); err != nil { return nil, err } - err = m.convert(width, height) - if err != nil { - return nil, err - } - res, err := encode(m) - return res, err + return encode(m.Image) } func (img *Image) convert(width int, height int) error { @@ -65,20 +76,23 @@ func (img *Image) convert(width int, height int) error { heightOrig := img.Bounds().Max.Y sfOriginal := sizeFactor(widthOrig, heightOrig) sfNew := sizeFactor(width, height) + switch { case sfOriginal > sfNew: // Ресайз по одной высоте и кроп по ширине следом // Определение ширины кропа. - img.resize(int(float64(widthOrig)*sfOriginal), height) - if err := img.crop(image.Point{X: (widthOrig - width) / 2, Y: 0}, image.Point{X: (widthOrig-width)/2 + width, Y: height}); err != nil { + calcWidth := int(float64(height) * sfOriginal) + img.resize(calcWidth, height) + if err := img.crop(image.Point{X: (calcWidth - width) / 2, Y: 0}, image.Point{X: (calcWidth-width)/2 + width, Y: height}); err != nil { return err } case sfOriginal == sfNew: img.resize(width, height) case sfOriginal < sfNew: // Ресайз по одной ширине и кроп по высоте следом - img.resize(width, int(float64(heightOrig)*sfOriginal)) - if err := img.crop(image.Point{X: 0, Y: (heightOrig - height) / 2}, image.Point{X: width, Y: (heightOrig-height)/2 + height}); err != nil { + calcHeight := int(float64(width) / sfOriginal) + img.resize(width, calcHeight) + if err := img.crop(image.Point{X: 0, Y: (calcHeight - height) / 2}, image.Point{X: width, Y: (calcHeight-height)/2 + height}); err != nil { return err } } @@ -96,9 +110,10 @@ func (img *Image) crop(p1 image.Point, p2 image.Point) error { if p1.X < 0 || p1.Y < 0 || p2.X < 0 || p2.Y < 0 { return errors.New("not valid corner points") } - b := image.Rect(0, 0, p2.X, p2.Y) + b := image.Rect(0, 0, p2.X-p1.X, p2.Y-p1.Y) resImg := image.NewRGBA(b) - draw.Draw(resImg, b, img, p1, draw.Src) + draw.Draw(resImg, b, img.Image, p1, draw.Src) + img.Image = resImg return nil } diff --git a/project_test.html b/project_test.html index c90cdca..596c82e 100644 --- a/project_test.html +++ b/project_test.html @@ -3,19 +3,19 @@
- +
- +
- +
- +
- +