kernel-convolution-visualizer / src /hooks /useImageLoader.ts
mihirmithani
Add Kernel Convolution Visualizer - Phase 1 complete
80bcac8
Raw History Blame
3.88 kB
import { useCallback, useRef, useEffect, useState, useReducer } from 'react'
export function useImageLoader() {
const fileInputRef = useRef<HTMLInputElement>(null)
const loadImage = useCallback(
(file: File): Promise<{ image: HTMLImageElement; imageData: ImageData }> => {
return new Promise((resolve, reject) => {
const url = URL.createObjectURL(file)
const img = new Image()
img.onload = () => {
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
if (!ctx) {
URL.revokeObjectURL(url)
reject(new Error('Failed to get canvas context'))
return
}
ctx.drawImage(img, 0, 0)
const imageData = ctx.getImageData(0, 0, img.width, img.height)
URL.revokeObjectURL(url)
resolve({ image: img, imageData })
}
img.onerror = () => {
URL.revokeObjectURL(url)
reject(new Error('Failed to load image'))
}
img.src = url
})
},
[]
)
const openFileDialog = useCallback(() => {
fileInputRef.current?.click()
}, [])
const handleFileSelect = useCallback(
(event: React.ChangeEvent<HTMLInputElement>, onLoad: (data: { image: HTMLImageElement; imageData: ImageData }) => void) => {
const file = event.target.files?.[0]
if (!file) return
if (!file.type.startsWith('image/')) {
alert('Please select an image file')
return
}
loadImage(file).then(onLoad).catch((error) => {
alert(`Failed to load image: ${error.message}`)
})
},
[loadImage]
)
return {
fileInputRef,
loadImage,
openFileDialog,
handleFileSelect,
}
}
export function useDragAndDrop(onLoad: (image: HTMLImageElement, imageData: ImageData) => void) {
const [isDragging, setIsDragging] = useState(false)
const loadImageFromFile = useCallback(
(file: File): Promise<{ image: HTMLImageElement; imageData: ImageData }> => {
return new Promise((resolve, reject) => {
const url = URL.createObjectURL(file)
const img = new Image()
img.onload = () => {
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
if (!ctx) {
URL.revokeObjectURL(url)
reject(new Error('Failed to get canvas context'))
return
}
ctx.drawImage(img, 0, 0)
const imageData = ctx.getImageData(0, 0, img.width, img.height)
URL.revokeObjectURL(url)
resolve({ image: img, imageData })
}
img.onerror = () => {
URL.revokeObjectURL(url)
reject(new Error('Failed to load image'))
}
img.src = url
})
},
[]
)
const handleDragOver = useCallback((e: React.DragEvent) => {
e.preventDefault()
e.stopPropagation()
setIsDragging(true)
}, [])
const handleDragLeave = useCallback((e: React.DragEvent) => {
e.preventDefault()
e.stopPropagation()
setIsDragging(false)
}, [])
const handleDrop = useCallback(
async (e: React.DragEvent) => {
e.preventDefault()
e.stopPropagation()
setIsDragging(false)
const file = e.dataTransfer.files[0]
if (!file || !file.type.startsWith('image/')) return
try {
const { image, imageData } = await loadImageFromFile(file)
onLoad(image, imageData)
} catch (error) {
alert(`Failed to load image: ${error instanceof Error ? error.message : 'Unknown error'}`)
}
},
[onLoad, loadImageFromFile]
)
return {
handleDragOver,
handleDragLeave,
handleDrop,
isDragging,
}
}