const Canvas = require('canvas'); const { AttachmentBuilder } = require('discord.js') module.exports = { async execute(interaction){ const file = interaction.options.getAttachment('image'); if(!file.contentType.startsWith("image")) return interaction.reply({ content: "Merci d'envoyer une image", ephemeral: true }); await interaction.deferReply(); const filter = interaction.options.getString('filter'); const canvas = Canvas.createCanvas(500, 500); const ctx = canvas.getContext('2d'); const image = await Canvas.loadImage(file.url); ctx.drawImage(image, 0, 0, canvas.width, canvas.height); switch(filter){ case 'invert': applyInvertEffect(ctx); break; case 'grayscale': applyGrayscaleEffect(ctx); break; case 'sepia': applySepiaEffect(ctx); break; case 'blur': applyBlurEffect(ctx); break; case 'pixelate': applyPixelateEffect(ctx); break; case 'mirror': applyMirrorEffect(ctx); break; case 'rotate': applyRotateEffect(ctx, image); break; case 'brightness': applyBrightnessEffect(ctx); break; case 'vintage': applyVintageEffect(ctx); break; case 'oilpaint': applyOilPaintEffect(ctx, 8, 8); break; case 'watercolor': applyWatercolorEffect(ctx); break; case 'neon': applyNeonEffect(ctx); break; } const remixedImageBuffer = canvas.toBuffer(); const remixedImageAttachment = new AttachmentBuilder(remixedImageBuffer, {name: 'image.png'} ); await interaction.editReply({content: `Voici l'image modifiée :`, files: [remixedImageAttachment]}); } } // Fonction pour appliquer l'effet d'inversion des couleurs function applyInvertEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; // Inversion des couleurs for (let i = 0; i < data.length; i += 4) { data[i] = 255 - data[i]; // Inversion du canal rouge data[i + 1] = 255 - data[i + 1]; // Inversion du canal vert data[i + 2] = 255 - data[i + 2]; // Inversion du canal bleu } ctx.putImageData(imageData, 0, 0); } // Fonction pour appliquer l'effet de conversion en niveaux de gris function applyGrayscaleEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; // Conversion en niveaux de gris for (let i = 0; i < data.length; i += 4) { const average = (data[i] + data[i + 1] + data[i + 2]) / 3; data[i] = average; // Rouge data[i + 1] = average; // Vert data[i + 2] = average; // Bleu } ctx.putImageData(imageData, 0, 0); } // Fonction pour appliquer l'effet de sépia function applySepiaEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; for (let i = 0; i < data.length; i += 4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; data[i] = Math.min(255, (r * 0.393) + (g * 0.769) + (b * 0.189)); data[i + 1] = Math.min(255, (r * 0.349) + (g * 0.686) + (b * 0.168)); data[i + 2] = Math.min(255, (r * 0.272) + (g * 0.534) + (b * 0.131)); } ctx.putImageData(imageData, 0, 0); } // Fonction pour appliquer l'effet de flou function applyBlurEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; const width = ctx.canvas.width; const height = ctx.canvas.height; const blurRadius = 5; for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { let red = 0; let green = 0; let blue = 0; let count = 0; for (let dy = -blurRadius; dy <= blurRadius; dy++) { for (let dx = -blurRadius; dx <= blurRadius; dx++) { const nx = x + dx; const ny = y + dy; if (nx >= 0 && ny >= 0 && nx < width && ny < height) { const index = (ny * width + nx) * 4; red += data[index]; green += data[index + 1]; blue += data[index + 2]; count++; } } } const index = (y * width + x) * 4; data[index] = red / count; data[index + 1] = green / count; data[index + 2] = blue / count; } } ctx.putImageData(imageData, 0, 0); } // Fonction pour appliquer l'effet de pixelisation function applyPixelateEffect(ctx) { const pixelSize = 10; // Taille des pixels for (let y = 0; y < ctx.canvas.height; y += pixelSize) { for (let x = 0; x < ctx.canvas.width; x += pixelSize) { const pixelColor = ctx.getImageData(x, y, pixelSize, pixelSize); ctx.fillStyle = `rgb(${pixelColor.data[0]}, ${pixelColor.data[1]}, ${pixelColor.data[2]})`; ctx.fillRect(x, y, pixelSize, pixelSize); } } } // Fonction pour appliquer l'effet de miroir horizontal function applyMirrorEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; const width = ctx.canvas.width; const height = ctx.canvas.height; for (let y = 0; y < height; y++) { for (let x = 0; x < width / 2; x++) { const indexA = (y * width + x) * 4; const indexB = (y * width + (width - x - 1)) * 4; // Échangez les valeurs de pixel pour le miroir horizontal [data[indexA], data[indexB]] = [data[indexB], data[indexA]]; [data[indexA + 1], data[indexB + 1]] = [data[indexB + 1], data[indexA + 1]]; [data[indexA + 2], data[indexB + 2]] = [data[indexB + 2], data[indexA + 2]]; } } ctx.putImageData(imageData, 0, 0); } // Fonction pour appliquer l'effet de rotation function applyRotateEffect(ctx, image) { ctx.save(); ctx.translate(ctx.canvas.width/2,ctx.canvas.height/2); ctx.rotate(90*Math.PI/180); ctx.drawImage(image,-image.width/2,-image.width/2); ctx.restore(); } // Fonction pour appliquer l'effet de luminosité function applyBrightnessEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; const brightnessFactor = 1.5; // Facteur de luminosité (ajustez selon vos préférences) for (let i = 0; i < data.length; i += 4) { data[i] = Math.min(255, data[i] * brightnessFactor); data[i + 1] = Math.min(255, data[i + 1] * brightnessFactor); data[i + 2] = Math.min(255, data[i + 2] * brightnessFactor); } ctx.putImageData(imageData, 0, 0); } // Fonction pour appliquer l'effet vintage function applyVintageEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; for (let i = 0; i < data.length; i += 4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; data[i] = Math.min(255, r * 1.5); data[i + 1] = Math.min(255, g * 1.2); data[i + 2] = Math.min(255, b * 0.8); } ctx.putImageData(imageData, 0, 0); } // Fonction pour appliquer l'effet de peinture à l'huile (oil paint) function applyOilPaintEffect(ctx, radius, intensity) { var width = ctx.canvas.width, height = ctx.canvas.height, imgData = ctx.getImageData(0, 0, width, height), pixData = imgData.data, pixelIntensityCount = []; destCanvas = ctx.canvas; destCanvas.width = width; destCanvas.height = height; var destImageData = ctx.createImageData(width, height), destPixData = destImageData.data, intensityLUT = [], rgbLUT = []; for (var y = 0; y < height; y++) { intensityLUT[y] = []; rgbLUT[y] = []; for (var x = 0; x < width; x++) { var idx = (y * width + x) * 4, r = pixData[idx], g = pixData[idx + 1], b = pixData[idx + 2], avg = (r + g + b) / 3; intensityLUT[y][x] = Math.round((avg * intensity) / 255); rgbLUT[y][x] = { r: r, g: g, b: b }; } } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixelIntensityCount = []; // Find intensities of nearest pixels within radius. for (var yy = -radius; yy <= radius; yy++) { for (var xx = -radius; xx <= radius; xx++) { if (y + yy > 0 && y + yy < height && x + xx > 0 && x + xx < width) { var intensityVal = intensityLUT[y + yy][x + xx]; if (!pixelIntensityCount[intensityVal]) { pixelIntensityCount[intensityVal] = { val: 1, r: rgbLUT[y + yy][x + xx].r, g: rgbLUT[y + yy][x + xx].g, b: rgbLUT[y + yy][x + xx].b } } else { pixelIntensityCount[intensityVal].val++; pixelIntensityCount[intensityVal].r += rgbLUT[y + yy][x + xx].r; pixelIntensityCount[intensityVal].g += rgbLUT[y + yy][x + xx].g; pixelIntensityCount[intensityVal].b += rgbLUT[y + yy][x + xx].b; } } } } pixelIntensityCount.sort(function (a, b) { return b.val - a.val; }); var curMax = pixelIntensityCount[0].val, dIdx = (y * width + x) * 4; destPixData[dIdx] = ~~ (pixelIntensityCount[0].r / curMax); destPixData[dIdx + 1] = ~~ (pixelIntensityCount[0].g / curMax); destPixData[dIdx + 2] = ~~ (pixelIntensityCount[0].b / curMax); destPixData[dIdx + 3] = 255; } } // change this to ctx to instead put the data on the original canvas ctx.putImageData(destImageData, 0, 0); } // Fonction pour appliquer l'effet aquarelle (watercolor) function applyWatercolorEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; const width = ctx.canvas.width; const height = ctx.canvas.height; const radius = Math.floor(Math.random() * 10)+2; for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const pixelIndex = (y * width + x) * 4; const randomX = x + Math.floor(Math.random() * (radius * 2 + 1)) - radius; const randomY = y + Math.floor(Math.random() * (radius * 2 + 1)) - radius; const neighborIndex = (randomY * width + randomX) * 4; // On copie un pixel voisin au hasard if (randomX >= 0 && randomX < width && randomY >= 0 && randomY < height) { data[pixelIndex] = data[neighborIndex]; data[pixelIndex + 1] = data[neighborIndex + 1]; data[pixelIndex + 2] = data[neighborIndex + 2]; } } } ctx.putImageData(imageData, 0, 0); } // Fonction pour appliquer l'effet néon function applyNeonEffect(ctx) { const imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const data = imageData.data; for (let i = 0; i < data.length; i += 4) { const r = data[i]; const g = data[i + 1]; const b = data[i + 2]; // Augmentez la saturation des couleurs data[i] = r > 128 ? 255 : 0; data[i + 1] = g > 128 ? 255 : 0; data[i + 2] = b > 128 ? 255 : 0; } ctx.putImageData(imageData, 0, 0); }