@@ -7,6 +7,7 @@ import * as sharp from "sharp";
77import * as t from "io-ts" ;
88import { UploadResponse } from "@google-cloud/storage/build/src/bucket" ;
99import { Bucket } from "@google-cloud/storage" ;
10+ import { Sharp } from "sharp" ;
1011
1112const imageSize = 500
1213
@@ -49,7 +50,7 @@ export const changeCharacterAvatar = functions.https.onCall(async (data, context
4950
5051 const tempFile = await file ( ) ;
5152
52- await sharp ( Buffer . from ( imageData , "base64" ) )
53+ await ( await cropToRectangle ( sharp ( Buffer . from ( imageData , "base64" ) ) ) )
5354 . resize ( imageSize , imageSize , { fit : "outside" } )
5455 . webp ( )
5556 . toFile ( tempFile . path ) ;
@@ -81,6 +82,27 @@ export const changeCharacterAvatar = functions.https.onCall(async (data, context
8182 } ;
8283} ) ;
8384
85+ const cropToRectangle = async ( image : Sharp ) : Promise < Sharp > => {
86+ const metadata = await image . metadata ( ) ;
87+ const width = metadata . width ;
88+ const height = metadata . height ;
89+
90+ if ( width == undefined || height == undefined ) {
91+ console . error ( "Could not read image width and height" ) ;
92+
93+ return image ;
94+ }
95+
96+ const size = Math . min ( width , height ) ;
97+
98+ return image . extract ( {
99+ top : Math . round ( ( height - size ) / 2 ) ,
100+ left : Math . round ( ( width - size ) / 2 ) ,
101+ width : size ,
102+ height : size ,
103+ } )
104+ }
105+
84106const generateAvatarUrl = ( response : UploadResponse , bucket : Bucket ) : string => {
85107 if ( "FIREBASE_STORAGE_EMULATOR_HOST" in process . env ) {
86108 return response [ 1 ] . mediaLink ;
0 commit comments