Сервис работает и выполняет свою функцию. Проверить можно на файле project_test.html

master
Andrey Ivanov 2020-10-29 15:16:35 +03:00 committed by Andrey Ivanov
parent f9535562d4
commit 676d7e2bd9
4 changed files with 57 additions and 39 deletions

View File

@ -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)
})
}

View File

@ -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")

View File

@ -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
}

View File

@ -3,19 +3,19 @@
</head>
<body>
<div>
<img src="http://localhost/20/40/tiburon.su/img/portfolio/big/011.jpg">
<img src="http://localhost/200/400/tiburon.su/img/portfolio/big/011.jpg">
</div>
<div>
<img src="http://localhost/fill/20/40/tiburon.su/img/portfolio/big/011.jpg">
<img src="http://localhost/fill/200/400/tiburon.su/img/portfolio/big/011.jpg">
</div>
<div>
<img src="http://localhost/fill/40/20/tiburon.su/img/portfolio/big/011.jpg">
<img src="http://localhost/fill/400/200/tiburon.su/img/portfolio/big/011.jpg">
</div>
<div>
<img src="http://localhost/fill/1200/1300/tiburon.su/img/portfolio/big/011.jpg">
<img src="http://localhost/fill/1200/1400/tiburon.su/img/portfolio/big/011.jpg">
</div>
<div>
<img src="http://localhost/fill/100/100/tiburon.su/img/portfolio/big/011.jpg">
<img src="http://localhost/fill/400/400/tiburon.su/img/portfolio/big/011.jpg">
</div>
</body>
</html>