Image Editor Using HTML CSS JavaScript With free source code

captcha generator,impossible captcha generator,react captcha generator,select all squares captcha generator,random captcha generator,custom captcha generator,spring boot captcha generator example,captcha generator meme,black metal captcha generator,php captcha generator,ai captcha generator,captcha generator api,captcha generator angular,captcha audio generator,generate captcha android,captcha auto maker,generate captcha aspx,captcha generator using html css and javascript,asp-captcha-generator-display-mode,captcha rules,audio captcha generator,asp.net captcha generator,angular captcha generator,how do i create a captcha,how do you create a captcha code,can you make money with captcha,how do you get a captcha code,discord token generator captcha bypass,botdetect captcha generator,captcha code example,quantum random bit generator captcha,spring boot captcha generator,can captcha be bypassed,captcha generator c#,captcha generator code,captcha generator codeigniter,captcha generation code in python,captcha generation code in java,captcha code generator javascript,captcha code generator in c#,captcha code generator in php,generate captcha code in asp.net core,captcha generator html code,c# captcha generator,captcha generator javascript,captcha generator python,captcha generator in python with source code,captcha generator java,captcha generator php,react-captcha-generator example,captcha explained,get paid by typing captcha,captcha generator free,captcha generator fake,captcha generator facebook,fake captcha generator,facebook captcha generator,fake image captcha generator,free primogems generator no captcha,free robux generator no captcha,fake captcha text generator,how are captcha generated,captcha generator github,google recaptcha generator,golang captcha generator,captcha when using google,github captcha generator,google captcha key generator,google captcha meme generator,why am i getting a google captcha,captcha generator html,heavy metal captcha generator,html captcha image generator,captcha generator in html,homestuck captcha code generator,how to get captcha to work,captcha generator image,captcha generator in php,captcha generator in python,captcha image generator javascript,captcha image generator api,captcha image generator c#,random captcha generator in java,image captcha generator php,java captcha image generator,c# captcha image generator,captcha creator job,captcha generation using javascript,java captcha generator open source,captcha writing jobs,javascript captcha generator,java captcha generator,node js captcha generator,captcha key generator,how much can you earn from captcha,key captcha example,captcha generator online,free captcha generator,recaptcha meme generator,captcha message example,captcha meme generator,is captcha typing legal,captcha generator npm,captcha generator nodejs,captcha generator node,captcha number generator,.net captcha generator,nodejs captcha generator,.net core captcha generator,npm captcha generator,node-captcha-generator,npm node-captcha-generator,robux generator no captcha,captcha generator open source,open source captcha generator,one click captcha generator,online captcha generator,captcha words list,how to get captcha code,captcha picture generator,python captcha generator,captcha test example,captcha generator react,captcha generation in spring boot,quantum random bit generator service captcha,python simple captcha generator,simple captcha example,why do i get captcha every time,captcha test generator,captcha token generator,recaptcha token generator,recaptcha token generator online,recaptcha test generator,text captcha generator,what is the best captcha to use,captcha generator using python,free robux generator captcha verification,captcha types,captcha rating,captcha word generator,word captcha generator,funny captcha generator,2captcha key generator,how 2captcha pay,2captcha prices,is 2captcha legal,2captcha rates,3d captcha,4chan captcha solver github,4chan captcha solver,4chan captcha bypass,human captcha test

Social Links

HTML
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
    <meta charset="utf-8">
    <title>Image Editor JavaScript | CodingAyush</title>
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://unpkg.com/boxicons@2.1.2/css/boxicons.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" />
</head>

<body>
    <div class="container disable">
        <h2>Easy Image Editor</h2>
        <div class="wrapper">
            <div class="editor-panel">
                <div class="filter">
                    <label class="title">Filters</label>
                    <div class="options">
                        <button id="brightness" class="active">Brightness</button>
                        <button id="saturation">Saturation</button>
                        <button id="inversion">Inversion</button>
                        <button id="grayscale">Grayscale</button>
                    </div>
                    <div class="slider">
                        <div class="filter-info">
                            <p class="name">Brighteness</p>
                            <p class="value">100%</p>
                        </div>
                        <input type="range" value="100" min="0" max="200">
                    </div>
                </div>
                <div class="rotate">
                    <label class="title">Rotate & Flip</label>
                    <div class="options">
                        <button id="left"><i class="fa-solid fa-rotate-left"></i></button>
                        <button id="right"><i class="fa-solid fa-rotate-right"></i></button>
                        <button id="horizontal"><i class='bx bx-reflect-vertical'></i></button>
                        <button id="vertical"><i class='bx bx-reflect-horizontal'></i></button>
                    </div>
                </div>
            </div>
            <div class="preview-img">
                <img src="image-placeholder.svg" alt="preview-img">
            </div>
        </div>
        <div class="controls">
            <button class="reset-filter">Reset Filters</button>
            <div class="row">
                <input type="file" class="file-input" accept="image/*" hidden>
                <button class="choose-img">Choose Image</button>
                <button class="save-img">Save Image</button>
            </div>
        </div>
    </div>

    <script src="script.js"></script>

</body>

</html>
CSS
/* Import Google font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  display: flex;
  padding: 10px;
  min-height: 100vh;
  align-items: center;
  justify-content: center;
  background: #11131e;
}
.container{
  width: 850px;
  padding: 30px 35px 35px;
  background: #11131e;
  border-radius: 10px;
  box-shadow: 0 10px 20px rgba(0,0,0);
  color:#fff;
}
.container.disable .editor-panel,
.container.disable .controls .reset-filter,
.container.disable .controls .save-img{
  opacity: 0.5;
  pointer-events: none;
}
.container h2{
  margin-top: -8px;
  font-size: 22px;
  font-weight: 500;
}
.container .wrapper{
  display: flex;
  margin: 20px 0;
  min-height: 335px;
}
.wrapper .editor-panel{
  padding: 15px 20px;
  width: 280px;
  border-radius: 5px;
  border: 1px solid #ccc;
}
.editor-panel .title{
  display: block;
  font-size: 16px;
  margin-bottom: 12px;
}
.editor-panel .options, .controls{
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
.editor-panel button{
  outline: none;
  height: 40px;
  font-size: 14px;
  color: #6C757D;
  background: #fff;
  border-radius: 3px;
  margin-bottom: 8px;
  border: 1px solid #aaa;
}
.editor-panel .filter button{
  width: calc(100% / 2 - 4px);
}
.editor-panel button:hover{
  background: #f5f5f5;
}
.filter button.active{
  color: #fff;
  border-color: #5372F0;
  background: #5372F0;
}
.filter .slider{
  margin-top: 12px;
}
.filter .slider .filter-info{
  display: flex;
  color: #464646;
  font-size: 14px;
  justify-content: space-between;
}
.filter .slider input{
  width: 100%;
  height: 5px;
  accent-color: #5372F0;
}
.editor-panel .rotate{
  margin-top: 17px;
}
.editor-panel .rotate button{
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(100% / 4 - 3px);
}
.rotate .options button:nth-child(3),
.rotate .options button:nth-child(4){
  font-size: 18px;
}
.rotate .options button:active{
  color: #fff;
  background: #5372F0;
  border-color: #5372F0;
}
.wrapper .preview-img{
  flex-grow: 1;
  display: flex;
  overflow: hidden;
  margin-left: 20px;
  border-radius: 5px;
  align-items: center;
  justify-content: center;
}
.preview-img img{
  max-width: 490px;
  max-height: 335px;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.controls button{
  padding: 11px 20px;
  font-size: 14px;
  border-radius: 3px;
  outline: none;
  color: #fff;
  cursor: pointer;
  background: none;
  transition: all 0.3s ease;
  text-transform: uppercase;
}
.controls .reset-filter{
  color: #6C757D;
  border: 1px solid #6C757D;
}
.controls .reset-filter:hover{
  color: #fff;
  background: #6C757D;
}
.controls .choose-img{
  background: #6C757D;
  border: 1px solid #6C757D;
}
.controls .save-img{
  margin-left: 5px;
  background: #5372F0;
  border: 1px solid #5372F0;
}

@media screen and (max-width: 760px) {
  .container{
    padding: 25px;
  }
  .container .wrapper{
    flex-wrap: wrap-reverse;
  }
  .wrapper .editor-panel{
    width: 100%;
  }
  .wrapper .preview-img{
    width: 100%;
    margin: 0 0 15px;
  }
}

@media screen and (max-width: 500px) {
  .controls button{
    width: 100%;
    margin-bottom: 10px;
  }
  .controls .row{
    width: 100%;
  }
  .controls .row .save-img{
    margin-left: 0px;
  }
}
JS
const fileInput = document.querySelector(".file-input"),
    filterOptions = document.querySelectorAll(".filter button"),
    filterName = document.querySelector(".filter-info .name"),
    filterValue = document.querySelector(".filter-info .value"),
    filterSlider = document.querySelector(".slider input"),
    rotateOptions = document.querySelectorAll(".rotate button"),
    previewImg = document.querySelector(".preview-img img"),
    resetFilterBtn = document.querySelector(".reset-filter"),
    chooseImgBtn = document.querySelector(".choose-img"),
    saveImgBtn = document.querySelector(".save-img");

let brightness = "100", saturation = "100", inversion = "0", grayscale = "0";
let rotate = 0, flipHorizontal = 1, flipVertical = 1;

const loadImage = () => {
    let file = fileInput.files[0];
    if (!file) return;
    previewImg.src = URL.createObjectURL(file);
    previewImg.addEventListener("load", () => {
        resetFilterBtn.click();
        document.querySelector(".container").classList.remove("disable");
    });
}
const applyFilter = () => {
    previewImg.style.transform = `rotate(${rotate}deg) scale(${flipHorizontal}, ${flipVertical})`;
    previewImg.style.filter = `brightness(${brightness}%) saturate(${saturation}%) invert(${inversion}%) grayscale(${grayscale}%)`;
}

filterOptions.forEach(option => {
    option.addEventListener("click", () => {
        document.querySelector(".active").classList.remove("active");
        option.classList.add("active");
        filterName.innerText = option.innerText;

        if (option.id === "brightness") {
            filterSlider.max = "200";
            filterSlider.value = brightness;
            filterValue.innerText = `${brightness}%`;
        } else if (option.id === "saturation") {
            filterSlider.max = "200";
            filterSlider.value = saturation;
            filterValue.innerText = `${saturation}%`
        } else if (option.id === "inversion") {
            filterSlider.max = "100";
            filterSlider.value = inversion;
            filterValue.innerText = `${inversion}%`;
        } else {
            filterSlider.max = "100";
            filterSlider.value = grayscale;
            filterValue.innerText = `${grayscale}%`;
        }
    });
});

const updateFilter = () => {
    filterValue.innerText = `${filterSlider.value}%`;
    const selectedFilter = document.querySelector(".filter .active");

    if (selectedFilter.id === "brightness") {
        brightness = filterSlider.value;
    } else if (selectedFilter.id === "saturation") {
        saturation = filterSlider.value;
    } else if (selectedFilter.id === "inversion") {
        inversion = filterSlider.value;
    } else {
        grayscale = filterSlider.value;
    }
    applyFilter();
}

rotateOptions.forEach(option => {
    option.addEventListener("click", () => {
        if (option.id === "left") {
            rotate -= 90;
        } else if (option.id === "right") {
            rotate += 90;
        } else if (option.id === "horizontal") {
            flipHorizontal = flipHorizontal === 1 ? -1 : 1;
        } else {
            flipVertical = flipVertical === 1 ? -1 : 1;
        }
        applyFilter();
    });
});

const resetFilter = () => {
    brightness = "100"; saturation = "100"; inversion = "0"; grayscale = "0";
    rotate = 0; flipHorizontal = 1; flipVertical = 1;
    filterOptions[0].click();
    applyFilter();
}
const saveImage = () => {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    canvas.width = previewImg.naturalWidth;
    canvas.height = previewImg.naturalHeight;

    ctx.filter = `brightness(${brightness}%) saturate(${saturation}%) invert(${inversion}%) grayscale(${grayscale}%)`;
    ctx.translate(canvas.width / 2, canvas.height / 2);
    if (rotate !== 0) {
        ctx.rotate(rotate * Math.PI / 180);
    }
    ctx.scale(flipHorizontal, flipVertical);
    ctx.drawImage(previewImg, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);

    const link = document.createElement("a");
    link.download = "image.jpg";
    link.href = canvas.toDataURL();
    link.click();
}

filterSlider.addEventListener("input", updateFilter);
resetFilterBtn.addEventListener("click", resetFilter);
saveImgBtn.addEventListener("click", saveImage);
fileInput.addEventListener("change", loadImage);
chooseImgBtn.addEventListener("click", () => fileInput.click());

Post a Comment

Previous Post Next Post