Free Online Image Editor

Resize, crop, adjust colors, convert formats, and remove backgrounds. All in your browser — no uploads to servers.

📁
Drop image here or click to upload
Supports PNG, JPEG, WebP, BMP, GIF

Image Editor Features

The Image Editor provides powerful image manipulation tools directly in your browser. No server uploads required — all processing happens locally using HTML5 Canvas technology.

Basic Adjustments

Transform

Color Operations

Advanced

Format Conversion

Jak používat editor obrázků

  1. Nahrajte obrázek kliknutím na tlačítko nahrávání nebo přetažením a puštěním souboru. Podporované formáty zahrnují JPG, PNG, WebP, GIF a BMP. Obrázek je zpracován výhradně ve vašem prohlížeči — bez nahrávání na jakýkoliv server.
  2. Použijte posuvníky úprav pro úpravu jasu, kontrastu a sytosti. Karta filtry poskytuje efekty jedním kliknutím včetně odstínů šedi, sépie, inverze a rozostření — každý s nastavitelnou intenzitou.
  3. Použijte nástroje transformace pro otočení (90° vlevo/vpravo nebo libovolný úhel), překlopení (horizontální/vertikální) nebo oříznutí obrázku na specifický poměr stran nebo vlastní výběr.
  4. Použijte změnu velikosti pro změnu rozměrů obrázku při zachování nebo porušení poměru stran a použijte konverzi formátu pro export jako JPG, PNG nebo WebP.
  5. Klikněte na Download pro uložení upraveného obrázku. Veškeré zpracování je nedestruktivní vůči původnímu souboru — původní soubor můžete kdykoliv znovu nahrát a začít znovu.

Principy úpravy obrázků

Digitální úprava obrázků manipuluje s pixelovými daty pro dosažení vizuálních transformací. Úprava jasu posouvá všechny pixelové hodnoty rovnoměrně směrem ke světlejším nebo tmavším, zatímco úprava kontrastu zvyšuje nebo snižuje rozdíl mezi světlými a tmavými oblastmi. Sytost řídí intenzitu barev — při 0% se obrázek stává odstíny šedi; při vysokých hodnotách se barvy jeví živě zvýrazněné. Tyto tři úpravy tvoří základ většiny pracovních postupů úpravy fotografií, od příležitostných příspěvků na sociálních sítích až po profesionální retušování fotografií.

Filtry aplikují algoritmické transformace napříč celým obrázkem. Odstíny šedi převádějí každý pixel na hodnotu jasu pomocí váženého průměru červeného, zeleného a modrého kanálu (0,299R + 0,587G + 0,114B), který bere v úvahu lidské vizuální vnímání. Sépie aplikuje teplý hnědý tón připomínající vintage fotografie pomocí transformace barevné matice. Inverze vytváří negativní efekt odečtením každé hodnoty kanálu od 255. Rozostření vyhlazuje přechody pixelů pomocí Gaussových nebo boxových konvolučních jader, což snižuje šum a detail — užitečné pro změkčování pozadí nebo vytváření efektů hloubky ostrosti. Každý z těchto filtrů může být aplikován s proměnlivou intenzitou pro dosažení jemných nebo dramatických výsledků.

Změna velikosti obrázku a konverze formátu slouží praktickým účelům. Změna velikosti mění pixelové rozměry obrázku — užitečné pro snížení velikosti souboru pro web, vytváření miniatur nebo přizpůsobení specifickým požadavkům na zobrazení. Při zmenšování používá prohlížeč interpolační algoritmy (typicky bilineární nebo bikubické) pro vzorkování a průměrování pixelů, což může zavést mírné změkčení. Konverze formátu představuje kompromis mezi kompatibilitou a kompresí: JPG nabízí vynikající kompresi pro fotografie, ale je ztrátový a nepodporuje průhlednost, PNG používá bezeztrátovou kompresi a podporuje alfa průhlednost, ale produkuje větší soubory, a WebP poskytuje nadřazené kompresní poměry s bezeztrátovým i ztrátovým režimem plus podporou průhlednosti. Tento editor zpracovává všechny transformace na straně klienta pomocí HTML5 Canvas API, což zajišťuje soukromí a eliminuje čekací doby nahrávání.

Často kladené dotazy

Are my images uploaded to a server?

All image editing is done entirely in your browser using the HTML5 Canvas API. Your images never leave your device, except when you use the "Remove Background" feature which sends the image to our server for processing with Python (PIL). The image is processed in memory and deleted immediately after — nothing is stored.

What image formats are supported?

You can load PNG, JPEG, WebP, GIF (first frame), BMP, and SVG images. You can export your edited images as PNG, JPEG, or WebP. PNG supports transparency and lossless quality, JPEG produces smaller files for photos, and WebP offers the best of both — small file size with transparency support.

How do I crop an image?

Click the "Crop" button in the toolbar to enter crop mode. Then click and drag on the image to select the area you want to keep. Click "Apply Crop" to confirm, or "Cancel" to discard the selection.

Je můj obrázek nahrán na server?
Ne. Veškeré zpracování obrázku — úpravy, filtry, ořezávání, změna velikosti a konverze formátu — probíhá výhradně ve vašem prohlížeči pomocí HTML5 Canvas API. Vaše obrázky nikdy neopustí vaše zařízení.
Jaké formáty obrázků mohu upravovat a exportovat?
Můžete importovat obrázky JPG, PNG, WebP, GIF a BMP. Možnosti exportu zahrnují JPG (nejlepší pro fotografie), PNG (nejlepší pro grafiku s průhledností) a WebP (nejlepší komprese pro webové použití).
Sníží úpravy kvalitu mého obrázku?
Některé operace jsou ze své podstaty ztrátové: export JPG vždy ztrácí určitou kvalitu a zmenšení velikosti snižuje pixelové informace. Filtry a úpravy aplikované v prohlížeči však neovlivňují původní soubor. Znovu nahrajte originál pro čerstvý začátek.
Mohu odstranit pozadí z obrázku?
Ano, nástroj pro odstranění pozadí používá algoritmus založený na barvě pro zprůhlednění vybraných oblastí. U komplexních obrázků s různorodým pozadím se mohou výsledky lišit. Výstupem je PNG s alfa průhledností.

Related Tools

tListener('DOMContentLoaded', function() { canvas = $('ie-canvas'); ctx = canvas.getContext('2d'); overlay = $('ie-overlay'); octx = overlay.getContext('2d'); // Upload var zone = $('ie-upload-zone'); var fileInput = $('ie-file-input'); zone.addEventListener('click', function() { fileInput.click(); }); zone.addEventListener('dragover', function(e) { e.preventDefault(); zone.classList.add('drag-over'); }); zone.addEventListener('dragleave', function() { zone.classList.remove('drag-over'); }); zone.addEventListener('drop', function(e) { e.preventDefault(); zone.classList.remove('drag-over'); if (e.dataTransfer.files.length) loadFile(e.dataTransfer.files[0]); }); fileInput.addEventListener('change', function() { if (fileInput.files.length) loadFile(fileInput.files[0]); }); // Sliders var sliders = ['brightness','contrast','lightness','saturation','blur','opacity','red-ch','green-ch','blue-ch','threshold']; sliders.forEach(function(name) { var el = $('ie-' + name); if (!el) return; el.addEventListener('input', function() { var vEl = $('ie-' + name + '-val'); if (vEl) vEl.textContent = name === 'threshold' ? (parseInt(el.value) === 0 ? 'Off' : el.value) : el.value; render(); }); }); // Toggle buttons setupToggle('ie-gray'); setupToggle('ie-sepia'); setupToggle('ie-invert'); // Transform buttons $('ie-rot-ccw').addEventListener('click', function() { rotateImage(-90); }); $('ie-rot-cw').addEventListener('click', function() { rotateImage(90); }); $('ie-flip-h').addEventListener('click', function() { flipImage('h'); }); $('ie-flip-v').addEventListener('click', function() { flipImage('v'); }); // Resize $('ie-resize-w').addEventListener('input', function() { if (state.aspectLocked) { $('ie-resize-h').value = Math.round(parseInt($('ie-resize-w').value) / state.aspectRatio) || ''; } }); $('ie-resize-h').addEventListener('input', function() { if (state.aspectLocked) { $('ie-resize-w').value = Math.round(parseInt($('ie-resize-h').value) * state.aspectRatio) || ''; } }); $('ie-aspect-lock').addEventListener('click', function() { state.aspectLocked = !state.aspectLocked; this.style.opacity = state.aspectLocked ? '1' : '0.3'; }); $('ie-resize-btn').addEventListener('click', doResize); // Crop $('ie-crop-toggle').addEventListener('click', toggleCrop); $('ie-crop-apply').addEventListener('click', applyCrop); $('ie-crop-cancel').addEventListener('click', cancelCrop); // Canvas mouse events for crop canvas.addEventListener('mousedown', cropMouseDown); canvas.addEventListener('mousemove', cropMouseMove); canvas.addEventListener('mouseup', cropMouseUp); canvas.addEventListener('touchstart', cropTouchStart, {passive:false}); canvas.addEventListener('touchmove', cropTouchMove, {passive:false}); canvas.addEventListener('touchend', cropTouchEnd); // Toolbar $('ie-undo').addEventListener('click', undo); $('ie-redo').addEventListener('click', redo); $('ie-reset').addEventListener('click', resetAll); $('ie-download').addEventListener('click', download); $('ie-new-img').addEventListener('click', function() { state.originalImg = null; state.history = []; state.historyIdx = -1; $('ie-editor').style.display = 'none'; $('ie-upload-zone').style.display = ''; }); // Remove background $('ie-remove-bg').addEventListener('click', removeBackground); // Section collapse document.querySelectorAll('.ie-section-header').forEach(function(hdr) { hdr.addEventListener('click', function() { this.parentElement.classList.toggle('collapsed'); }); }); }); /* ===== Toggle Buttons ===== */ function setupToggle(id) { var btn = $(id); if (!btn) return; btn.addEventListener('click', function() { btn.classList.toggle('active'); render(); }); } /* ===== File Loading ===== */ function loadFile(file) { if (!file || !file.type.startsWith('image/')) return; var reader = new FileReader(); reader.onload = function(e) { var img = new Image(); img.onload = function() { state.originalImg = img; state.rotation = 0; state.flipH = false; state.flipV = false; state.aspectRatio = img.width / img.height; state.history = []; state.historyIdx = -1; pushHistory(); $('ie-upload-zone').style.display = 'none'; $('ie-editor').style.display = ''; $('ie-resize-w').value = img.width; $('ie-resize-h').value = img.height; $('ie-img-info').textContent = file.name; $('ie-img-size').textContent = img.width + ' x ' + img.height; resetSliders(); render(); // Scroll the canvas into view var canvasWrap = document.querySelector('.img-editor-canvas-wrap'); if (canvasWrap) canvasWrap.scrollIntoView({ behavior: 'smooth', block: 'start' }); }; img.src = e.target.result; }; reader.readAsDataURL(file); } function resetSliders() { ['brightness','contrast','lightness','saturation','blur','opacity','red-ch','green-ch','blue-ch'].forEach(function(n) { var el = $('ie-' + n); if (!el) return; el.value = n === 'opacity' ? 100 : 0; var v = $('ie-' + n + '-val'); if (v) v.textContent = n === 'opacity' ? '100' : '0'; }); var th = $('ie-threshold'); if (th) th.value = 0; var thv = $('ie-threshold-val'); if (thv) thv.textContent = 'Off'; ['ie-gray','ie-sepia','ie-invert'].forEach(function(id) { var b = $(id); if (b) b.classList.remove('active'); }); } /* ===== History ===== */ function pushHistory() { if (!state.originalImg) return; var tmpC = document.createElement('canvas'); tmpC.width = state.originalImg.width; tmpC.height = state.originalImg.height; tmpC.getContext('2d').drawImage(state.originalImg, 0, 0); state.history = state.history.slice(0, state.historyIdx + 1); state.history.push(tmpC); if (state.history.length > state.maxHistory) state.history.shift(); state.historyIdx = state.history.length - 1; } function undo() { if (state.historyIdx > 0) { state.historyIdx--; state.originalImg = historyToImg(state.history[state.historyIdx]); $('ie-resize-w').value = state.originalImg.width; $('ie-resize-h').value = state.originalImg.height; $('ie-img-size').textContent = state.originalImg.width + ' x ' + state.originalImg.height; render(); } } function redo() { if (state.historyIdx < state.history.length - 1) { state.historyIdx++; state.originalImg = historyToImg(state.history[state.historyIdx]); $('ie-resize-w').value = state.originalImg.width; $('ie-resize-h').value = state.originalImg.height; $('ie-img-size').textContent = state.originalImg.width + ' x ' + state.originalImg.height; render(); } } function historyToImg(c) { var img = new Image(); img.src = c.toDataURL(); return img; } /* ===== Render Pipeline ===== */ function render() { if (!state.originalImg) return; var w = state.originalImg.width; var h = state.originalImg.height; // Determine display size (fit within 800x600, preserve aspect ratio) var maxW = 800, maxH = 600; var scale = Math.min(maxW / w, maxH / h, 1); var dw = Math.round(w * scale); var dh = Math.round(h * scale); // Set canvas resolution to native image size canvas.width = w; canvas.height = h; // Set only display width; CSS height:auto keeps aspect ratio canvas.style.width = dw + 'px'; canvas.style.height = ''; // Let CSS height:auto handle it overlay.width = w; overlay.height = h; overlay.style.width = dw + 'px'; overlay.style.height = ''; // Build CSS filter string (only add filters when values differ from defaults) var brightness = getVal('ie-brightness', 0); var contrast = getVal('ie-contrast', 0); var lightness = getVal('ie-lightness', 0); var saturation = getVal('ie-saturation', 0); var blur = getVal('ie-blur', 0); var opacity = getVal('ie-opacity', 100) / 100; var gray = $('ie-gray') && $('ie-gray').classList.contains('active'); var sepia = $('ie-sepia') && $('ie-sepia').classList.contains('active'); var invert = $('ie-invert') && $('ie-invert').classList.contains('active'); var filterStr = ''; var parts = []; if (brightness !== 0) parts.push('brightness(' + (1 + brightness / 100) + ')'); if (contrast !== 0) parts.push('contrast(' + (1 + contrast / 100) + ')'); if (lightness !== 0) parts.push('brightness(' + (1 + lightness / 100) + ')'); if (saturation !== 0) parts.push('saturate(' + (1 + saturation / 100) + ')'); if (blur > 0) parts.push('blur(' + blur + 'px)'); if (gray) parts.push('grayscale(1)'); if (sepia) parts.push('sepia(1)'); if (invert) parts.push('invert(1)'); if (parts.length) filterStr = parts.join(' '); ctx.clearRect(0, 0, w, h); ctx.save(); if (filterStr) ctx.filter = filterStr; else ctx.filter = 'none'; ctx.globalAlpha = opacity; // Apply transforms var needTransform = (state.rotation % 360 !== 0) || state.flipH || state.flipV; if (needTransform) { ctx.translate(w / 2, h / 2); if (state.rotation % 360 !== 0) ctx.rotate(state.rotation * Math.PI / 180); if (state.flipH) ctx.scale(-1, 1); if (state.flipV) ctx.scale(1, -1); ctx.drawImage(state.originalImg, -w / 2, -h / 2, w, h); } else { ctx.drawImage(state.originalImg, 0, 0, w, h); } ctx.restore(); // Pixel-level operations (channel mix, threshold) var redCh = getVal('ie-red-ch', 0); var greenCh = getVal('ie-green-ch', 0); var blueCh = getVal('ie-blue-ch', 0); var threshold = getVal('ie-threshold', 0); if (redCh !== 0 || greenCh !== 0 || blueCh !== 0 || threshold > 0) { var imgData = ctx.getImageData(0, 0, w, h); var d = imgData.data; for (var i = 0; i < d.length; i += 4) { if (redCh !== 0) d[i] = clamp(d[i] + redCh * 2.55); if (greenCh !== 0) d[i+1] = clamp(d[i+1] + greenCh * 2.55); if (blueCh !== 0) d[i+2] = clamp(d[i+2] + blueCh * 2.55); if (threshold > 0) { var avg = 0.299 * d[i] + 0.587 * d[i+1] + 0.114 * d[i+2]; var v = avg >= threshold ? 255 : 0; d[i] = v; d[i+1] = v; d[i+2] = v; } } ctx.putImageData(imgData, 0, 0); } } function getVal(id, def) { var el = $(id); return el ? parseFloat(el.value) : def; } function clamp(v) { return v < 0 ? 0 : v > 255 ? 255 : Math.round(v); } /* ===== Transform ===== */ function rotateImage(deg) { state.rotation = (state.rotation + deg) % 360; if (state.rotation < 0) state.rotation += 360; // Swap dimensions for 90/270 if (state.rotation === 90 || state.rotation === 270) { var tmp = state.originalImg.width; // We don't swap original — we handle it in render } pushHistory(); render(); } function flipImage(axis) { if (axis === 'h') state.flipH = !state.flipH; else state.flipV = !state.flipV; pushHistory(); render(); } function doResize() { var nw = parseInt($('ie-resize-w').value); var nh = parseInt($('ie-resize-h').value); if (!nw || !nh || nw < 1 || nh < 1) return; var tmpC = document.createElement('canvas'); tmpC.width = state.originalImg.width; tmpC.height = state.originalImg.height; tmpC.getContext('2d').drawImage(state.originalImg, 0, 0); var outC = document.createElement('canvas'); outC.width = nw; outC.height = nh; outC.getContext('2d').drawImage(tmpC, 0, 0, nw, nh); var img = new Image(); img.onload = function() { state.originalImg = img; state.aspectRatio = nw / nh; $('ie-resize-w').value = nw; $('ie-resize-h').value = nh; $('ie-img-size').textContent = nw + ' x ' + nh; pushHistory(); render(); }; img.src = outC.toDataURL(); } /* ===== Crop ===== */ function toggleCrop() { state.cropMode = !state.cropMode; $('ie-crop-toggle').classList.toggle('active', state.cropMode); $('ie-crop-actions').style.display = state.cropMode ? '' : 'none'; canvas.style.cursor = state.cropMode ? 'crosshair' : 'default'; if (!state.cropMode) { octx.clearRect(0, 0, overlay.width, overlay.height); state.cropStart = null; state.cropEnd = null; } } function getCanvasCoords(e) { var rect = canvas.getBoundingClientRect(); var scaleX = canvas.width / rect.width; var scaleY = canvas.height / rect.height; return { x: Math.round((e.clientX - rect.left) * scaleX), y: Math.round((e.clientY - rect.top) * scaleY) }; } function cropMouseDown(e) { if (!state.cropMode) return; e.preventDefault(); state.cropping = true; state.cropStart = getCanvasCoords(e); state.cropEnd = null; } function cropMouseMove(e) { if (!state.cropMode || !state.cropping) return; state.cropEnd = getCanvasCoords(e); drawCropOverlay(); } function cropMouseUp(e) { if (!state.cropMode || !state.cropping) return; state.cropping = false; if (state.cropEnd) state.cropEnd = getCanvasCoords(e); drawCropOverlay(); } function cropTouchStart(e) { if (!state.cropMode) return; e.preventDefault(); var t = e.touches[0]; state.cropping = true; state.cropStart = getCanvasCoords(t); } function cropTouchMove(e) { if (!state.cropMode || !state.cropping) return; e.preventDefault(); state.cropEnd = getCanvasCoords(e.touches[0]); drawCropOverlay(); } function cropTouchEnd(e) { if (!state.cropMode || !state.cropping) return; state.cropping = false; drawCropOverlay(); } function drawCropOverlay() { octx.clearRect(0, 0, overlay.width, overlay.height); if (!state.cropStart || !state.cropEnd) return; var x = Math.min(state.cropStart.x, state.cropEnd.x); var y = Math.min(state.cropStart.y, state.cropEnd.y); var w = Math.abs(state.cropEnd.x - state.cropStart.x); var h = Math.abs(state.cropEnd.y - state.cropStart.y); // Dim outside octx.fillStyle = 'rgba(0,0,0,0.5)'; octx.fillRect(0, 0, overlay.width, overlay.height); octx.clearRect(x, y, w, h); // Border octx.strokeStyle = '#fff'; octx.lineWidth = Math.max(2, Math.round(canvas.width / 200)); octx.setLineDash([8, 4]); octx.strokeRect(x, y, w, h); octx.setLineDash([]); // Size label octx.fillStyle = '#fff'; octx.font = 'bold ' + Math.max(14, Math.round(canvas.width / 40)) + 'px sans-serif'; octx.fillText(w + ' x ' + h, x + 4, y > 20 ? y - 6 : y + 20); } function applyCrop() { if (!state.cropStart || !state.cropEnd) return; var x = Math.min(state.cropStart.x, state.cropEnd.x); var y = Math.min(state.cropStart.y, state.cropEnd.y); var w = Math.abs(state.cropEnd.x - state.cropStart.x); var h = Math.abs(state.cropEnd.y - state.cropStart.y); if (w < 2 || h < 2) return; var tmpC = document.createElement('canvas'); tmpC.width = state.originalImg.width; tmpC.height = state.originalImg.height; tmpC.getContext('2d').drawImage(state.originalImg, 0, 0); var outC = document.createElement('canvas'); outC.width = w; outC.height = h; outC.getContext('2d').drawImage(tmpC, x, y, w, h, 0, 0, w, h); var img = new Image(); img.onload = function() { state.originalImg = img; state.aspectRatio = w / h; $('ie-resize-w').value = w; $('ie-resize-h').value = h; $('ie-img-size').textContent = w + ' x ' + h; cancelCrop(); pushHistory(); render(); }; img.src = outC.toDataURL(); } function cancelCrop() { state.cropMode = false; state.cropStart = null; state.cropEnd = null; state.cropping = false; $('ie-crop-toggle').classList.remove('active'); $('ie-crop-actions').style.display = 'none'; canvas.style.cursor = 'default'; octx.clearRect(0, 0, overlay.width, overlay.height); } /* ===== Download ===== */ function download() { if (!state.originalImg) return; var format = $('ie-format').value; var ext = format === 'image/png' ? 'png' : format === 'image/jpeg' ? 'jpg' : 'webp'; var quality = format === 'image/png' ? undefined : 0.92; canvas.toBlob(function(blob) { if (!blob) return; var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'edited-image.' + ext; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }, format, quality); } /* ===== Reset ===== */ function resetAll() { if (state.historyIdx > 0) { state.historyIdx = 0; state.originalImg = historyToImg(state.history[0]); state.rotation = 0; state.flipH = false; state.flipV = false; state.aspectRatio = state.originalImg.width / state.originalImg.height; $('ie-resize-w').value = state.originalImg.width; $('ie-resize-h').value = state.originalImg.height; $('ie-img-size').textContent = state.originalImg.width + ' x ' + state.originalImg.height; resetSliders(); render(); } } /* ===== Remove Background ===== */ function removeBackground() { if (!state.originalImg) return; var status = $('ie-rembg-status'); var btn = $('ie-remove-bg'); btn.disabled = true; status.innerHTML = ' Processing...'; // Create blob from current canvas state canvas.toBlob(function(blob) { if (!blob) { status.textContent = 'Error: could not create image'; btn.disabled = false; return; } var fd = new FormData(); fd.append('image', blob, 'image.png'); fetch(REMBG_URL, { method: 'POST', body: fd }) .then(function(res) { if (!res.ok) throw new Error('Server error: ' + res.status); return res.blob(); }) .then(function(resultBlob) { var img = new Image(); img.onload = function() { state.originalImg = img; state.aspectRatio = img.width / img.height; $('ie-resize-w').value = img.width; $('ie-resize-h').value = img.height; $('ie-img-size').textContent = img.width + ' x ' + img.height; pushHistory(); render(); var canvasWrap = document.querySelector('.img-editor-canvas-wrap'); if (canvasWrap) canvasWrap.scrollIntoView({ behavior: 'smooth', block: 'start' }); status.textContent = '✅ Background removed'; btn.disabled = false; }; img.src = URL.createObjectURL(resultBlob); }) .catch(function(err) { status.textContent = '❌ ' + err.message; btn.disabled = false; }); }, 'image/png'); } })();