@@ -68,7 +68,86 @@ const FindFace = ({ imageUrl, onUserDataChange, user }) => {
68
68
} , [ fetchFaceData ] ) ;
69
69
70
70
const handleDownload = ( ) => {
71
- console . log ( 'Download image' ) ;
71
+ const img = new Image ( ) ;
72
+ const proxyUrl = 'https://cors-anywhere-api-liwc.onrender.com/proxy?url=' ;
73
+ const proxiedImageUrl = proxyUrl + imageUrl ;
74
+ img . crossOrigin = 'anonymous' ;
75
+ img . src = proxiedImageUrl ;
76
+
77
+ img . onload = ( ) => {
78
+ const canvas = document . createElement ( 'canvas' ) ;
79
+ const ctx = canvas . getContext ( '2d' , {
80
+ willReadFrequently : true ,
81
+ } ) ;
82
+
83
+ canvas . width = img . width ;
84
+ canvas . height = img . height ;
85
+
86
+ ctx . drawImage ( img , 0 , 0 , img . width , img . height ) ;
87
+
88
+ faceAreas . forEach ( ( area ) => {
89
+ const width = img . width - ( area . leftCol + area . rightCol ) ;
90
+ const height = img . height - ( area . bottomRow + area . topRow ) ;
91
+ const fontSize = Math . max ( width , height ) * 1.1 ;
92
+
93
+ if ( filterType === 'blur' ) {
94
+ const blurredCanvas = document . createElement ( 'canvas' ) ;
95
+ const blurredCtx = blurredCanvas . getContext ( '2d' , {
96
+ willReadFrequently : true ,
97
+ } ) ;
98
+
99
+ blurredCanvas . width = img . width ;
100
+ blurredCanvas . height = img . height ;
101
+
102
+ ctx . drawImage ( img , 0 , 0 , img . width , img . height ) ;
103
+ blurredCtx . filter = 'blur(20px)' ;
104
+ blurredCtx . drawImage ( img , 0 , 0 , img . width , img . height ) ;
105
+
106
+ faceAreas . forEach ( ( area ) => {
107
+ const width = img . width - ( area . leftCol + area . rightCol ) ;
108
+ const height = img . height - ( area . bottomRow + area . topRow ) ;
109
+
110
+ const faceImageData = blurredCtx . getImageData (
111
+ area . leftCol ,
112
+ area . topRow ,
113
+ width ,
114
+ height
115
+ ) ;
116
+
117
+ ctx . putImageData ( faceImageData , area . leftCol , area . topRow ) ;
118
+ } ) ;
119
+ }
120
+
121
+ if ( [ 'emoji' , 'alien' , 'dog' , 'ghost' ] . includes ( filterType ) ) {
122
+ const emojiMap = {
123
+ emoji : '😎' ,
124
+ alien : '👽' ,
125
+ dog : '🐶' ,
126
+ ghost : '🫠' ,
127
+ } ;
128
+
129
+ ctx . font = `${ fontSize } px Arial` ;
130
+ ctx . textAlign = 'center' ;
131
+ ctx . textBaseline = 'middle' ;
132
+ ctx . fillText (
133
+ emojiMap [ filterType ] ,
134
+ area . leftCol + width / 2 ,
135
+ area . topRow + height / 2
136
+ ) ;
137
+ }
138
+ } ) ;
139
+
140
+ canvas . toBlob ( ( blob ) => {
141
+ const link = document . createElement ( 'a' ) ;
142
+ link . href = URL . createObjectURL ( blob ) ;
143
+ link . download = 'filtered_image.png' ;
144
+ link . click ( ) ;
145
+ } , 'image/png' ) ;
146
+ } ;
147
+
148
+ img . onerror = ( ) => {
149
+ console . error ( 'Failed to load image for processing.' ) ;
150
+ } ;
72
151
} ;
73
152
74
153
return (
@@ -87,7 +166,7 @@ const FindFace = ({ imageUrl, onUserDataChange, user }) => {
87
166
) ) }
88
167
</ div >
89
168
< button onClick = { handleDownload } className = "mb-5 download-controls" >
90
- Download Image
169
+ { ' Download Image' }
91
170
</ button >
92
171
< div className = "relative" >
93
172
< img
0 commit comments