Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added image converter tool #2393

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Image Converter/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"manifest_version": 1,
"name": "Image Converter",
"version": "1.0",
"description": "A Chrome extension to convert the image's extension.",
"permissions": [
"downloads",
"storage"
],
"action": {
"default_popup": "popup.html"
}
}
130 changes: 130 additions & 0 deletions Image Converter/popup.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: #333;
}

.container {
width: 100%;
max-width: 600px;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
text-align: center;
}

h1 {
color: #4a90e2;
margin-bottom: 20px;
}

form {
display: flex;
flex-direction: column;
align-items: center;
}

input[type="file"] {
display: none;
}

label[for="imageFiles"] {
display: inline-block;
padding: 10px 20px;
margin: 10px 0;
cursor: pointer;
border-radius: 4px;
background: #4a90e2;
color: #fff;
font-size: 16px;
transition: background 0.3s;
}

label[for="imageFiles"]:hover {
background: #357abd;
}

label[for="format"] {
margin: 10px 0;
}

select {
padding: 10px;
border-radius: 4px;
border: 1px solid #ccc;
font-size: 16px;
margin-bottom: 20px;
width: 100%;
max-width: 300px;
}

button {
padding: 10px 20px;
border-radius: 4px;
border: none;
background: #4a90e2;
color: #fff;
font-size: 16px;
cursor: pointer;
transition: background 0.3s;
}

button:hover {
background: #357abd;
}

#preview {
margin-top: 20px;
display: flex;
flex-wrap: wrap;
justify-content: center;
}

.preview-item {
position: relative;
margin: 10px;
text-align: center;
}

.preview-item img {
max-width: 100px;
max-height: 100px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.file-name {
display: block;
font-size: 12px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.image-type {
position: absolute;
top: 5px;
right: 5px;
background-color: white;
padding: 2px 5px;
border-radius: 3px;
font-size: 10px;
}

.delete-icon {
position: absolute;
top: 5px;
left: 5px;
color: red;
font-size: 16px;
cursor: pointer;
}
34 changes: 34 additions & 0 deletions Image Converter/popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Converter Tool</title>
<link rel="stylesheet" href="popup.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha512-Q85xgzayNwtT9vIkzYuhCe9zLsIWDgln/gSpQvxvWGvLMvhhUSSFpQvUhIA+SsrezDjNJzHpDLPUHzgprtq&_csp=no-referrer" crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<body>
<div class="container">
<h1>Image Converter Tool</h1>
<div id="preview"></div>
<form id="uploadForm">
<input type="file" id="imageFiles" name="images" multiple accept="image/*" required>
<label for="imageFiles">Choose Images</label>
<label for="format">Select output format:</label>
<select id="format" name="format" required>
<option value="jpeg">JPEG</option>
<option value="png">PNG</option>
<option value="bmp">BMP</option>
<option value="gif">GIF</option>
<option value="webp">WEBP</option>
<option value="ico">ICO</option>
</select>
<button type="submit">Convert and Download</button>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html2canvas.min.js"></script>
<script src="popup.js"></script>
</body>
</html>
140 changes: 140 additions & 0 deletions Image Converter/popup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
document.getElementById('imageFiles').addEventListener('change', updatePreview);
document.getElementById('uploadForm').addEventListener('submit', async function (event) {
event.preventDefault();
const files = document.getElementById('imageFiles').files;
const format = document.getElementById('format').value;
if (files.length === 0) {
alert('Please upload at least one image.');
return;
}
const convertedFiles = await convertImages(files, format);
if (convertedFiles.length === 1) {
downloadFile(convertedFiles[0].data, convertedFiles[0].filename);
} else {
const zip = new JSZip();
convertedFiles.forEach(file => {
zip.file(file.filename, file.data);
});
const zipBlob = await zip.generateAsync({ type: 'blob' });
downloadFile(zipBlob, 'converted_images.zip');
}
});

async function convertImages(files, format) {
const convertedFiles = [];
for (const file of files) {
const img = await loadImage(file);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
let dataUrl = '';
if (format === 'ico') {
dataUrl = await convertToIco(canvas);
} else {
dataUrl = canvas.toDataURL(`image/${format}`);
}
const blob = await dataUrlToBlob(dataUrl);
const filename = file.name.replace(/\.[^/.]+$/, "") + '.' + format;
convertedFiles.push({ filename, data: blob });
}
return convertedFiles;
}

function loadImage(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = function (e) {
const img = new Image();
img.onload = function () {
resolve(img);
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
});
}

function dataUrlToBlob(dataUrl) {
return fetch(dataUrl).then(res => res.blob());
}

function downloadFile(blob, filename) {
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}

async function convertToIco(canvas) {
const iconSizes = [16, 32, 48, 64, 128, 256];
const iconCanvas = document.createElement('canvas');
const iconCtx = iconCanvas.getContext('2d');
const images = await Promise.all(iconSizes.map(size => {
iconCanvas.width = size;
iconCanvas.height = size;
iconCtx.drawImage(canvas, 0, 0, size, size);
return dataUrlToBlob(iconCanvas.toDataURL('image/png'));
}));
const icoBlob = await createIco(images);
return URL.createObjectURL(icoBlob);
}

async function createIco(images) {
const icoData = [0, 0, 1, 0, images.length];
let imageData = [];
let imageOffset = 6 + (16 * images.length);
for (const image of images) {
const size = await image.size;
icoData.push(image.width, image.height, 0, 0, 1, 32, size, imageOffset);
imageOffset += size;
const buffer = await image.arrayBuffer();
imageData.push(new Uint8Array(buffer));
}
const header = new Uint8Array(icoData.flat());
const icoBlob = new Blob([header, ...imageData], { type: 'image/x-icon' });
return icoBlob;
}

function updatePreview() {
const preview = document.getElementById('preview');
preview.innerHTML = '';
const files = document.getElementById('imageFiles').files;
for (const file of files) {
const reader = new FileReader();
reader.onload = function (e) {
const div = document.createElement('div');
div.className = 'preview-item';

const img = document.createElement('img');
img.src = e.target.result;

const fileName = document.createElement('span');
fileName.className = 'file-name';
fileName.textContent = file.name;

const imageType = document.createElement('span');
imageType.className = 'image-type';
imageType.textContent = file.type.split('/')[1];

const deleteIcon = document.createElement('i');
deleteIcon.className = 'fas fa-times-circle delete-icon'; // Assuming Font Awesome

deleteIcon.addEventListener('click', () => {
preview.removeChild(div);
const updatedFiles = Array.from(files).filter(f => f !== file);
document.getElementById('imageFiles').files = updatedFiles;
});

div.appendChild(img);
div.appendChild(fileName);
div.appendChild(imageType);
div.appendChild(deleteIcon);
preview.appendChild(div);
};
reader.readAsDataURL(file);
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Happy coding!
| [Image Comparison Slider](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image%20Comparison%20Slider) | [Image Compressor](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image%20Compressor) | [Image Downlaoder](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image%20Downlaoder) | [Image Editor](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image%20Editor) | [Image Gallery](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image%20Gallery) |
| [Image To PDF](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image%20To%20PDF) | [Image To Text](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image%20To%20Text) | [Image2Link](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image2Link) | [Important Text Highlighter](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Important%20Text%20Highlighter) | [Infix Prefix Postfix Calculator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Infix%20Prefix%20Postfix%20Calculator) |
| [Instragram Post Download](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Instragram%20Post%20Download) | [Intellect Quest](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Intellect%20Quest) | [Interactive Learning Aid JS Extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Interactive%20Learning%20Aid%20JS%20Extension) | [Interactive Periodic Table](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Interactive%20Periodic%20Table) | [Interactive Periodic Table Extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Interactive%20Periodic%20Table%20Extension) |
| [Internet Extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Internet%20Extension) | [Interplanetary Weight Calculator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Interplanetary%20Weight%20Calculator) | [Invoice Generator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Invoice%20Generator) | [ISBN Validator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/ISBN%20Validator) | [IT Income Tax Calculator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/IT%20Income%20Tax%20Calculator) |
| [Internet Extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Internet%20Extension) | [Image Converter](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Image%20Converter) | [Interplanetary Weight Calculator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Interplanetary%20Weight%20Calculator) | [Invoice Generator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Invoice%20Generator) | [ISBN Validator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/ISBN%20Validator) | [IT Income Tax Calculator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/IT%20Income%20Tax%20Calculator) |
| [Java Code Editor](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Java%20Code%20Editor) | [Jokes Xpress Extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Jokes%20Xpress%20Extension) | [JSON Editor](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/JSON%20Editor) | [Kanye Quote Extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Kanye%20Quote%20Extension) | [Keyboard Shortcut](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Keyboard%20Shortcut) |
| [Knife Thrower](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Knife%20Thrower) | [Knox Meeting extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Knox%20Meeting%20extension) | [Language Translator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Language%20Translator) | [Language Translator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Language%20Translator) | [LCM and HCF Extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/LCM%20and%20HCF%20Extension) |
| [Leetcode POTD Generator](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Leetcode%20POTD%20Generator) | [LeetHub](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/LeetHub) | [Length Converter JS Extension](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Length%20Converter%20JS%20Extension) | [Library Detector](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/Library%20Detector) | [LightHouse](https://github.com/Sulagna-Dutta-Roy/GGExtensions/tree/master/LightHouse) |
Expand Down
Loading