Exemple #1
0
// Resize given image file & write it to io.Writer
func resize(w io.Writer, r io.Reader, size []int) error {
	img, mimetype, err := image.Decode(r)
	if size == nil || err != nil {
		io.Copy(w, r)
		return nil
	}

	ib := img.Bounds()

	size = fitToActualSize(&img, size)
	x := size[0]
	y := size[1]

	// set optimal thumbnail size
	wrat := float64(x) / float64(ib.Dx())
	hrat := float64(y) / float64(ib.Dy())
	if wrat <= hrat {
		y = int(wrat * float64(ib.Dy()))
	} else {
		x = int(hrat * float64(ib.Dx()))
	}

	dst := image.NewRGBA(image.Rect(0, 0, x, y))
	graphics.Thumbnail(dst, img)

	return writeByMimetype(w, dst, mimetype)
}
Exemple #2
0
func (c Creature) CropImage(width, height, max int, ctx appengine.Context) (image.Image, error) {
	url, _ := aeimg.ServingURL(ctx, c.BlobKey, &aeimg.ServingURLOptions{Size: max, Crop: true})

	client := urlfetch.Client(ctx)
	resp, _ := client.Get(url.String())

	// Just in case
	if resp.StatusCode != 200 {
		return nil, errors.New("Blob not found")
	}

	// Do we need further cropping?
	if width == height {
		return jpeg.Decode(resp.Body)
	}

	src, err := jpeg.Decode(resp.Body)
	dest := image.NewRGBA(image.Rect(0, 0, width, height))
	if err != nil {
		return nil, err
	}

	graphics.Thumbnail(dest, src)

	return dest, nil
}
Exemple #3
0
// Crop given image file & write it to io.Writer
func crop(w io.Writer, r io.Reader, size []int) error {
	img, mimetype, err := image.Decode(r)
	if size == nil || err != nil {
		io.Copy(w, r)
		return nil
	}

	size = setMaxSize(fitToActualSize(&img, size))
	dst := image.NewRGBA(image.Rect(0, 0, size[0], size[1]))
	graphics.Thumbnail(dst, img)

	return writeByMimetype(w, dst, mimetype)
}
Exemple #4
0
func (processor LocalImageProcessor) Process(src multipart.File, contentType string) (string, error) {

	filename := generateRandomFilename(contentType)

	if err := os.MkdirAll(settings.UploadsDir, 0777); err != nil && !os.IsExist(err) {
		return filename, err
	}

	if err := os.MkdirAll(settings.ThumbnailsDir, 0777); err != nil && !os.IsExist(err) {
		return filename, err
	}

	// make thumbnail
	var (
		img image.Image
		err error
	)

	if contentType == "image/png" {
		img, err = png.Decode(src)
	} else {
		img, err = jpeg.Decode(src)
	}

	if err != nil {
		return filename, err
	}

	thumb := image.NewRGBA(image.Rect(0, 0, 300, 300))
	graphics.Thumbnail(thumb, img)

	dst, err := os.Create(path.Join(settings.ThumbnailsDir, filename))

	if err != nil {
		return filename, err
	}

	defer dst.Close()

	if contentType == "image/png" {
		png.Encode(dst, thumb)
	} else if contentType == "image/jpeg" {
		jpeg.Encode(dst, thumb, nil)
	}

	src.Seek(0, 0)

	dst, err = os.Create(path.Join(settings.UploadsDir, filename))

	if err != nil {
		return filename, err
	}

	defer dst.Close()

	_, err = io.Copy(dst, src)
	if err != nil {
		return filename, err
	}

	return filename, nil

}
func GetImages(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/images/" {
		ListFolder()

		jsonData, err := json.MarshalIndent(files, "", "    ")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		if len(files) == 0 {
			w.Write([]byte("[]"))
		} else {
			w.Write(jsonData)
		}
	} else {
		filename := filepath.FromSlash(r.URL.Path[1:])

		absFilename, err := filepath.Abs(filename)
		if err != nil {
			fmt.Printf("Error: %s\n", err.Error())
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		wd, _ := os.Getwd()
		if !strings.HasPrefix(absFilename, wd) {
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		if r.Method == "GET" {
			width, err1 := strconv.Atoi(r.URL.Query().Get("width"))
			height, err2 := strconv.Atoi(r.URL.Query().Get("height"))

			var x, y int
			if x, err = strconv.Atoi(r.URL.Query().Get("x")); err != nil {
				x = -1
			}
			if y, err = strconv.Atoi(r.URL.Query().Get("y")); err != nil {
				y = -1
			}

			if err1 == nil && err2 == nil && width > 0 && height > 0 {
				ext := filepath.Ext(filename)
				resizedFilename := strings.TrimRight(filepath.Base(filename), ext)
				resizedFilename += "_" + strconv.Itoa(width)
				resizedFilename += "_" + strconv.Itoa(height)
				resizedFilename += "_" + strconv.Itoa(x)
				resizedFilename += "_" + strconv.Itoa(y)
				resizedFilename += ext

				resizedFilename = filepath.Join(*cache, resizedFilename)

				if _, err := os.Stat(resizedFilename); os.IsNotExist(err) {
					fSrc, err := os.Open(filename)
					if err != nil {
						fmt.Printf("Error: %s\n", err.Error())
						http.Error(w, err.Error(), http.StatusInternalServerError)
						return
					}
					defer fSrc.Close()

					src, _, err := image.Decode(fSrc)
					if err != nil {
						fmt.Printf("Error: %s\n", err.Error())
						http.Error(w, err.Error(), http.StatusInternalServerError)
						return
					}

					if !(src.Bounds().Max.X == width && src.Bounds().Max.Y == height) || x > -1 || y > -1 {

						var dst draw.Image
						if x > -1 || y > -1 {
							if x < 0 {
								x = 0
							}
							if y < 0 {
								y = 0
							}
							dst = image.NewRGBA(image.Rect(0, 0, src.Bounds().Max.X-x, src.Bounds().Max.Y-y))
							draw.Draw(dst, dst.Bounds(), src, image.Point{x, y}, draw.Src)
						} else {
							dst = image.NewRGBA(image.Rect(0, 0, width, height))
							graphics.Thumbnail(dst, src)
						}

						fDst, err := os.Create(resizedFilename)
						if err != nil {
							fmt.Printf("Error: %s\n", err.Error())
							http.Error(w, err.Error(), http.StatusInternalServerError)
							return
						}
						defer fDst.Close()

						if ext == ".png" {
							png.Encode(fDst, dst)
						} else {
							jpeg.Encode(fDst, dst, &jpeg.Options{95})
						}
						filename = resizedFilename
					}
				} else {
					filename = resizedFilename
				}
			}

			http.ServeFile(w, r, filename)

			fmt.Printf("Serving image %s\n", filename)

		} else if r.Method == "DELETE" {
			if err := os.Remove(filename); err != nil {
				fmt.Printf("Error: %s\n", err.Error())
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			removeCached(filename)

			fmt.Printf("Removed %s\n", filename)

			w.WriteHeader(http.StatusNoContent)
		}
	}
}
Exemple #6
0
// 根据需求实时获取缩略图片
// way string 缩略图生成方式:
//      'auto': 原图全显优先,获取width或height最大,原图不会被截断
//      'full': 图片填充优先,将widthd和height,按照比例全部填充, 原图将会被截断
//
func Thumb(way string, width uint, height uint, picturePath string) (*os.File, error) {
	/* 获取配置文件中上传根路径 */
	revel.Config.SetSection(revel.RunMode)
	uploadRoot, _ := revel.Config.String("uploadpath")

	ext := filepath.Ext(picturePath)

	/* 检测是否是获取一个远端url图片的缩率图 */
	picUrl, err := url.ParseRequestURI(picturePath)
	isRemotePic := false
	//if err == nil && picUrl.Scheme == "http" && (picUrl.Host == "img.show.wepiao.com" || picUrl.Host == "img.wxmovie.com" || picUrl.Host == "static.show.wepiao.com" || picUrl.Host == "static.task.18.tl:86") {
	if err == nil && picUrl.Scheme == "http" {
		isRemotePic = true
		uploadRoot += "/upload"
		savePath, saveName := HelperForFilePathCreator(uploadRoot, picturePath, false)
		picturePath = savePath + "/" + saveName + ext
	}

	if way != "full" {
		way = "auto"
	}

	fname := uploadRoot + "/" + picturePath
	thumbFile := fmt.Sprintf("%s_%s_%v_%v%v", fname, way, width, height, ext)

	/* 检查有没有现成的缩略图 */
	_, err = os.Stat(thumbFile)
	if err == nil { // 如果有,直接读出
		thumb, _ := os.Open(thumbFile)
		return thumb, nil
	}
	// fmt.Printf("没有现成缩率图\n")

	/* 没有现成的缩略图,需要实施生成, 查找原图片文件是否存在 */
	finfo, err := os.Stat(fname)
	if err != nil {
		// 如果是获取远端图片,那就先获取.
		if isRemotePic {
			// fmt.Printf("是远端图片\n")

			client := http.Client{}
			reqImg, err := client.Get(picUrl.Scheme + "://" + picUrl.Host + picUrl.Path)
			defer reqImg.Body.Close()
			if err != nil {
				return nil, err
			}
			//如果是4开头的错误状态 则生成默认图片
			if '4' == reqImg.Status[0] {
				fname = "/opt/www/static/pc/img/logo.png"
				way = "auto"
			} else {
				out, err := os.Create(fname)
				if err != nil {
					return nil, err
				}
				defer out.Close()
				io.Copy(out, reqImg.Body)
			}
			finfo, err = os.Stat(fname)
			// fmt.Printf("存储远端图片到: %#v\n", fname)
		} else if os.IsNotExist(err) || err.(*os.PathError).Err == syscall.ENOTDIR {
			return nil, errors.New("20108")
		} else {
			return nil, err
		}
	}
	if finfo.Mode().IsDir() {
		return nil, errors.New("10016")
	}

	file, err := os.Open(fname)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, errors.New("20108")
		}
		return nil, err
	}
	defer file.Close()

	/* 生成缩略图 */
	var img image.Image
	img, _, err = image.Decode(file)

	if err != nil {
		return nil, err
	}

	// 产生缩略图,等比例缩放
	out, errF := os.Create(thumbFile)
	if errF != nil {
		return nil, errors.New("20108")
	}
	defer out.Close()

	var m image.Image
	// fmt.Printf("生成缩率图\n")

	origBounds := img.Bounds()
	origWidth := uint(origBounds.Dx())
	origHeight := uint(origBounds.Dy())
	if way == "full" {
		dst := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
		graphics.Thumbnail(dst, img)
		m = dst
	} else if width >= origWidth && height >= origHeight {
		bg := imaging.New(int(width), int(height), color.NRGBA{255, 255, 255, 255})
		m = imaging.PasteCenter(bg, img)
	} else {
		m = resize.Thumbnail(width, height, img, resize.Lanczos3)
	}

	/* 生成文件 */
	err = jpeg.Encode(out, m, &jpeg.Options{90})
	if err != nil {
		err = png.Encode(out, m)
	}
	if err != nil {
		err = gif.Encode(out, m, nil)
	}
	if err != nil {
		return nil, err
	}

	/* 这里不知道如何将 image.Image类型转换为 io.Writer类型,
	   所以只有暂时在保存后,又重新读了次文件 */
	thumb, _ := os.Open(thumbFile)

	return thumb, nil
}
Exemple #7
0
func (f *defaultFileStorage) store(src readable, filename, contentType string) error {
	if err := os.MkdirAll(f.uploadsDir, 0777); err != nil && !os.IsExist(err) {
		return errgo.Mask(err)
	}

	if err := os.MkdirAll(f.thumbnailsDir, 0777); err != nil && !os.IsExist(err) {
		return errgo.Mask(err)
	}

	// make thumbnail
	var (
		img image.Image
		err error
	)

	switch contentType {
	case "image/png":
		img, err = png.Decode(src)
		break
	case "image/jpeg":
		img, err = jpeg.Decode(src)
		break
	case "image/jpg":
		img, err = jpeg.Decode(src)
		break
	case "image/gif":
		img, err = gif.Decode(src)
		break
	default:
		return errors.New("invalid content type:" + contentType)
	}

	if err != nil {
		return errgo.Mask(err)
	}

	thumb := image.NewRGBA(image.Rect(0, 0, thumbnailWidth, thumbnailHeight))
	graphics.Thumbnail(thumb, img)

	dst, err := os.Create(path.Join(f.thumbnailsDir, filename))
	if err != nil {
		return errgo.Mask(err)
	}

	g := gift.New(gift.Contrast(-30))
	g.Draw(thumb, thumb)

	if err != nil {
		return errgo.Mask(err)
	}

	defer dst.Close()

	switch contentType {
	case "image/png":
		err = png.Encode(dst, thumb)
		break
	case "image/jpeg":
		err = jpeg.Encode(dst, thumb, nil)
		break
	case "image/jpg":
		err = jpeg.Encode(dst, thumb, nil)
		break
	case "image/gif":
		err = gif.Encode(dst, thumb, nil)
	}

	if err != nil {
		return errgo.Mask(err)
	}

	src.Seek(0, 0)

	dst, err = os.Create(path.Join(f.uploadsDir, filename))

	if err != nil {
		return errgo.Mask(err)
	}

	defer dst.Close()

	_, err = io.Copy(dst, src)
	if err != nil {
		return errgo.Mask(err)
	}

	return nil

}
Exemple #8
0
func MakeThumbnail(src image.Image, x int, y int) (image.Image, error) {
	tgt := image.NewRGBA(image.Rect(0, 0, x, y))
	err := graphics.Thumbnail(tgt, src)
	return tgt, err
}
Exemple #9
0
func (c Application) PostUpload(name string) rev.Result {
	c.Validation.Required(name)

	if c.Validation.HasErrors() {
		c.FlashParams()
		c.Validation.Keep()
		return c.Redirect(Application.Upload)
	}

	photoDir := path.Join(PHOTO_DIRECTORY, name)
	thumbDir := path.Join(PHOTO_DIRECTORY, "thumbs", name)
	err := os.MkdirAll(photoDir, 0777)
	if err != nil {
		c.FlashParams()
		c.Flash.Error("Error making directory:", err)
		return c.Redirect(Application.Upload)
	}
	err = os.MkdirAll(thumbDir, 0777)
	if err != nil {
		c.FlashParams()
		c.Flash.Error("Error making directory:", err)
		return c.Redirect(Application.Upload)
	}

	photos := c.Params.Files["photos[]"]
	for _, photoFileHeader := range photos {
		// Open the photo.
		input, err := photoFileHeader.Open()
		if err != nil {
			c.FlashParams()
			c.Flash.Error("Error opening photo:", err)
			return c.Redirect(Application.Upload)
		}

		photoBytes, err := ioutil.ReadAll(input)
		if err != nil || len(photoBytes) == 0 {
			rev.ERROR.Println("Failed to read image:", err)
			continue
		}
		input.Close()

		// Decode the photo.
		photoImage, format, err := image.Decode(bytes.NewReader(photoBytes))
		if err != nil {
			rev.ERROR.Println("Failed to decode image:", err)
			continue
		}

		// Decode the EXIF data
		x, err := exif.Decode(bytes.NewReader(photoBytes))
		if err != nil {
			rev.ERROR.Println("Failed to decode image exif:", err)
			continue
		}

		var orientation int = 1
		if orientationTag, err := x.Get(exif.Orientation); err == nil {
			orientation = int(orientationTag.Int(0))
		}

		photoName := path.Base(photoFileHeader.Filename)

		// Create a thumbnail
		thumbnail := image.NewRGBA(image.Rect(0, 0, 256, 256))
		err = graphics.Thumbnail(thumbnail, photoImage)
		if err != nil {
			rev.ERROR.Println("Failed to create thumbnail:", err)
			continue
		}

		// If the EXIF said to, rotate the thumbnail.
		// TODO: maintain the EXIF in the thumb instead.
		if orientation != 1 {
			if angleRadians, ok := ORIENTATION_ANGLES[orientation]; ok {
				rotatedThumbnail := image.NewRGBA(image.Rect(0, 0, 256, 256))
				err = graphics.Rotate(rotatedThumbnail, thumbnail, &graphics.RotateOptions{Angle: angleRadians})
				if err != nil {
					rev.ERROR.Println("Failed to rotate:", err)
				} else {
					thumbnail = rotatedThumbnail
				}
			}
		}

		thumbnailFile, err := os.Create(path.Join(thumbDir, photoName))
		if err != nil {
			c.FlashParams()
			c.Flash.Error("Error creating file:", err)
			return c.Redirect(Application.Upload)
		}

		err = jpeg.Encode(thumbnailFile, thumbnail, nil)
		if err != nil {
			c.FlashParams()
			c.Flash.Error("Failed to save thumbnail:", err)
			return c.Redirect(Application.Upload)
		}

		// Save the photo
		output, err := os.Create(path.Join(photoDir, photoName))
		if err != nil {
			c.FlashParams()
			c.Flash.Error("Error creating file:", err)
			return c.Redirect(Application.Upload)
		}

		_, err = io.Copy(output, bytes.NewReader(photoBytes))
		output.Close()
		if err != nil {
			c.FlashParams()
			c.Flash.Error("Error writing photo:", err)
			return c.Redirect(Application.Upload)
		}

		var taken time.Time
		if takenTag, err := x.Get("DateTimeOriginal"); err == nil {
			taken, err = time.Parse("2006:01:02 15:04:05", takenTag.StringVal())
			if err != nil {
				rev.ERROR.Println("Failed to parse time:", takenTag.StringVal(), ":", err)
			}
		}

		// Save a record of the photo to our database.
		rect := photoImage.Bounds()
		photo := models.Photo{
			Username: name,
			Format:   format,
			Name:     photoName,
			Width:    rect.Max.X - rect.Min.X,
			Height:   rect.Max.Y - rect.Min.Y,
			Uploaded: time.Now(),
			Taken:    taken,
		}

		c.Txn.Insert(&photo)
	}

	c.Flash.Success("%d photos uploaded.", len(photos))
	return c.Redirect(Application.View)
}
Exemple #10
0
func serveThumb(resp http.ResponseWriter, req *http.Request, path string) {

	var outerr error

	log.Println("Requested image", path)
	//log.Println( "Oldest: ", icache.Top() )
	//log.Println( "heap: ", icache.GetPaths() )

	defer func() {
		if recover() != nil {
			if outerr == nil {
				http.Error(resp, "Internal Server Error", 500)
			} else {
				http.Error(resp, outerr.Error(), 500)
			}
		}
	}()

	/*
	   if icache == nil {
	       //icache = make( map[string]*bytes.Reader, 100 )
	       icache = &ImageCache{}
	   }
	*/

	cached, ok := icache.Find(path)

	if ok {
		icache.Update(path)
	} else {
		log.Println("Generating thumbnail")
		fd, err := os.Open(config.Root + "/" + path)
		defer fd.Close()

		if err != nil {
			outerr = err
			log.Panic("ERROR: file open error ", err.Error())
		}

		img, _, err := image.Decode(fd)
		if err != nil {
			outerr = err
			log.Panic("ERROR: Could not decode. ", err.Error())
		}

		scaled := image.NewRGBA(image.Rect(0, 0, 100, 100))

		graphics.Thumbnail(scaled, img)

		var buf bytes.Buffer
		err = jpeg.Encode(&buf, scaled, &jpeg.Options{jpeg.DefaultQuality})

		if err != nil {
			outerr = err
			log.Panic("ERROR: could not encode to jpeg. ", err.Error())
		}

		data, err := ioutil.ReadAll(&buf)
		if err != nil {
			outerr = err
			log.Panic("ERROR: ", err.Error())
		}

		cached = bytes.NewReader(data)

		heap.Push(icache, NewCacheItem(path, cached))

		if icache.Len() > config.MaxImages {
			log.Println("Dropping oldest cache: ", heap.Pop(icache).(*CacheItem).path)
		}

		//icache[ path ] = cached
	}

	cached.Seek(0, 0)
	io.Copy(resp, cached)
}