Пример #1
0
func rotate(img image.Image, orientation int) image.Image {
	fmt.Println("orientation:", orientation)
	// 1        2       3      4         5            6           7          8

	// 888888  888888      88  88      8888888888  88                  88  8888888888
	// 88          88      88  88      88  88      88  88          88  88      88  88
	// 8888      8888    8888  8888    88          8888888888  8888888888          88
	// 88          88      88  88
	// 88          88  888888  888888

	// func Rotate180(img image.Image) *image.NRGBA
	// func Rotate270(img image.Image) *image.NRGBA
	// func Rotate90(img image.Image) *image.NRGBA
	// func FlipH(img image.Image) *image.NRGBA
	// func FlipV(img image.Image) *image.NRGBA

	var out image.Image
	switch orientation {
	case 1:
		out = img
		// nothing;
	case 2:
		out = imaging.FlipH(img)
		// flip Horiz L to R
	case 3:
		out = imaging.Rotate180(img)
		// rotate 180 ccw
	case 4:
		out = imaging.FlipV(img)
		// flip Vert T to B
	case 5:
		out = imaging.Transpose(img)
		// transpose
	case 6:
		out = imaging.Rotate90(img)
		// rotate 90
	case 7:
		out = imaging.Transverse(img)
		// transverse
	case 8:
		out = imaging.Rotate270(img)
		// rotate 270
	default:
		out = img
		// nothing;
	}

	return out
}
Пример #2
0
func handleImages(previewPathList []string, thumbnailPathList []string, fileData [][]byte) {
	for i, data := range fileData {
		go func(i int, data []byte) {
			// Decode image bytes into Image object
			img, imgType, err := image.Decode(bytes.NewReader(fileData[i]))
			if err != nil {
				l4g.Error(utils.T("api.file.handle_images_forget.decode.error"), err)
				return
			}

			width := img.Bounds().Dx()
			height := img.Bounds().Dy()

			// Fill in the background of a potentially-transparent png file as white
			if imgType == "png" {
				dst := image.NewRGBA(img.Bounds())
				draw.Draw(dst, dst.Bounds(), image.NewUniform(color.White), image.Point{}, draw.Src)
				draw.Draw(dst, dst.Bounds(), img, img.Bounds().Min, draw.Over)
				img = dst
			}

			// Flip the image to be upright
			orientation, _ := getImageOrientation(fileData[i])

			switch orientation {
			case UprightMirrored:
				img = imaging.FlipH(img)
			case UpsideDown:
				img = imaging.Rotate180(img)
			case UpsideDownMirrored:
				img = imaging.FlipV(img)
			case RotatedCWMirrored:
				img = imaging.Transpose(img)
			case RotatedCCW:
				img = imaging.Rotate270(img)
			case RotatedCCWMirrored:
				img = imaging.Transverse(img)
			case RotatedCW:
				img = imaging.Rotate90(img)
			}

			go generateThumbnailImage(img, thumbnailPathList[i], width, height)
			go generatePreviewImage(img, previewPathList[i], width)
		}(i, data)
	}
}
Пример #3
0
func prepareImage(fileData []byte) (*image.Image, int, int) {
	// Decode image bytes into Image object
	img, imgType, err := image.Decode(bytes.NewReader(fileData))
	if err != nil {
		l4g.Error(utils.T("api.file.handle_images_forget.decode.error"), err)
		return nil, 0, 0
	}

	width := img.Bounds().Dx()
	height := img.Bounds().Dy()

	// Fill in the background of a potentially-transparent png file as white
	if imgType == "png" {
		dst := image.NewRGBA(img.Bounds())
		draw.Draw(dst, dst.Bounds(), image.NewUniform(color.White), image.Point{}, draw.Src)
		draw.Draw(dst, dst.Bounds(), img, img.Bounds().Min, draw.Over)
		img = dst
	}

	// Flip the image to be upright
	orientation, _ := getImageOrientation(fileData)

	switch orientation {
	case UprightMirrored:
		img = imaging.FlipH(img)
	case UpsideDown:
		img = imaging.Rotate180(img)
	case UpsideDownMirrored:
		img = imaging.FlipV(img)
	case RotatedCWMirrored:
		img = imaging.Transpose(img)
	case RotatedCCW:
		img = imaging.Rotate270(img)
	case RotatedCCWMirrored:
		img = imaging.Transverse(img)
	case RotatedCW:
		img = imaging.Rotate90(img)
	}

	return &img, width, height
}
Пример #4
0
func handleImages(filenames []string, fileData [][]byte, teamId, channelId, userId string) {
	dest := "teams/" + teamId + "/channels/" + channelId + "/users/" + userId + "/"

	for i, filename := range filenames {
		name := filename[:strings.LastIndex(filename, ".")]
		go func() {
			// Decode image bytes into Image object
			img, imgType, err := image.Decode(bytes.NewReader(fileData[i]))
			if err != nil {
				l4g.Error(utils.T("api.file.handle_images_forget.decode.error"), channelId, userId, filename, err)
				return
			}

			width := img.Bounds().Dx()
			height := img.Bounds().Dy()

			// Get the image's orientation and ignore any errors since not all images will have orientation data
			orientation, _ := getImageOrientation(fileData[i])

			if imgType == "png" {
				dst := image.NewRGBA(img.Bounds())
				draw.Draw(dst, dst.Bounds(), image.NewUniform(color.White), image.Point{}, draw.Src)
				draw.Draw(dst, dst.Bounds(), img, img.Bounds().Min, draw.Over)
				img = dst
			}

			switch orientation {
			case UprightMirrored:
				img = imaging.FlipH(img)
			case UpsideDown:
				img = imaging.Rotate180(img)
			case UpsideDownMirrored:
				img = imaging.FlipV(img)
			case RotatedCWMirrored:
				img = imaging.Transpose(img)
			case RotatedCCW:
				img = imaging.Rotate270(img)
			case RotatedCCWMirrored:
				img = imaging.Transverse(img)
			case RotatedCW:
				img = imaging.Rotate90(img)
			}

			// Create thumbnail
			go func() {
				thumbWidth := float64(utils.Cfg.FileSettings.ThumbnailWidth)
				thumbHeight := float64(utils.Cfg.FileSettings.ThumbnailHeight)
				imgWidth := float64(width)
				imgHeight := float64(height)

				var thumbnail image.Image
				if imgHeight < thumbHeight && imgWidth < thumbWidth {
					thumbnail = img
				} else if imgHeight/imgWidth < thumbHeight/thumbWidth {
					thumbnail = imaging.Resize(img, 0, utils.Cfg.FileSettings.ThumbnailHeight, imaging.Lanczos)
				} else {
					thumbnail = imaging.Resize(img, utils.Cfg.FileSettings.ThumbnailWidth, 0, imaging.Lanczos)
				}

				buf := new(bytes.Buffer)
				err = jpeg.Encode(buf, thumbnail, &jpeg.Options{Quality: 90})
				if err != nil {
					l4g.Error(utils.T("api.file.handle_images_forget.encode_jpeg.error"), channelId, userId, filename, err)
					return
				}

				if err := WriteFile(buf.Bytes(), dest+name+"_thumb.jpg"); err != nil {
					l4g.Error(utils.T("api.file.handle_images_forget.upload_thumb.error"), channelId, userId, filename, err)
					return
				}
			}()

			// Create preview
			go func() {
				var preview image.Image
				if width > int(utils.Cfg.FileSettings.PreviewWidth) {
					preview = imaging.Resize(img, utils.Cfg.FileSettings.PreviewWidth, utils.Cfg.FileSettings.PreviewHeight, imaging.Lanczos)
				} else {
					preview = img
				}

				buf := new(bytes.Buffer)

				err = jpeg.Encode(buf, preview, &jpeg.Options{Quality: 90})
				if err != nil {
					l4g.Error(utils.T("api.file.handle_images_forget.encode_preview.error"), channelId, userId, filename, err)
					return
				}

				if err := WriteFile(buf.Bytes(), dest+name+"_preview.jpg"); err != nil {
					l4g.Error(utils.T("api.file.handle_images_forget.upload_preview.error"), channelId, userId, filename, err)
					return
				}
			}()
		}()
	}
}
Пример #5
0
func storeImage(rw http.ResponseWriter, req *http.Request) {
	// Appengine
	var c appengine.Context
	// Google Cloud Storage authentication
	var cc gcscontext.Context
	// Google Cloud Storage bucket name
	var bucketName string = ""
	// Google Cloud Storage client
	var client *storage.Client
	// Google Cloud Storage bucket
	var bucketHandle *storage.BucketHandle
	// User uploaded image file name
	var fileName string = uuid.New()
	// Transform user uploaded image to a thumbnail file name
	var fileNameThumbnail string = uuid.New()
	// User uploaded image file type
	var contentType string = ""
	// User uploaded image file raw data
	var b []byte
	// Google Cloud Storage file writer
	var wc *storage.Writer = nil
	// Error
	var err error = nil
	// Result, 0: success, 1: failed
	var r int = http.StatusCreated

	// Set response in the end
	defer func() {
		// Return status. WriteHeader() must be called before call to Write
		if r == http.StatusCreated {
			// Changing the header after a call to WriteHeader (or Write) has no effect.
			// rw.Header().Set("Location", req.URL.String()+"/"+cKey.Encode())
			rw.Header().Set("Location", "http://"+bucketName+".storage.googleapis.com/"+fileName)
			rw.Header().Set("X-Thumbnail", "http://"+bucketName+".storage.googleapis.com/"+fileNameThumbnail)
			rw.WriteHeader(r)
		} else {
			http.Error(rw, http.StatusText(r), r)
		}
	}()

	// To log information in Google APP Engine console
	c = appengine.NewContext(req)

	// Get data from body
	b, err = ioutil.ReadAll(req.Body)
	if err != nil {
		c.Errorf("%s in reading body", err)
		r = http.StatusInternalServerError
		return
	}
	c.Infof("Body length %d bytes, read %d bytes", req.ContentLength, len(b))

	// Determine filename extension from content type
	contentType = req.Header["Content-Type"][0]
	switch contentType {
	case "image/jpeg":
		fileName += ".jpg"
		fileNameThumbnail += ".jpg"
	default:
		c.Errorf("Unknown or unsupported content type '%s'. Valid: image/jpeg", contentType)
		r = http.StatusBadRequest
		return
	}
	c.Infof("Content type %s is received, %s is detected.", contentType, http.DetectContentType(b))

	// Prepare Google Cloud Storage authentication
	cc = gcsappengine.NewContext(req)
	if client, err = storage.NewClient(cc); err != nil {
		c.Errorf("%s in initializing a GCS client", err)
		r = http.StatusInternalServerError
		return
	}
	defer client.Close()

	// Get default bucket
	if bucketName, err = gcsfile.DefaultBucketName(cc); err != nil {
		c.Errorf("%s in getting default GCS bucket name", err)
		r = http.StatusInternalServerError
		return
	}
	bucketHandle = client.Bucket(bucketName)
	c.Infof("APP Engine Version: %s", gcsappengine.VersionID(cc))
	c.Infof("Using bucket name: %s", bucketName)

	// Change default object ACLs
	if err = bucketHandle.DefaultObjectACL().Set(cc, storage.AllUsers, storage.RoleReader); err != nil {
		c.Errorf("%v in saving default object ACL rule for bucket %q", err, bucketName)
		r = http.StatusInternalServerError
		return
	}

	// Store rotated image in Google Cloud Storage
	var in *bytes.Reader = bytes.NewReader(b)
	var x *exif.Exif = nil
	var orientation *tiff.Tag = nil
	var beforeImage image.Image
	var afterImage *image.NRGBA = nil

	// Read EXIF
	if _, err = in.Seek(0, 0); err != nil {
		c.Errorf("%s in moving the reader offset to the beginning in order to read EXIF", err)
		return
	}
	if x, err = exif.Decode(in); err != nil {
		c.Errorf("%s in decoding JPEG image", err)
		return
	}

	// Get Orientation
	if orientation, err = x.Get(exif.Orientation); err != nil {
		c.Warningf("%s in getting orientation from EXIF", err)
		return
	}
	c.Debugf("Orientation %s", orientation.String())

	// Open image
	if _, err = in.Seek(0, 0); err != nil {
		c.Errorf("%s in moving the reader offset to the beginning in order to read EXIF", err)
		return
	}
	if beforeImage, err = imaging.Decode(in); err != nil {
		c.Errorf("%s in opening image %s", err)
		return
	}

	switch orientation.String() {
	case "1":
		afterImage = beforeImage.(*image.NRGBA)
	case "2":
		afterImage = imaging.FlipH(beforeImage)
	case "3":
		afterImage = imaging.Rotate180(beforeImage)
	case "4":
		afterImage = imaging.FlipV(beforeImage)
	case "5":
		afterImage = imaging.Transverse(beforeImage)
	case "6":
		afterImage = imaging.Rotate270(beforeImage)
	case "7":
		afterImage = imaging.Transpose(beforeImage)
	case "8":
		afterImage = imaging.Rotate90(beforeImage)
	}

	// Save rotated image
	wc = bucketHandle.Object(fileName).NewWriter(cc)
	wc.ContentType = contentType
	if err = imaging.Encode(wc, afterImage, imaging.JPEG); err != nil {
		c.Errorf("%s in saving rotated image", err)
		return
	}
	if err = wc.Close(); err != nil {
		c.Errorf("CreateFile: unable to close bucket %q, file %q: %v", bucketName, fileName, err)
		r = 1
		return
	}
	wc = nil

	// Make thumbnail
	if afterImage.Rect.Dx() > afterImage.Rect.Dy() {
		afterImage = imaging.Resize(afterImage, 1920, 0, imaging.Lanczos)
	} else {
		afterImage = imaging.Resize(afterImage, 0, 1920, imaging.Lanczos)
	}

	// Save thumbnail
	wc = bucketHandle.Object(fileNameThumbnail).NewWriter(cc)
	wc.ContentType = contentType
	if imaging.Encode(wc, afterImage, imaging.JPEG); err != nil {
		c.Errorf("%s in saving image thumbnail", err)
		return
	}
	if err = wc.Close(); err != nil {
		c.Errorf("CreateFileThumbnail: unable to close bucket %q, file %q: %v", bucketName, fileNameThumbnail, err)
		r = 1
		return
	}

	c.Infof("/%v/%v, /%v/%v created", bucketName, fileName, bucketName, fileNameThumbnail)
}
Пример #6
0
func main() {
	fmt.Println("Hello, world")
	fname := "P1070332.JPG"
	rname := "P1070332_rotate.JPG"
	sname := "P1070332_small.JPG"

	f, err := os.Open(fname)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	// Optionally register camera makenote data parsing - currently Nikon and
	// Canon are supported.
	exif.RegisterParsers(mknote.All...)

	x, err := exif.Decode(f)
	if err != nil {
		log.Fatal(err)
	}

	// Get Orientation
	orientation, err := x.Get(exif.Orientation)
	if err != nil {
		fmt.Println(exif.Model, " not fround")
		return
	}
	fmt.Println("Orientation", orientation.String())

	// Rotate
	var rotateImage *image.NRGBA
	openImage, err := imaging.Open(fname)
	if err != nil {
		fmt.Println(err)
		return
	}
	switch orientation.String() {
	case "1":
	// Do nothing
	case "2":
		rotateImage = imaging.FlipH(openImage)
	case "3":
		rotateImage = imaging.Rotate180(openImage)
	case "4":
		rotateImage = imaging.FlipV(openImage)
	case "5":
		rotateImage = imaging.Transverse(openImage)
	case "6":
		rotateImage = imaging.Rotate270(openImage)
	case "7":
		rotateImage = imaging.Transpose(openImage)
	case "8":
		rotateImage = imaging.Rotate90(openImage)
	}
	err = imaging.Save(rotateImage, rname)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(rname, " saved")

	// Small
	var smallImage *image.NRGBA
	if rotateImage.Rect.Dx() > rotateImage.Rect.Dy() {
		smallImage = imaging.Resize(rotateImage, 1920, 0, imaging.Lanczos)
	} else {
		smallImage = imaging.Resize(rotateImage, 0, 1920, imaging.Lanczos)
	}
	err = imaging.Save(smallImage, sname)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(sname, " saved")

	// Use jpeg.Encode() to write to a file
	// https://github.com/disintegration/imaging/blob/master/helpers.go#L79
	// func Encode(w io.Writer, m image.Image, o *Options) error
	// https://golang.org/pkg/image/jpeg/
}