Skip to content

Commit 5e92009

Browse files
committed
add download image with applied filter
1 parent 425d1ec commit 5e92009

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

src/components/FindFace/FindFace.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
}
5656

5757
.filter-none {
58-
box-shadow: 0 0 0 1px #72bf64 inset;
58+
box-shadow: 0 0 0 3px #72bf64 inset;
59+
border-radius: 50%;
5960
}
6061
.filter-blur {
6162
backdrop-filter: blur(20px);

src/components/FindFace/FindFace.js

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,86 @@ const FindFace = ({ imageUrl, onUserDataChange, user }) => {
6868
}, [fetchFaceData]);
6969

7070
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+
};
72151
};
73152

74153
return (
@@ -87,7 +166,7 @@ const FindFace = ({ imageUrl, onUserDataChange, user }) => {
87166
))}
88167
</div>
89168
<button onClick={handleDownload} className="mb-5 download-controls">
90-
Download Image
169+
{'Download Image'}
91170
</button>
92171
<div className="relative">
93172
<img

0 commit comments

Comments
 (0)