mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 04:02:26 -05:00 
			
		
		
		
	update media processing (#244)
This commit is contained in:
		
					parent
					
						
							
								7e6350b448
							
						
					
				
			
			
				commit
				
					
						ddfd83d0fb
					
				
			
		
					 8 changed files with 63 additions and 81 deletions
				
			
		|  | @ -187,9 +187,9 @@ func (suite *MediaCreateTestSuite) TestStatusCreatePOSTImageHandlerSuccessful() | ||||||
| 			Aspect: 1.7777778, | 			Aspect: 1.7777778, | ||||||
| 		}, | 		}, | ||||||
| 		Small: model.MediaDimensions{ | 		Small: model.MediaDimensions{ | ||||||
| 			Width:  256, | 			Width:  512, | ||||||
| 			Height: 144, | 			Height: 288, | ||||||
| 			Size:   "256x144", | 			Size:   "512x288", | ||||||
| 			Aspect: 1.7777778, | 			Aspect: 1.7777778, | ||||||
| 		}, | 		}, | ||||||
| 		Focus: model.MediaFocus{ | 		Focus: model.MediaFocus{ | ||||||
|  | @ -197,7 +197,7 @@ func (suite *MediaCreateTestSuite) TestStatusCreatePOSTImageHandlerSuccessful() | ||||||
| 			Y: 0.5, | 			Y: 0.5, | ||||||
| 		}, | 		}, | ||||||
| 	}, attachmentReply.Meta) | 	}, attachmentReply.Meta) | ||||||
| 	assert.Equal(suite.T(), "LjCZnlvyRkRn_NvzRjWF?urqV@f9", attachmentReply.Blurhash) | 	assert.Equal(suite.T(), "LjBzUo#6RQR._NvzRjWF?urqV@a$", attachmentReply.Blurhash) | ||||||
| 	assert.NotEmpty(suite.T(), attachmentReply.ID) | 	assert.NotEmpty(suite.T(), attachmentReply.ID) | ||||||
| 	assert.NotEmpty(suite.T(), attachmentReply.URL) | 	assert.NotEmpty(suite.T(), attachmentReply.URL) | ||||||
| 	assert.NotEmpty(suite.T(), attachmentReply.PreviewURL) | 	assert.NotEmpty(suite.T(), attachmentReply.PreviewURL) | ||||||
|  |  | ||||||
|  | @ -65,7 +65,7 @@ func (suite *AttachmentTestSuite) TestDereferenceAttachmentOK() { | ||||||
| 	suite.Equal(2071680, attachment.FileMeta.Original.Size) | 	suite.Equal(2071680, attachment.FileMeta.Original.Size) | ||||||
| 	suite.Equal(1245, attachment.FileMeta.Original.Height) | 	suite.Equal(1245, attachment.FileMeta.Original.Height) | ||||||
| 	suite.Equal(1664, attachment.FileMeta.Original.Width) | 	suite.Equal(1664, attachment.FileMeta.Original.Width) | ||||||
| 	suite.Equal("LwQ9yKRP_4t8t7RjWBt7%hozM_ay", attachment.Blurhash) | 	suite.Equal("LwP?p=aK_4%N%MRjWXt7%hozM_a}", attachment.Blurhash) | ||||||
| 	suite.Equal(gtsmodel.ProcessingStatusProcessed, attachment.Processing) | 	suite.Equal(gtsmodel.ProcessingStatusProcessed, attachment.Processing) | ||||||
| 	suite.NotEmpty(attachment.File.Path) | 	suite.NotEmpty(attachment.File.Path) | ||||||
| 	suite.Equal(attachmentContentType, attachment.File.ContentType) | 	suite.Equal(attachmentContentType, attachment.File.ContentType) | ||||||
|  | @ -91,7 +91,7 @@ func (suite *AttachmentTestSuite) TestDereferenceAttachmentOK() { | ||||||
| 	suite.Equal(2071680, dbAttachment.FileMeta.Original.Size) | 	suite.Equal(2071680, dbAttachment.FileMeta.Original.Size) | ||||||
| 	suite.Equal(1245, dbAttachment.FileMeta.Original.Height) | 	suite.Equal(1245, dbAttachment.FileMeta.Original.Height) | ||||||
| 	suite.Equal(1664, dbAttachment.FileMeta.Original.Width) | 	suite.Equal(1664, dbAttachment.FileMeta.Original.Width) | ||||||
| 	suite.Equal("LwQ9yKRP_4t8t7RjWBt7%hozM_ay", dbAttachment.Blurhash) | 	suite.Equal("LwP?p=aK_4%N%MRjWXt7%hozM_a}", dbAttachment.Blurhash) | ||||||
| 	suite.Equal(gtsmodel.ProcessingStatusProcessed, dbAttachment.Processing) | 	suite.Equal(gtsmodel.ProcessingStatusProcessed, dbAttachment.Processing) | ||||||
| 	suite.NotEmpty(dbAttachment.File.Path) | 	suite.NotEmpty(dbAttachment.File.Path) | ||||||
| 	suite.Equal(attachmentContentType, dbAttachment.File.ContentType) | 	suite.Equal(attachmentContentType, dbAttachment.File.ContentType) | ||||||
|  |  | ||||||
|  | @ -120,7 +120,7 @@ func (mh *mediaHandler) processHeaderOrAvi(imageBytes []byte, contentType string | ||||||
| 		AccountID:         accountID, | 		AccountID:         accountID, | ||||||
| 		Description:       "", | 		Description:       "", | ||||||
| 		ScheduledStatusID: "", | 		ScheduledStatusID: "", | ||||||
| 		Blurhash:          original.blurhash, | 		Blurhash:          small.blurhash, | ||||||
| 		Processing:        2, | 		Processing:        2, | ||||||
| 		File: gtsmodel.File{ | 		File: gtsmodel.File{ | ||||||
| 			Path:        originalPath, | 			Path:        originalPath, | ||||||
|  |  | ||||||
|  | @ -55,7 +55,7 @@ func (mh *mediaHandler) processImageAttachment(data []byte, minAttachment *gtsmo | ||||||
| 		return nil, errors.New("media type unrecognized") | 		return nil, errors.New("media type unrecognized") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	small, err = deriveThumbnail(clean, contentType, 256, 256) | 	small, err = deriveThumbnail(clean, contentType, 512, 512) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("error deriving thumbnail: %s", err) | 		return nil, fmt.Errorf("error deriving thumbnail: %s", err) | ||||||
| 	} | 	} | ||||||
|  | @ -109,7 +109,7 @@ func (mh *mediaHandler) processImageAttachment(data []byte, minAttachment *gtsmo | ||||||
| 		AccountID:         minAttachment.AccountID, | 		AccountID:         minAttachment.AccountID, | ||||||
| 		Description:       minAttachment.Description, | 		Description:       minAttachment.Description, | ||||||
| 		ScheduledStatusID: minAttachment.ScheduledStatusID, | 		ScheduledStatusID: minAttachment.ScheduledStatusID, | ||||||
| 		Blurhash:          original.blurhash, | 		Blurhash:          small.blurhash, | ||||||
| 		Processing:        2, | 		Processing:        2, | ||||||
| 		File: gtsmodel.File{ | 		File: gtsmodel.File{ | ||||||
| 			Path:        originalPath, | 			Path:        originalPath, | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 753 KiB After Width: | Height: | Size: 263 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 24 KiB | 
|  | @ -156,23 +156,12 @@ func deriveGif(b []byte, extension string) (*imageAndMeta, error) { | ||||||
| 	size := width * height | 	size := width * height | ||||||
| 	aspect := float64(width) / float64(height) | 	aspect := float64(width) / float64(height) | ||||||
| 
 | 
 | ||||||
| 	bh, err := blurhash.Encode(4, 3, g.Image[0]) |  | ||||||
| 	if err != nil || bh == "" { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	out := &bytes.Buffer{} |  | ||||||
| 	if err := gif.EncodeAll(out, g); err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return &imageAndMeta{ | 	return &imageAndMeta{ | ||||||
| 		image:    out.Bytes(), | 		image:  b, | ||||||
| 		width:  width, | 		width:  width, | ||||||
| 		height: height, | 		height: height, | ||||||
| 		size:   size, | 		size:   size, | ||||||
| 		aspect: aspect, | 		aspect: aspect, | ||||||
| 		blurhash: bh, |  | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -200,25 +189,12 @@ func deriveImage(b []byte, contentType string) (*imageAndMeta, error) { | ||||||
| 	size := width * height | 	size := width * height | ||||||
| 	aspect := float64(width) / float64(height) | 	aspect := float64(width) / float64(height) | ||||||
| 
 | 
 | ||||||
| 	bh, err := blurhash.Encode(4, 3, i) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	out := &bytes.Buffer{} |  | ||||||
| 	if err := jpeg.Encode(out, i, &jpeg.Options{ |  | ||||||
| 		Quality: 100, |  | ||||||
| 	}); err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return &imageAndMeta{ | 	return &imageAndMeta{ | ||||||
| 		image:    out.Bytes(), | 		image:  b, | ||||||
| 		width:  width, | 		width:  width, | ||||||
| 		height: height, | 		height: height, | ||||||
| 		size:   size, | 		size:   size, | ||||||
| 		aspect: aspect, | 		aspect: aspect, | ||||||
| 		blurhash: bh, |  | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -257,9 +233,15 @@ func deriveThumbnail(b []byte, contentType string, x uint, y uint) (*imageAndMet | ||||||
| 	size := width * height | 	size := width * height | ||||||
| 	aspect := float64(width) / float64(height) | 	aspect := float64(width) / float64(height) | ||||||
| 
 | 
 | ||||||
|  | 	tiny := resize.Thumbnail(32, 32, thumb, resize.NearestNeighbor) | ||||||
|  | 	bh, err := blurhash.Encode(4, 3, tiny) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	out := &bytes.Buffer{} | 	out := &bytes.Buffer{} | ||||||
| 	if err := jpeg.Encode(out, thumb, &jpeg.Options{ | 	if err := jpeg.Encode(out, thumb, &jpeg.Options{ | ||||||
| 		Quality: 100, | 		Quality: 75, | ||||||
| 	}); err != nil { | 	}); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -269,6 +251,7 @@ func deriveThumbnail(b []byte, contentType string, x uint, y uint) (*imageAndMet | ||||||
| 		height:   height, | 		height:   height, | ||||||
| 		size:     size, | 		size:     size, | ||||||
| 		aspect:   aspect, | 		aspect:   aspect, | ||||||
|  | 		blurhash: bh, | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,7 +23,6 @@ import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/stretchr/testify/assert" |  | ||||||
| 	"github.com/stretchr/testify/suite" | 	"github.com/stretchr/testify/suite" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -64,82 +63,82 @@ func (suite *MediaUtilTestSuite) TearDownTest() { | ||||||
| 
 | 
 | ||||||
| func (suite *MediaUtilTestSuite) TestParseContentTypeOK() { | func (suite *MediaUtilTestSuite) TestParseContentTypeOK() { | ||||||
| 	f, err := ioutil.ReadFile("./test/test-jpeg.jpg") | 	f, err := ioutil.ReadFile("./test/test-jpeg.jpg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 	ct, err := parseContentType(f) | 	ct, err := parseContentType(f) | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 	assert.Equal(suite.T(), "image/jpeg", ct) | 	suite.Equal("image/jpeg", ct) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (suite *MediaUtilTestSuite) TestParseContentTypeNotOK() { | func (suite *MediaUtilTestSuite) TestParseContentTypeNotOK() { | ||||||
| 	f, err := ioutil.ReadFile("./test/test-corrupted.jpg") | 	f, err := ioutil.ReadFile("./test/test-corrupted.jpg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 	ct, err := parseContentType(f) | 	ct, err := parseContentType(f) | ||||||
| 	assert.NotNil(suite.T(), err) | 	suite.NotNil(err) | ||||||
| 	assert.Equal(suite.T(), "", ct) | 	suite.Equal("", ct) | ||||||
| 	assert.Equal(suite.T(), "filetype unknown", err.Error()) | 	suite.Equal("filetype unknown", err.Error()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (suite *MediaUtilTestSuite) TestRemoveEXIF() { | func (suite *MediaUtilTestSuite) TestRemoveEXIF() { | ||||||
| 	// load and validate image | 	// load and validate image | ||||||
| 	b, err := ioutil.ReadFile("./test/test-with-exif.jpg") | 	b, err := ioutil.ReadFile("./test/test-with-exif.jpg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 
 | 
 | ||||||
| 	// clean it up and validate the clean version | 	// clean it up and validate the clean version | ||||||
| 	clean, err := purgeExif(b) | 	clean, err := purgeExif(b) | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 
 | 
 | ||||||
| 	// compare it to our stored sample | 	// compare it to our stored sample | ||||||
| 	sampleBytes, err := ioutil.ReadFile("./test/test-without-exif.jpg") | 	sampleBytes, err := ioutil.ReadFile("./test/test-without-exif.jpg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 	assert.EqualValues(suite.T(), sampleBytes, clean) | 	suite.EqualValues(sampleBytes, clean) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (suite *MediaUtilTestSuite) TestDeriveImageFromJPEG() { | func (suite *MediaUtilTestSuite) TestDeriveImageFromJPEG() { | ||||||
| 	// load image | 	// load image | ||||||
| 	b, err := ioutil.ReadFile("./test/test-jpeg.jpg") | 	b, err := ioutil.ReadFile("./test/test-jpeg.jpg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 
 | 
 | ||||||
| 	// clean it up and validate the clean version | 	// clean it up and validate the clean version | ||||||
| 	imageAndMeta, err := deriveImage(b, "image/jpeg") | 	imageAndMeta, err := deriveImage(b, "image/jpeg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 
 | 
 | ||||||
| 	assert.Equal(suite.T(), 1920, imageAndMeta.width) | 	suite.Equal(1920, imageAndMeta.width) | ||||||
| 	assert.Equal(suite.T(), 1080, imageAndMeta.height) | 	suite.Equal(1080, imageAndMeta.height) | ||||||
| 	assert.Equal(suite.T(), 1.7777777777777777, imageAndMeta.aspect) | 	suite.Equal(1.7777777777777777, imageAndMeta.aspect) | ||||||
| 	assert.Equal(suite.T(), 2073600, imageAndMeta.size) | 	suite.Equal(2073600, imageAndMeta.size) | ||||||
| 	assert.Equal(suite.T(), "LjCZnlvyRkRn_NvzRjWF?urqV@f9", imageAndMeta.blurhash) |  | ||||||
| 
 | 
 | ||||||
| 	// assert that the final image is what we would expect | 	// assert that the final image is what we would expect | ||||||
| 	sampleBytes, err := ioutil.ReadFile("./test/test-jpeg-processed.jpg") | 	sampleBytes, err := ioutil.ReadFile("./test/test-jpeg-processed.jpg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 	assert.EqualValues(suite.T(), sampleBytes, imageAndMeta.image) | 	suite.EqualValues(sampleBytes, imageAndMeta.image) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (suite *MediaUtilTestSuite) TestDeriveThumbnailFromJPEG() { | func (suite *MediaUtilTestSuite) TestDeriveThumbnailFromJPEG() { | ||||||
| 	// load image | 	// load image | ||||||
| 	b, err := ioutil.ReadFile("./test/test-jpeg.jpg") | 	b, err := ioutil.ReadFile("./test/test-jpeg.jpg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 
 | 
 | ||||||
| 	// clean it up and validate the clean version | 	// clean it up and validate the clean version | ||||||
| 	imageAndMeta, err := deriveThumbnail(b, "image/jpeg", 256, 256) | 	imageAndMeta, err := deriveThumbnail(b, "image/jpeg", 512, 512) | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 
 | 
 | ||||||
| 	assert.Equal(suite.T(), 256, imageAndMeta.width) | 	suite.Equal(512, imageAndMeta.width) | ||||||
| 	assert.Equal(suite.T(), 144, imageAndMeta.height) | 	suite.Equal(288, imageAndMeta.height) | ||||||
| 	assert.Equal(suite.T(), 1.7777777777777777, imageAndMeta.aspect) | 	suite.Equal(1.7777777777777777, imageAndMeta.aspect) | ||||||
| 	assert.Equal(suite.T(), 36864, imageAndMeta.size) | 	suite.Equal(147456, imageAndMeta.size) | ||||||
|  | 	suite.Equal("LjBzUo#6RQR._NvzRjWF?urqV@a$", imageAndMeta.blurhash) | ||||||
| 
 | 
 | ||||||
| 	sampleBytes, err := ioutil.ReadFile("./test/test-jpeg-thumbnail.jpg") | 	sampleBytes, err := ioutil.ReadFile("./test/test-jpeg-thumbnail.jpg") | ||||||
| 	assert.Nil(suite.T(), err) | 	suite.NoError(err) | ||||||
| 	assert.EqualValues(suite.T(), sampleBytes, imageAndMeta.image) | 	suite.EqualValues(sampleBytes, imageAndMeta.image) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (suite *MediaUtilTestSuite) TestSupportedImageTypes() { | func (suite *MediaUtilTestSuite) TestSupportedImageTypes() { | ||||||
| 	ok := SupportedImageType("image/jpeg") | 	ok := SupportedImageType("image/jpeg") | ||||||
| 	assert.True(suite.T(), ok) | 	suite.True(ok) | ||||||
| 
 | 
 | ||||||
| 	ok = SupportedImageType("image/bmp") | 	ok = SupportedImageType("image/bmp") | ||||||
| 	assert.False(suite.T(), ok) | 	suite.False(ok) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestMediaUtilTestSuite(t *testing.T) { | func TestMediaUtilTestSuite(t *testing.T) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue