import React,
{
useState, useEffect
} from
'react'
;
import {
Navbar, Card,
Spinner, Modal,
Button
} from
'react-bootstrap'
;
import { FontAwesomeIcon }
from
'@fortawesome/react-fontawesome'
;
import {
faImage, faDownload,
faUpload, faImage as faImagePlaceholder,
faQuestionCircle,
faHistory
} from
'@fortawesome/free-solid-svg-icons'
;
import
'./Compressor.css'
;
import { compress }
from
'image-conversion'
;
function
CompressorComp() {
const [compressedLink, setCompressedLink] = useState(
''
);
const [originalImage, setOriginalImage] = useState(
null
);
const [originalLink, setOriginalLink] = useState(
''
);
const [uploadImage, setUploadImage] = useState(
false
);
const [outputFileName, setOutputFileName] = useState(
''
);
const [compressionQuality, setCompressionQuality] = useState(0.8);
const [originalSize, setOriginalSize] = useState(0);
const [compressedSize, setCompressedSize] = useState(0);
const [isCompressed, setIsCompressed] = useState(
false
);
const [compressionInProgress, setCompressionInProgress] = useState(
false
);
const [loading, setLoading] = useState(
false
);
const [showHelp, setShowHelp] = useState(
false
);
const [showHistory, setShowHistory] = useState(
false
);
const [compressedHistory, setCompressedHistory] = useState([]);
const [showCompressedImage, setShowCompressedImage] = useState(
false
);
const [modalShow, setModalShow] = useState(
false
);
useEffect(() => {
if
(originalImage) {
setCompressedLink(
''
);
setCompressedSize(0);
setIsCompressed(
false
);
setShowCompressedImage(
false
);
}
}, [originalImage]);
async
function
uploadLink(event) {
const imageFile = event.target.files[0];
setOriginalLink(URL.createObjectURL(imageFile));
setOriginalImage(imageFile);
setOutputFileName(imageFile.name);
setUploadImage(
true
);
setOriginalSize(imageFile.size);
}
async
function
compressImage() {
if
(!originalImage) {
alert(
'Please upload an image first.'
);
return
;
}
try
{
setCompressionInProgress(
true
);
setShowCompressedImage(
false
);
setLoading(
true
);
const compressedImage =
await compress(originalImage, {
quality: compressionQuality,
width: 800,
height: 800,
});
setCompressedLink(URL.createObjectURL(compressedImage));
setCompressedSize(compressedImage.size);
setIsCompressed(
true
);
setCompressedHistory(
[
...compressedHistory,
{
link: compressedLink,
name: outputFileName
}
]);
setTimeout(
() => {
setLoading(
false
);
setShowCompressedImage(
true
);
}, 2000);
}
catch
(error) {
console.error(
'Image compression failed:'
, error);
alert(
'Image compression failed. Please try again.'
);
} finally {
setCompressionInProgress(
false
);
}
}
function
resetApp() {
setOriginalLink(
''
);
setOriginalImage(
null
);
setUploadImage(
false
);
setOutputFileName(
''
);
setCompressionQuality(0.8);
setOriginalSize(0);
setCompressedSize(0);
setIsCompressed(
false
);
setCompressedLink(
''
);
setShowCompressedImage(
false
);
}
function
toggleHelp() {
setShowHelp(!showHelp);
}
function
toggleHistory() {
setShowHistory(!showHistory);
}
return
(
<div className=
"mainContainer"
>
<Navbar className=
"navbar justify-content-between"
bg=
"lig"
variant=
"dark"
>
<div>
<Navbar.Brand className=
"navbar-content"
>
<center>
<FontAwesomeIcon icon={faImage}
className=
"icon"
/>
GeeksforGeeks Image Compressor
</center>
</Navbar.Brand>
</div>
<div className=
"navbar-actions"
>
<FontAwesomeIcon icon={faQuestionCircle}
className=
"help-icon"
onClick={toggleHelp} />
<FontAwesomeIcon icon={faHistory}
className=
"history-icon"
onClick={toggleHistory} />
</div>
</Navbar>
{showHelp && (
<div className=
"help-container"
>
<p>Instructions:</p>
<ul>
<li>
Upload an image using
the
"Upload a file"
button.
</li>
<li>
Adjust the compression
quality using the slider.
</li>
<li>
Press the
"Compress"
button
to start the compression.
</li>
<li>
Download the compressed image
using the
"Download"
button.
</li>
</ul>
</div>
)}
{showHistory && (
<div className=
"history-container"
>
<p>Compressed History:</p>
<ul>
{
compressedHistory.map(
(item, index) => (
<li key={index}>
<a href={item.link}
download={item.name}>
{item.name}
</a>
</li>
))
}
</ul>
</div>
)}
<div className=
"row mt-5"
>
<div className=
"col-xl-3 col-lg-3
col-md-12 col-sm-12"
>
{uploadImage ? (
<Card.Img className=
"image"
variant=
"top"
src={originalLink}
alt=
"Original Image"
/>
) : (
<Card.Img className=
"uploadCard"
variant=
"top"
src={faUpload} alt=
""
/>
)}
<div className=
"d-flex justify-content-center
upload-btn-wrapper"
>
<label htmlFor=
"uploadBtn"
className=
"btn btn-primary"
>
<FontAwesomeIcon icon={faUpload}
className=
"icon"
/>
Upload a file
</label>
<input
type=
"file"
id=
"uploadBtn"
accept=
"image/*"
className=
"mt-2 btn btn-primary w-75"
onChange={(event) => uploadLink(event)} />
</div>
</div>
<div
className=
"col-xl-6 col-lg-6
col-md-12 col-sm-12
d-flex justify-content-center
align-items-baseline"
>
<div>
{outputFileName ? (
<div>
<label htmlFor=
"qualitySlider"
>
Compression Quality:
</label>
<input
id=
"qualitySlider"
type=
"range"
min=
"0.1"
max=
"1"
step=
"0.1"
value={compressionQuality}
onChange={
(event) =>
setCompressionQuality(
parseFloat(event.target.value)
)
}
/>
<div className=
"text-center"
>
Original Size:
{
Math.round(originalSize / 1024)
} KB
<br />
Compressed Size:
{
Math.round(compressedSize / 1024)
} KB
</div>
<div className=
"text-center"
>
{isCompressed &&
!compressionInProgress && (
<div className=
"text-success
compressed-message"
>
Image compressed successfully!
</div>
)}
{
compressionInProgress &&
<div className=
"text-info"
>
Compressing image...
</div>
}
</div>
<div className=
"button-container"
>
{loading ? (
<div className=
"text-info"
>
Loading...
</div>
) : (
<button type=
"button"
className=
"btn btn-success"
onClick={compressImage}>
<FontAwesomeIcon icon={faImage}
className=
"icon"
/>
Compress
</button>
)}
<button type=
"button"
className=
"btn btn-danger ml-3"
onClick={resetApp}>
Reset
</button>
</div>
</div>
) : (
<></>
)}
</div>
</div>
<div className=
"col-xl-3 col-lg-3 col-md-12 col-sm-12"
>
{showCompressedImage ? (
<div>
<Card.Img
className=
"image"
variant=
"top"
src={compressedLink}
alt=
"Compressed Image"
onClick={() => setModalShow(
true
)}
style={{ cursor:
'pointer'
}}
/>
<a href={compressedLink}
download={outputFileName}
className=
"mt-2 btn btn-success
w-75 download-btn"
>
<FontAwesomeIcon icon={faDownload}
className=
"icon"
/>
Download
</a>
<Modal show={modalShow}
onHide={
() =>
setModalShow(
false
)
} size=
"lg"
>
<Modal.Body className=
"text-center"
>
<Card.Img className=
"image"
variant=
"top"
src={compressedLink}
alt=
"Compressed Image"
/>
</Modal.Body>
<Modal.Footer>
<Button variant=
"secondary"
onClick={
() => setModalShow(
false
)
}>
Close
</Button>
</Modal.Footer>
</Modal>
</div>
) : (
<div className=
"d-flex align-items-center
justify-content-center"
>
{
compressionInProgress &&
<Spinner animation=
"border"
variant=
"primary"
/>
}
{
!uploadImage &&
!compressionInProgress && (
<FontAwesomeIcon icon={faImagePlaceholder}
className=
"icon"
size=
"3x"
/>
)
}
</div>
)}
</div>
</div>
</div>
);
}
export
default
CompressorComp;