mirror of
https://github.com/mattermost/mattermost.git
synced 2026-08-30 17:06:34 +08:00
* Fix EXIF profile picture orientation bug (#34275) * Test AdustProfileImage with rotated PNG assets This commit adds two test assets: - quadrants-orientation-1.png - quadrants-orientation-8.png Both represent the exact same image: a 128x128 image with four differently coloured 64x64 quadrants. Clockwise, starting from the top-left: green, white, blue and red [G][W] [R][B] quadrants-orientation-1.png has an EXIF rotation tag of 1, meaning that its data is already correctly rotated. quadrants-orientation-8.png has an EXIF rotation tag of 8, meaning that the data in the file is rotated 90° clockwise, and an inverse rotation needs to be applied to render it correctly. Rendering the raw data would show the following: [R][G] [B][W] That rotation is what we test in the new TestAdjustProfileImage sub-test, which calls AdjustImage in both PNGs and make a byte-to-byte comparison of the result, which is expected to be equal. * Fix imports --------- Co-authored-by: Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
This commit is contained in:
@@ -1026,6 +1026,12 @@ func (a *App) AdjustImage(rctx request.CTX, file io.ReadSeeker) (*bytes.Buffer,
|
||||
return nil, model.NewAppError("SetProfileImage", "api.user.upload_profile_user.decode.app_error", nil, "", http.StatusBadRequest).Wrap(err)
|
||||
}
|
||||
|
||||
// Decode() reads the file to EOF; seek back to beginning so GetImageOrientation
|
||||
// can read the EXIF data to determine the correct orientation.
|
||||
if _, seekErr := file.Seek(0, io.SeekStart); seekErr != nil {
|
||||
rctx.Logger().Warn("Failed to seek image file for orientation check", mlog.Err(seekErr))
|
||||
}
|
||||
|
||||
orientation, err := imaging.GetImageOrientation(file, format)
|
||||
if err != nil {
|
||||
rctx.Logger().Warn("Failed to get image orientation", mlog.Err(err))
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -140,11 +142,28 @@ func TestAdjustProfileImage(t *testing.T) {
|
||||
|
||||
// default image should not require adjustment
|
||||
user := th.BasicUser
|
||||
image, appErr := th.App.GetDefaultProfileImage(user)
|
||||
defaultImg, appErr := th.App.GetDefaultProfileImage(user)
|
||||
require.Nil(t, appErr)
|
||||
image2, appErr := th.App.AdjustImage(th.Context, bytes.NewReader(image))
|
||||
image2, appErr := th.App.AdjustImage(th.Context, bytes.NewReader(defaultImg))
|
||||
require.Nil(t, appErr)
|
||||
assert.Equal(t, image, image2.Bytes())
|
||||
assert.Equal(t, defaultImg, image2.Bytes())
|
||||
|
||||
t.Run("EXIF orientation is applied for rotated images", func(t *testing.T) {
|
||||
// quadrants-orientation-8.png: 128×128 color quadrants with EXIF orientation 8.
|
||||
// quadrants-orientation-1.png: same visual content already rotated, EXIF orientation 1.
|
||||
rotated, err := testutils.ReadTestFile("exif_samples/quadrants-orientation-8.png")
|
||||
require.NoError(t, err)
|
||||
normal, err := testutils.ReadTestFile("exif_samples/quadrants-orientation-1.png")
|
||||
require.NoError(t, err)
|
||||
|
||||
rotatedResult, appErr := th.App.AdjustImage(th.Context, bytes.NewReader(rotated))
|
||||
require.Nil(t, appErr)
|
||||
normalResult, appErr := th.App.AdjustImage(th.Context, bytes.NewReader(normal))
|
||||
require.Nil(t, appErr)
|
||||
|
||||
assert.Equal(t, rotatedResult.Bytes(), normalResult.Bytes(),
|
||||
"EXIF-rotated image should produce the same profile picture as the normally-oriented one")
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateUserToRestrictedDomain(t *testing.T) {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 414 B |
Binary file not shown.
|
After Width: | Height: | Size: 413 B |
Reference in New Issue
Block a user