import React, { useState, useRef, useEffect } from 'react'; import { Upload, Scissors, Download, Image as ImageIcon, Trash2, Layers, RefreshCw, ArrowRight, ArrowDown, Grid, Share2, Zap, Shield, Smartphone, ChevronRight, Menu, X, Layout } from 'lucide-react'; /* ========================================= PART 1: THE LANDING PAGE COMPONENT ========================================= */ const LandingPage = ({ onNavigate }) => { const [isMenuOpen, setIsMenuOpen] = useState(false); return (
{/* Navigation */} {/* Hero Section */}
v1.0 Now Live

Simple tools for
creative people.

Free, fast, and privacy-focused web tools to help you create better content for social media and the web. No sign-up required.

{ e.preventDefault(); onNavigate('splitter'); }} className="inline-flex items-center justify-center px-8 py-4 text-lg font-bold text-white bg-blue-600 rounded-xl hover:bg-blue-700 transition-all shadow-lg shadow-blue-200 active:scale-95 group" > Try Image Splitter
{/* Abstract Background Decoration */}
{/* Tools Grid */}

Our Tools

{/* Active Tool: Image Splitter */} { e.preventDefault(); onNavigate('splitter'); }} className="group relative bg-white rounded-2xl p-6 shadow-sm border border-slate-200 hover:shadow-xl hover:shadow-blue-100 hover:border-blue-200 transition-all duration-300 active:scale-[0.98]" >
New

Image Splitter

Split large images into perfect grids, seamless carousels, or vertical strips for Instagram and Webtoons.

Open Tool
{/* Coming Soon: QR Generator */}
Coming Soon

QR Code Studio

Generate customizable QR codes with logos, colors, and specific data types securely.

{/* Coming Soon: Converter */}
Coming Soon

Format Converter

Quickly convert images between WEBP, PNG, JPG and other formats locally in your browser.

{/* Features / Why Us */}

Privacy First

All image processing happens locally in your browser. Your photos are never uploaded to our servers.

Lightning Fast

No waiting for uploads or downloads. The heavy lifting is done instantly by your device.

Mobile Optimized

Designed for touchscreens. Split and save images directly from your phone to social media.

{/* Footer */}
); }; /* ========================================= PART 2: THE IMAGE SPLITTER APP (Your Code) ========================================= */ const ImageSplitterApp = ({ onBack }) => { const [selectedImage, setSelectedImage] = useState(null); const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 }); const [splitCount, setSplitCount] = useState(3); const [gridRows, setGridRows] = useState(3); const [gridCols, setGridCols] = useState(3); const [scale, setScale] = useState(100); const [splitDirection, setSplitDirection] = useState('horizontal'); const [processedImages, setProcessedImages] = useState([]); const [isProcessing, setIsProcessing] = useState(false); const [fileName, setFileName] = useState("image"); const resultsRef = useRef(null); const handleImageUpload = (event) => { const file = event.target.files[0]; if (file) { setFileName(file.name.split('.')[0]); const reader = new FileReader(); reader.onload = (e) => { const img = new Image(); img.onload = () => { setImageDimensions({ width: img.width, height: img.height }); setSelectedImage(img); setProcessedImages([]); if (navigator.vibrate) navigator.vibrate(20); }; img.src = e.target.result; }; reader.readAsDataURL(file); } }; const handleReset = () => { if (navigator.vibrate) navigator.vibrate(20); setSelectedImage(null); setProcessedImages([]); setSplitCount(3); setGridRows(3); setGridCols(3); setScale(100); }; const handleShare = async (dataUrl, index) => { if (navigator.vibrate) navigator.vibrate(20); try { const res = await fetch(dataUrl); const blob = await res.blob(); const file = new File([blob], `${fileName}_${index}.png`, { type: 'image/png' }); if (navigator.canShare && navigator.canShare({ files: [file] })) { await navigator.share({ files: [file], title: 'Split Image Part', text: `Here is part ${index + 1} of my split image.` }); } else { downloadImage(dataUrl, index); } } catch (error) { console.log("Error sharing:", error); downloadImage(dataUrl, index); } }; const processImage = async () => { if (!selectedImage) return; if (navigator.vibrate) navigator.vibrate(20); setIsProcessing(true); setTimeout(() => { const chunks = []; const { width, height } = imageDimensions; const totalScaledWidth = width * (scale / 100); const totalScaledHeight = height * (scale / 100); let rows, cols; if (splitDirection === 'grid') { rows = gridRows; cols = gridCols; } else if (splitDirection === 'horizontal') { rows = 1; cols = splitCount; } else { rows = splitCount; cols = 1; } const chunkWidthOriginal = width / cols; const chunkHeightOriginal = height / rows; const chunkWidthScaled = totalScaledWidth / cols; const chunkHeightScaled = totalScaledHeight / rows; const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); for (let r = 0; r < rows; r++) { for (let c = 0; c < cols; c++) { canvas.width = chunkWidthScaled; canvas.height = chunkHeightScaled; const srcX = c * chunkWidthOriginal; const srcY = r * chunkHeightOriginal; ctx.drawImage( selectedImage, srcX, srcY, chunkWidthOriginal, chunkHeightOriginal, 0, 0, chunkWidthScaled, chunkHeightScaled ); chunks.push(canvas.toDataURL('image/png')); } } setProcessedImages(chunks); setIsProcessing(false); setTimeout(() => { if (resultsRef.current) { resultsRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' }); if (navigator.vibrate) navigator.vibrate([50, 50, 50]); } }, 100); }, 100); }; const getPostNumber = (index) => { return processedImages.length - index; }; const downloadImage = (dataUrl, index) => { if (navigator.vibrate) navigator.vibrate(20); const postNum = getPostNumber(index); const link = document.createElement('a'); link.href = dataUrl; link.download = `${fileName}_post_${postNum}.png`; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; const getResultGridClass = () => { if (splitDirection === 'grid') { if (gridCols === 2) return 'grid-cols-2'; if (gridCols === 3) return 'grid-cols-3'; if (gridCols >= 4) return 'grid-cols-4'; return 'grid-cols-1'; } if (splitDirection === 'vertical') return 'grid-cols-1 max-w-sm mx-auto'; return 'grid-cols-1 md:grid-cols-2'; }; return (
{/* Navigation for Tool View */}

Image Splitter

Grid • Carousel • Webtoon

{!selectedImage ? (

Tap to upload

Open Camera Roll or Files

) : (
Thumbnail

{fileName}

{imageDimensions.width} × {imageDimensions.height}


{[ { id: 'horizontal', icon: ArrowRight, label: 'Panorama' }, { id: 'vertical', icon: ArrowDown, label: 'Vertical' }, { id: 'grid', icon: Grid, label: 'Grid' } ].map(mode => ( ))}
{splitDirection === 'grid' ? (
{gridRows}
setGridRows(parseInt(e.target.value))} className="w-full h-8 accent-blue-600 touch-pan-x" />
{gridCols}
setGridCols(parseInt(e.target.value))} className="w-full h-8 accent-blue-600 touch-pan-x" />
) : (
{splitCount}
setSplitCount(parseInt(e.target.value))} className="w-full h-8 accent-blue-600 touch-pan-x" />
1 10
)}
{scale}%
setScale(parseInt(e.target.value))} className="w-full h-8 accent-blue-600 touch-pan-x" />
)} {selectedImage && (
Note: Splits are numbered backward (e.g., upload Post #1 first) so they align correctly on your Instagram profile.
)}
{processedImages.length > 0 ? (

Results ({processedImages.length})

{processedImages.map((src, idx) => (
{`Part
{splitDirection === 'horizontal' ? `Slide ${idx + 1}/${processedImages.length}` : `Post #${getPostNumber(idx)}` }
{navigator.share && ( )}
))}
) : ( !selectedImage && (

Select an image to start splitting

) )}
); }; /* ========================================= PART 3: MAIN APP (ROUTER) ========================================= */ const App = () => { const [currentView, setCurrentView] = useState('landing'); useEffect(() => { // Add Favicon const link = document.createElement('link'); link.rel = 'icon'; // Blue Scissors SVG Data URI link.href = `data:image/svg+xml,`; document.head.appendChild(link); // Update Title document.title = "CoolWebTools - Image Splitter & More"; return () => { document.head.removeChild(link); }; }, []); return ( <> {currentView === 'landing' ? ( ) : ( setCurrentView('landing')} /> )} ); }; export default App;