From e1fca412fc9c1f98f1682052fa8ce52166181a44 Mon Sep 17 00:00:00 2001 From: George Goldberg Date: Tue, 22 Nov 2016 15:14:25 +0000 Subject: PLT-4442 Generate preview images sequentially in Slack importer (#4617) * Break out image preparation to its own function. This is preparatory work to make it easier to handle the thumbnail image generation in a non-racy way in the Slack command line importer. * Build preview images sequentially in Slack import. This removes the use of goroutines from the image preview generation code run when importing Slack attachments. This slows things down, but it has important benefits: 1) Avoids a race condition with the goroutines and the command line exiting. 2) Avoids the problem of massive memory consumption when importing a Slack channel with a lot of large images attached in quick succession. Fixes PLT-4442. * Use mutliple return values instead of struct. --- api/file.go | 85 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 39 deletions(-) (limited to 'api/file.go') diff --git a/api/file.go b/api/file.go index dd075d3e0..8de69937a 100644 --- a/api/file.go +++ b/api/file.go @@ -195,50 +195,57 @@ func doUploadFile(teamId string, channelId string, userId string, rawFilename st 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) + img, width, height := prepareImage(fileData[i]) + if img != nil { + go generateThumbnailImage(*img, thumbnailPathList[i], width, height) + go generatePreviewImage(*img, previewPathList[i], width) } - - go generateThumbnailImage(img, thumbnailPathList[i], width, height) - go generatePreviewImage(img, previewPathList[i], width) }(i, data) } } +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 +} + func getImageOrientation(imageData []byte) (int, error) { if exifData, err := exif.Decode(bytes.NewReader(imageData)); err != nil { return Upright, err -- cgit v1.2.3-1-g7c22