mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2024-11-10 06:54:16 +00:00
[chore] Only call imaging.Resize when necessary
, use even tinier blurhashes (#3247)
* [chore] Use `imaging.Fit`, use even tinier blurhashes * avoid calling resize if not necessary * update blurhashes + thumb
This commit is contained in:
parent
277b043633
commit
e10aa76612
7 changed files with 60 additions and 53 deletions
|
@ -858,7 +858,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
|
|||
"static_url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/small/`+instanceAccount.AvatarMediaAttachment.ID+`.webp",`+`
|
||||
"thumbnail_static_type": "image/webp",
|
||||
"thumbnail_description": "A bouncing little green peglin.",
|
||||
"blurhash": "LE9as6M}4YtO%dRlWEt6Dmoxx?WC"
|
||||
"blurhash": "LF9kG$RR4YtP%dR+V^t5D,oxx?WC"
|
||||
}`, string(instanceV2ThumbnailJson))
|
||||
|
||||
// double extra special bonus: now update the image description without changing the image
|
||||
|
|
|
@ -206,7 +206,7 @@ func (suite *MediaCreateTestSuite) TestMediaCreateSuccessful() {
|
|||
Y: 0.5,
|
||||
},
|
||||
}, *attachmentReply.Meta)
|
||||
suite.Equal("LjCGfG#6RkRn_NvzRjWF?urqV@a$", *attachmentReply.Blurhash)
|
||||
suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", *attachmentReply.Blurhash)
|
||||
suite.NotEmpty(attachmentReply.ID)
|
||||
suite.NotEmpty(attachmentReply.URL)
|
||||
suite.NotEmpty(attachmentReply.PreviewURL)
|
||||
|
@ -291,7 +291,7 @@ func (suite *MediaCreateTestSuite) TestMediaCreateSuccessfulV2() {
|
|||
Y: 0.5,
|
||||
},
|
||||
}, *attachmentReply.Meta)
|
||||
suite.Equal("LjCGfG#6RkRn_NvzRjWF?urqV@a$", *attachmentReply.Blurhash)
|
||||
suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", *attachmentReply.Blurhash)
|
||||
suite.NotEmpty(attachmentReply.ID)
|
||||
suite.Nil(attachmentReply.URL)
|
||||
suite.NotEmpty(attachmentReply.PreviewURL)
|
||||
|
|
|
@ -276,7 +276,7 @@ func (suite *ManagerTestSuite) TestSimpleJpegProcess() {
|
|||
suite.Equal("image/jpeg", attachment.Thumbnail.ContentType)
|
||||
suite.Equal(269739, attachment.File.FileSize)
|
||||
suite.Equal(22858, attachment.Thumbnail.FileSize)
|
||||
suite.Equal("LjCGfG#6RkRn_NvzRjWF?urqV@a$", attachment.Blurhash)
|
||||
suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", attachment.Blurhash)
|
||||
|
||||
// now make sure the attachment is in the database
|
||||
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
|
||||
|
@ -429,7 +429,7 @@ func (suite *ManagerTestSuite) TestSlothVineProcess() {
|
|||
suite.Equal("image/webp", attachment.Thumbnail.ContentType)
|
||||
suite.Equal(312453, attachment.File.FileSize)
|
||||
suite.Equal(5648, attachment.Thumbnail.FileSize)
|
||||
suite.Equal("LhIrNMt6Nsj[t7ayW.j[_4WBsWkB", attachment.Blurhash)
|
||||
suite.Equal("LfIYH~xtNskCxtfPW.kB_4aespof", attachment.Blurhash)
|
||||
|
||||
// now make sure the attachment is in the database
|
||||
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
|
||||
|
@ -489,7 +489,7 @@ func (suite *ManagerTestSuite) TestLongerMp4Process() {
|
|||
suite.Equal("image/webp", attachment.Thumbnail.ContentType)
|
||||
suite.Equal(109569, attachment.File.FileSize)
|
||||
suite.Equal(2976, attachment.Thumbnail.FileSize)
|
||||
suite.Equal("L8QJfm~qD%_3_3D%t7RjM{j[ofRj", attachment.Blurhash)
|
||||
suite.Equal("LJQJfm?bM{?b~qRjt7WBayWBofWB", attachment.Blurhash)
|
||||
|
||||
// now make sure the attachment is in the database
|
||||
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
|
||||
|
@ -549,7 +549,7 @@ func (suite *ManagerTestSuite) TestBirdnestMp4Process() {
|
|||
suite.Equal("image/webp", attachment.Thumbnail.ContentType)
|
||||
suite.Equal(1409625, attachment.File.FileSize)
|
||||
suite.Equal(14478, attachment.Thumbnail.FileSize)
|
||||
suite.Equal("LKF~w1RjRO.99DM_RPaetkV?WCMw", attachment.Blurhash)
|
||||
suite.Equal("LJF?FZV@RO.99DM_RPWAx]V?ayMw", attachment.Blurhash)
|
||||
|
||||
// now make sure the attachment is in the database
|
||||
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
|
||||
|
@ -657,7 +657,7 @@ func (suite *ManagerTestSuite) TestPngNoAlphaChannelProcess() {
|
|||
suite.Equal("image/jpeg", attachment.Thumbnail.ContentType)
|
||||
suite.Equal(17471, attachment.File.FileSize)
|
||||
suite.Equal(6446, attachment.Thumbnail.FileSize)
|
||||
suite.Equal("LDQcrD%i-?aj%ho#M~RP~nf3~nt2", attachment.Blurhash)
|
||||
suite.Equal("LFQT7e.A%O%4?co$M}M{_1W9~TxV", attachment.Blurhash)
|
||||
|
||||
// now make sure the attachment is in the database
|
||||
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
|
||||
|
@ -713,7 +713,7 @@ func (suite *ManagerTestSuite) TestPngAlphaChannelProcess() {
|
|||
suite.Equal("image/webp", attachment.Thumbnail.ContentType)
|
||||
suite.Equal(18832, attachment.File.FileSize)
|
||||
suite.Equal(3592, attachment.Thumbnail.FileSize)
|
||||
suite.Equal("LBOW$@%i-rak%go#RSRP_1av~Ts+", attachment.Blurhash)
|
||||
suite.Equal("LCONII.A%Oxw?co#M}M{_1ac~TxV", attachment.Blurhash)
|
||||
|
||||
// now make sure the attachment is in the database
|
||||
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
|
||||
|
@ -769,7 +769,7 @@ func (suite *ManagerTestSuite) TestSimpleJpegProcessWithCallback() {
|
|||
suite.Equal("image/jpeg", attachment.Thumbnail.ContentType)
|
||||
suite.Equal(269739, attachment.File.FileSize)
|
||||
suite.Equal(22858, attachment.Thumbnail.FileSize)
|
||||
suite.Equal("LjCGfG#6RkRn_NvzRjWF?urqV@a$", attachment.Blurhash)
|
||||
suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", attachment.Blurhash)
|
||||
|
||||
// now make sure the attachment is in the database
|
||||
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
|
||||
|
@ -847,7 +847,7 @@ func (suite *ManagerTestSuite) TestSimpleJpegProcessWithDiskStorage() {
|
|||
suite.Equal("image/jpeg", attachment.Thumbnail.ContentType)
|
||||
suite.Equal(269739, attachment.File.FileSize)
|
||||
suite.Equal(22858, attachment.Thumbnail.FileSize)
|
||||
suite.Equal("LjCGfG#6RkRn_NvzRjWF?urqV@a$", attachment.Blurhash)
|
||||
suite.Equal("LiBzRk#6V[WF_NvzV@WY_3rqV@a$", attachment.Blurhash)
|
||||
|
||||
// now make sure the attachment is in the database
|
||||
dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID)
|
||||
|
|
|
@ -34,6 +34,40 @@ import (
|
|||
"golang.org/x/image/webp"
|
||||
)
|
||||
|
||||
const (
|
||||
maxThumbWidth = 512
|
||||
maxThumbHeight = 512
|
||||
)
|
||||
|
||||
// thumbSize returns the dimensions to use for an input
|
||||
// image of given width / height, for its outgoing thumbnail.
|
||||
// This attempts to maintains the original image aspect ratio.
|
||||
func thumbSize(width, height int, aspect float32) (int, int) {
|
||||
|
||||
switch {
|
||||
// Simplest case, within bounds!
|
||||
case width < maxThumbWidth &&
|
||||
height < maxThumbHeight:
|
||||
return width, height
|
||||
|
||||
// Width is larger side.
|
||||
case width > height:
|
||||
// i.e. height = newWidth * (height / width)
|
||||
height = int(float32(maxThumbWidth) / aspect)
|
||||
return maxThumbWidth, height
|
||||
|
||||
// Height is larger side.
|
||||
case height > width:
|
||||
// i.e. width = newHeight * (width / height)
|
||||
width = int(float32(maxThumbHeight) * aspect)
|
||||
return width, maxThumbHeight
|
||||
|
||||
// Square.
|
||||
default:
|
||||
return maxThumbWidth, maxThumbHeight
|
||||
}
|
||||
}
|
||||
|
||||
// generateThumb generates a thumbnail for the
|
||||
// input file at path, resizing it to the given
|
||||
// dimensions and generating a blurhash if needed.
|
||||
|
@ -229,11 +263,17 @@ func generateNativeThumb(
|
|||
img = imaging.Transverse(img)
|
||||
}
|
||||
|
||||
// Resize image to dimens.
|
||||
img = imaging.Resize(img,
|
||||
width, height,
|
||||
imaging.Linear,
|
||||
)
|
||||
// Resize image to dimens only if necessary.
|
||||
if img.Bounds().Dx() > maxThumbWidth ||
|
||||
img.Bounds().Dy() > maxThumbHeight {
|
||||
// Note: We could call "imaging.Fit" here
|
||||
// but there's no point, as we've already
|
||||
// calculated target dimensions beforehand.
|
||||
img = imaging.Resize(img,
|
||||
width, height,
|
||||
imaging.Linear,
|
||||
)
|
||||
}
|
||||
|
||||
// Open output file at given path.
|
||||
outfile, err := os.Create(outpath)
|
||||
|
@ -255,7 +295,7 @@ func generateNativeThumb(
|
|||
if needBlurhash {
|
||||
// for generating blurhashes, it's more cost effective to
|
||||
// lose detail since it's blurry, so make a tiny version.
|
||||
tiny := imaging.Resize(img, 64, 64, imaging.NearestNeighbor)
|
||||
tiny := imaging.Resize(img, 32, 0, imaging.NearestNeighbor)
|
||||
|
||||
// Drop the larger image
|
||||
// ref as soon as possible
|
||||
|
@ -294,7 +334,7 @@ func generateWebpBlurhash(filepath string) (string, error) {
|
|||
|
||||
// for generating blurhashes, it's more cost effective to
|
||||
// lose detail since it's blurry, so make a tiny version.
|
||||
tiny := imaging.Resize(img, 64, 64, imaging.NearestNeighbor)
|
||||
tiny := imaging.Resize(img, 32, 0, imaging.NearestNeighbor)
|
||||
|
||||
// Drop the larger image
|
||||
// ref as soon as possible
|
||||
|
|
|
@ -39,39 +39,6 @@ func getExtension(path string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// thumbSize returns the dimensions to use for an input
|
||||
// image of given width / height, for its outgoing thumbnail.
|
||||
// This attempts to maintains the original image aspect ratio.
|
||||
func thumbSize(width, height int, aspect float32) (int, int) {
|
||||
const (
|
||||
maxThumbWidth = 512
|
||||
maxThumbHeight = 512
|
||||
)
|
||||
|
||||
switch {
|
||||
// Simplest case, within bounds!
|
||||
case width < maxThumbWidth &&
|
||||
height < maxThumbHeight:
|
||||
return width, height
|
||||
|
||||
// Width is larger side.
|
||||
case width > height:
|
||||
// i.e. height = newWidth * (height / width)
|
||||
height = int(float32(maxThumbWidth) / aspect)
|
||||
return maxThumbWidth, height
|
||||
|
||||
// Height is larger side.
|
||||
case height > width:
|
||||
// i.e. width = newHeight * (width / height)
|
||||
width = int(float32(maxThumbHeight) * aspect)
|
||||
return width, maxThumbHeight
|
||||
|
||||
// Square.
|
||||
default:
|
||||
return maxThumbWidth, maxThumbHeight
|
||||
}
|
||||
}
|
||||
|
||||
// getMimeType returns a suitable mimetype for file extension.
|
||||
func getMimeType(ext string) string {
|
||||
const defaultType = "application/octet-stream"
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
@ -1078,7 +1078,7 @@ func NewTestAttachments() map[string]*gtsmodel.MediaAttachment {
|
|||
Thumbnail: gtsmodel.Thumbnail{
|
||||
Path: "01F8MH5ZK5VRH73AKHQM6Y9VNX/attachment/small/01FVW7RXPQ8YJHTEXYPE7Q8ZY0.jpeg",
|
||||
ContentType: "image/jpeg",
|
||||
FileSize: 20394,
|
||||
FileSize: 20395,
|
||||
URL: "http://localhost:8080/fileserver/01F8MH5ZK5VRH73AKHQM6Y9VNX/attachment/small/01FVW7RXPQ8YJHTEXYPE7Q8ZY0.webp",
|
||||
},
|
||||
Avatar: util.Ptr(false),
|
||||
|
@ -1124,7 +1124,7 @@ func NewTestAttachments() map[string]*gtsmodel.MediaAttachment {
|
|||
Thumbnail: gtsmodel.Thumbnail{
|
||||
Path: "062G5WYKY35KKD12EMSM3F8PJ8/attachment/small/01PFPMWK2FF0D9WMHEJHR07C3R.jpeg",
|
||||
ContentType: "image/webp",
|
||||
FileSize: 20394,
|
||||
FileSize: 20395,
|
||||
URL: "http://localhost:8080/fileserver/062G5WYKY35KKD12EMSM3F8PJ8/header/small/01PFPMWK2FF0D9WMHEJHR07C3R.webp",
|
||||
},
|
||||
Avatar: util.Ptr(false),
|
||||
|
|
Loading…
Reference in a new issue