mirror of https://github.com/perkeep/perkeep.git
Merge branch 'rotate' of github.com:bradfitz/camlistore into rotate
This commit is contained in:
commit
8c9fba0d71
|
@ -41,6 +41,7 @@ type ImageHandler struct {
|
|||
Fetcher blobref.StreamingFetcher
|
||||
Cache blobserver.Storage // optional
|
||||
MaxWidth, MaxHeight int
|
||||
Rotate int // degrees to rotate counter-clockwise: 0, ±90, ±180
|
||||
Square bool
|
||||
sc ScaledImage // optional cache for scaled images
|
||||
}
|
||||
|
@ -143,6 +144,43 @@ func (ih *ImageHandler) scaledCached(buf *bytes.Buffer, file *blobref.BlobRef) (
|
|||
return pieces[1], nil
|
||||
}
|
||||
|
||||
// rotate returns the given image rotated by ih.Rotate degrees if it is
|
||||
// ±90 or ±180, or the source image otherwise.
|
||||
func (ih *ImageHandler) rotate(im image.Image) image.Image {
|
||||
if ih.Rotate == 0 {
|
||||
return im
|
||||
}
|
||||
var rotated *image.NRGBA
|
||||
// trigonometric (i.e counter clock-wise)
|
||||
switch ih.Rotate {
|
||||
case 90:
|
||||
newH, newW := im.Bounds().Dx(), im.Bounds().Dy()
|
||||
rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH))
|
||||
for y := 0; y < newH; y++ {
|
||||
for x := 0; x < newW; x++ {
|
||||
rotated.Set(x, y, im.At(newH-1-y, x))
|
||||
}
|
||||
}
|
||||
case -90:
|
||||
newH, newW := im.Bounds().Dx(), im.Bounds().Dy()
|
||||
rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH))
|
||||
for y := 0; y < newH; y++ {
|
||||
for x := 0; x < newW; x++ {
|
||||
rotated.Set(x, y, im.At(y, newW-1-x))
|
||||
}
|
||||
}
|
||||
case 180, -180:
|
||||
newW, newH := im.Bounds().Dx(), im.Bounds().Dy()
|
||||
rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH))
|
||||
for y := 0; y < newH; y++ {
|
||||
for x := 0; x < newW; x++ {
|
||||
rotated.Set(x, y, im.At(newW-1-x, newH-1-y))
|
||||
}
|
||||
}
|
||||
}
|
||||
return rotated
|
||||
}
|
||||
|
||||
func (ih *ImageHandler) scaleImage(buf *bytes.Buffer, file *blobref.BlobRef) (format string, err error) {
|
||||
mw, mh := ih.MaxWidth, ih.MaxHeight
|
||||
|
||||
|
@ -202,7 +240,7 @@ func (ih *ImageHandler) scaleImage(buf *bytes.Buffer, file *blobref.BlobRef) (fo
|
|||
}
|
||||
|
||||
if !useBytesUnchanged {
|
||||
i = resize.Resize(i, b, mw, mh)
|
||||
i = ih.rotate(resize.Resize(i, b, mw, mh))
|
||||
// Encode as a new image
|
||||
buf.Reset()
|
||||
switch format {
|
||||
|
|
|
@ -309,15 +309,30 @@ func (ui *UIHandler) serveThumbnail(rw http.ResponseWriter, req *http.Request) {
|
|||
query := req.URL.Query()
|
||||
width, err := strconv.Atoi(query.Get("mw"))
|
||||
if err != nil {
|
||||
http.Error(rw, "Invalid specified max width 'mw': "+err.Error(), 500)
|
||||
http.Error(rw, "Invalid specified max width 'mw'", 500)
|
||||
return
|
||||
}
|
||||
height, err := strconv.Atoi(query.Get("mh"))
|
||||
if err != nil {
|
||||
http.Error(rw, "Invalid specified height 'mh': "+err.Error(), 500)
|
||||
http.Error(rw, "Invalid specified height 'mh'", 500)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(mpl): delete this; just temporary assistance before EXIF is done
|
||||
rot := query.Get("rot")
|
||||
rotateAngle := 0
|
||||
if rot != "" {
|
||||
rotateAngle, err = strconv.Atoi(rot)
|
||||
if err != nil {
|
||||
http.Error(rw, "Invalid 'rot' param", 500)
|
||||
return
|
||||
}
|
||||
if rotateAngle%90 != 0 {
|
||||
http.Error(rw, "Invalid rotate angle", 500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
blobref := blobref.Parse(m[1])
|
||||
if blobref == nil {
|
||||
http.Error(rw, "Invalid blobref", 400)
|
||||
|
@ -329,6 +344,7 @@ func (ui *UIHandler) serveThumbnail(rw http.ResponseWriter, req *http.Request) {
|
|||
Cache: ui.Cache,
|
||||
MaxWidth: width,
|
||||
MaxHeight: height,
|
||||
Rotate: rotateAngle,
|
||||
sc: ui.sc,
|
||||
}
|
||||
th.ServeHTTP(rw, req, blobref)
|
||||
|
|
Loading…
Reference in New Issue