rgb-curve 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +737 -0
- package/dist/index.d.ts +348 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +793 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/utils/curve.ts","../src/utils/constants.ts","../src/hooks/useCanvasInteraction.ts","../src/components/CurveCanvas.tsx","../src/components/ChannelTabs.tsx","../src/hooks/useCurvePoints.ts","../src/components/RGBCurve.tsx"],"sourcesContent":["import { CurvePoint, LUTData, ChannelPoints, Channel } from '../types';\n\n/**\n * Clamp a value between min and max\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Default points for a curve (diagonal line from 0,0 to 255,255)\n */\nexport function getDefaultPoints(): CurvePoint[] {\n return [\n { x: 0, y: 0 },\n { x: 255, y: 255 },\n ];\n}\n\n/**\n * Get default points for all channels\n */\nexport function getDefaultChannelPoints(): ChannelPoints {\n return {\n master: getDefaultPoints(),\n red: getDefaultPoints(),\n green: getDefaultPoints(),\n blue: getDefaultPoints(),\n };\n}\n\n/**\n * Sort points by x coordinate\n */\nexport function sortPoints(points: CurvePoint[]): CurvePoint[] {\n return [...points].sort((a, b) => a.x - b.x);\n}\n\n/**\n * Monotone cubic spline interpolation\n * This ensures the curve doesn't overshoot between control points\n * Based on Fritsch-Carlson method\n */\nexport function monotoneCubicInterpolation(\n points: CurvePoint[],\n x: number\n): number {\n const sorted = sortPoints(points);\n const n = sorted.length;\n\n if (n === 0) return x;\n if (n === 1) return sorted[0].y;\n\n // Handle edge cases\n if (x <= sorted[0].x) return sorted[0].y;\n if (x >= sorted[n - 1].x) return sorted[n - 1].y;\n\n // Find the segment containing x\n let i = 0;\n while (i < n - 1 && sorted[i + 1].x < x) {\n i++;\n }\n\n const x0 = sorted[i].x;\n const x1 = sorted[i + 1].x;\n const y0 = sorted[i].y;\n const y1 = sorted[i + 1].y;\n\n // Calculate slopes\n const dx = x1 - x0;\n const dy = y1 - y0;\n\n if (dx === 0) return y0;\n\n // Calculate tangents using finite differences\n let m0: number, m1: number;\n\n if (i === 0) {\n m0 = dy / dx;\n } else {\n const prevDx = x0 - sorted[i - 1].x;\n const prevDy = y0 - sorted[i - 1].y;\n m0 = prevDx === 0 ? 0 : (dy / dx + prevDy / prevDx) / 2;\n }\n\n if (i === n - 2) {\n m1 = dy / dx;\n } else {\n const nextDx = sorted[i + 2].x - x1;\n const nextDy = sorted[i + 2].y - y1;\n m1 = nextDx === 0 ? 0 : (dy / dx + nextDy / nextDx) / 2;\n }\n\n // Ensure monotonicity\n const slope = dy / dx;\n if (slope === 0) {\n m0 = 0;\n m1 = 0;\n } else {\n const alpha = m0 / slope;\n const beta = m1 / slope;\n\n // Fritsch-Carlson condition for monotonicity\n if (alpha < 0) m0 = 0;\n if (beta < 0) m1 = 0;\n\n const sum = alpha * alpha + beta * beta;\n if (sum > 9) {\n const tau = 3 / Math.sqrt(sum);\n m0 = tau * alpha * slope;\n m1 = tau * beta * slope;\n }\n }\n\n // Hermite interpolation\n const t = (x - x0) / dx;\n const t2 = t * t;\n const t3 = t2 * t;\n\n const h00 = 2 * t3 - 3 * t2 + 1;\n const h10 = t3 - 2 * t2 + t;\n const h01 = -2 * t3 + 3 * t2;\n const h11 = t3 - t2;\n\n const result = h00 * y0 + h10 * dx * m0 + h01 * y1 + h11 * dx * m1;\n\n return clamp(Math.round(result), 0, 255);\n}\n\n/**\n * Catmull-Rom spline interpolation\n * Smoother curves but may overshoot\n */\nexport function catmullRomInterpolation(\n points: CurvePoint[],\n x: number\n): number {\n const sorted = sortPoints(points);\n const n = sorted.length;\n\n if (n === 0) return x;\n if (n === 1) return sorted[0].y;\n\n // Handle edge cases\n if (x <= sorted[0].x) return sorted[0].y;\n if (x >= sorted[n - 1].x) return sorted[n - 1].y;\n\n // Find the segment containing x\n let i = 0;\n while (i < n - 1 && sorted[i + 1].x < x) {\n i++;\n }\n\n // Get 4 points for Catmull-Rom (p0, p1, p2, p3)\n const p0 = sorted[Math.max(0, i - 1)];\n const p1 = sorted[i];\n const p2 = sorted[Math.min(n - 1, i + 1)];\n const p3 = sorted[Math.min(n - 1, i + 2)];\n\n const dx = p2.x - p1.x;\n if (dx === 0) return p1.y;\n\n const t = (x - p1.x) / dx;\n const t2 = t * t;\n const t3 = t2 * t;\n\n // Catmull-Rom matrix multiplication\n const result =\n 0.5 *\n (2 * p1.y +\n (-p0.y + p2.y) * t +\n (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +\n (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);\n\n return clamp(Math.round(result), 0, 255);\n}\n\n/**\n * Generate LUT for a single channel\n */\nexport function generateChannelLUT(\n points: CurvePoint[],\n interpolation: 'monotone' | 'catmullRom' = 'monotone'\n): Uint8Array {\n const lut = new Uint8Array(256);\n const interpolate =\n interpolation === 'monotone'\n ? monotoneCubicInterpolation\n : catmullRomInterpolation;\n\n for (let i = 0; i < 256; i++) {\n lut[i] = interpolate(points, i);\n }\n\n return lut;\n}\n\n/**\n * Generate LUT for all channels\n */\nexport function generateLUT(\n channelPoints: ChannelPoints,\n interpolation: 'monotone' | 'catmullRom' = 'monotone'\n): LUTData {\n return {\n master: generateChannelLUT(channelPoints.master, interpolation),\n red: generateChannelLUT(channelPoints.red, interpolation),\n green: generateChannelLUT(channelPoints.green, interpolation),\n blue: generateChannelLUT(channelPoints.blue, interpolation),\n };\n}\n\n/**\n * Apply LUT to RGB values\n */\nexport function applyLUT(\n r: number,\n g: number,\n b: number,\n lut: LUTData\n): [number, number, number] {\n // Apply individual channel LUTs first\n let newR = lut.red[clamp(r, 0, 255)];\n let newG = lut.green[clamp(g, 0, 255)];\n let newB = lut.blue[clamp(b, 0, 255)];\n\n // Then apply master LUT to all\n newR = lut.master[newR];\n newG = lut.master[newG];\n newB = lut.master[newB];\n\n return [newR, newG, newB];\n}\n\n/**\n * Find the index where a new point should be inserted\n */\nexport function findInsertIndex(points: CurvePoint[], x: number): number {\n const sorted = sortPoints(points);\n for (let i = 0; i < sorted.length; i++) {\n if (sorted[i].x > x) return i;\n }\n return sorted.length;\n}\n\n/**\n * Check if a point is near another point (for hit testing)\n */\nexport function isPointNear(\n p1: { x: number; y: number },\n p2: { x: number; y: number },\n threshold: number\n): boolean {\n const dx = p1.x - p2.x;\n const dy = p1.y - p2.y;\n return Math.sqrt(dx * dx + dy * dy) <= threshold;\n}\n\n/**\n * Get all channels as an array\n */\nexport const CHANNELS: Channel[] = ['master', 'red', 'green', 'blue'];\n\n/**\n * Channel display info\n */\nexport const CHANNEL_INFO: Record<Channel, { label: string; shortLabel: string }> = {\n master: { label: 'Master', shortLabel: 'RGB' },\n red: { label: 'Red', shortLabel: 'R' },\n green: { label: 'Green', shortLabel: 'G' },\n blue: { label: 'Blue', shortLabel: 'B' },\n};\n","import { RGBCurveStyles } from '../types';\n\n/**\n * Default curve width\n */\nexport const DEFAULT_WIDTH = 300;\n\n/**\n * Default curve height\n */\nexport const DEFAULT_HEIGHT = 300;\n\n/**\n * Default styles - Dark theme inspired by Lightroom/Premiere Pro\n */\nexport const DEFAULT_STYLES: Required<RGBCurveStyles> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n gap: '12px',\n padding: '16px',\n backgroundColor: '#1a1a1a',\n borderRadius: '12px',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n },\n canvasWrapper: {\n position: 'relative',\n borderRadius: '8px',\n overflow: 'hidden',\n backgroundColor: '#0d0d0d',\n },\n grid: {\n color: '#2a2a2a',\n lineWidth: 1,\n subdivisions: 4,\n showDiagonal: true,\n diagonalColor: '#333333',\n },\n curve: {\n master: {\n color: '#e0e0e0',\n width: 2,\n shadowColor: 'rgba(255, 255, 255, 0.3)',\n shadowBlur: 4,\n },\n red: {\n color: '#ff6b6b',\n width: 2,\n shadowColor: 'rgba(255, 107, 107, 0.4)',\n shadowBlur: 4,\n },\n green: {\n color: '#51cf66',\n width: 2,\n shadowColor: 'rgba(81, 207, 102, 0.4)',\n shadowBlur: 4,\n },\n blue: {\n color: '#339af0',\n width: 2,\n shadowColor: 'rgba(51, 154, 240, 0.4)',\n shadowBlur: 4,\n },\n },\n controlPoint: {\n radius: 6,\n fill: '#ffffff',\n stroke: '#000000',\n strokeWidth: 2,\n activeFill: '#ffd43b',\n activeStroke: '#000000',\n hoverScale: 1.2,\n },\n tabs: {\n background: '#252525',\n borderRadius: 8,\n gap: 4,\n tab: {\n padding: '8px 16px',\n borderRadius: 6,\n fontSize: 13,\n fontWeight: 500,\n color: '#808080',\n background: 'transparent',\n hoverBackground: '#333333',\n activeColor: '#ffffff',\n activeBackground: '#404040',\n },\n },\n histogram: {\n show: false,\n opacity: 0.3,\n fillColor: '#666666',\n },\n};\n\n/**\n * Channel colors for easy access\n */\nexport const CHANNEL_COLORS = {\n master: '#e0e0e0',\n red: '#ff6b6b',\n green: '#51cf66',\n blue: '#339af0',\n} as const;\n\n/**\n * Hit test threshold for control points (in pixels)\n */\nexport const POINT_HIT_THRESHOLD = 12;\n\n/**\n * Minimum distance between points (in x-axis)\n */\nexport const MIN_POINT_DISTANCE = 5;\n","import { useState, useCallback, useRef, useEffect, MouseEvent } from 'react';\nimport { CurvePoint, Channel } from '../types';\nimport { sortPoints, isPointNear } from '../utils/curve';\nimport { POINT_HIT_THRESHOLD } from '../utils/constants';\n\ninterface UseCanvasInteractionOptions {\n points: CurvePoint[];\n channel: Channel;\n width: number;\n height: number;\n disabled?: boolean;\n onAddPoint: (channel: Channel, point: CurvePoint) => void;\n onRemovePoint: (channel: Channel, index: number) => void;\n onUpdatePoint: (channel: Channel, index: number, point: CurvePoint) => void;\n}\n\ninterface UseCanvasInteractionReturn {\n activePointIndex: number | null;\n hoveredPointIndex: number | null;\n handleMouseDown: (e: MouseEvent<HTMLCanvasElement>) => void;\n handleMouseMove: (e: MouseEvent<HTMLCanvasElement>) => void;\n handleMouseUp: () => void;\n handleMouseLeave: () => void;\n handleDoubleClick: (e: MouseEvent<HTMLCanvasElement>) => void;\n}\n\nexport function useCanvasInteraction(\n options: UseCanvasInteractionOptions\n): UseCanvasInteractionReturn {\n const {\n points,\n channel,\n width,\n height,\n disabled = false,\n onAddPoint,\n onRemovePoint,\n onUpdatePoint,\n } = options;\n\n const [activePointIndex, setActivePointIndex] = useState<number | null>(null);\n const [hoveredPointIndex, setHoveredPointIndex] = useState<number | null>(\n null\n );\n const isDragging = useRef(false);\n\n // Convert canvas coordinates to curve coordinates (0-255)\n const canvasToCurve = useCallback(\n (canvasX: number, canvasY: number): CurvePoint => {\n return {\n x: Math.round((canvasX / width) * 255),\n y: Math.round((1 - canvasY / height) * 255), // Flip Y axis\n };\n },\n [width, height]\n );\n\n // Convert curve coordinates to canvas coordinates\n const curveToCanvas = useCallback(\n (curveX: number, curveY: number): { x: number; y: number } => {\n return {\n x: (curveX / 255) * width,\n y: (1 - curveY / 255) * height, // Flip Y axis\n };\n },\n [width, height]\n );\n\n // Find point at given canvas position\n const findPointAtPosition = useCallback(\n (canvasX: number, canvasY: number): number | null => {\n const sorted = sortPoints(points);\n\n for (let i = 0; i < sorted.length; i++) {\n const canvasPoint = curveToCanvas(sorted[i].x, sorted[i].y);\n if (\n isPointNear(\n { x: canvasX, y: canvasY },\n canvasPoint,\n POINT_HIT_THRESHOLD\n )\n ) {\n return i;\n }\n }\n\n return null;\n },\n [points, curveToCanvas]\n );\n\n // Get canvas position from mouse event\n const getCanvasPosition = useCallback(\n (e: MouseEvent<HTMLCanvasElement>): { x: number; y: number } => {\n const rect = e.currentTarget.getBoundingClientRect();\n return {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n };\n },\n []\n );\n\n const handleMouseDown = useCallback(\n (e: MouseEvent<HTMLCanvasElement>) => {\n if (disabled) return;\n\n const pos = getCanvasPosition(e);\n const pointIndex = findPointAtPosition(pos.x, pos.y);\n\n if (pointIndex !== null) {\n // Start dragging existing point\n setActivePointIndex(pointIndex);\n isDragging.current = true;\n } else {\n // Add new point\n const curvePoint = canvasToCurve(pos.x, pos.y);\n onAddPoint(channel, curvePoint);\n }\n },\n [\n disabled,\n getCanvasPosition,\n findPointAtPosition,\n canvasToCurve,\n channel,\n onAddPoint,\n ]\n );\n\n const handleMouseMove = useCallback(\n (e: MouseEvent<HTMLCanvasElement>) => {\n if (disabled) return;\n\n const pos = getCanvasPosition(e);\n\n if (isDragging.current && activePointIndex !== null) {\n // Dragging a point\n const curvePoint = canvasToCurve(pos.x, pos.y);\n onUpdatePoint(channel, activePointIndex, curvePoint);\n } else {\n // Check for hover\n const pointIndex = findPointAtPosition(pos.x, pos.y);\n setHoveredPointIndex(pointIndex);\n }\n },\n [\n disabled,\n getCanvasPosition,\n activePointIndex,\n canvasToCurve,\n channel,\n onUpdatePoint,\n findPointAtPosition,\n ]\n );\n\n const handleMouseUp = useCallback(() => {\n isDragging.current = false;\n setActivePointIndex(null);\n }, []);\n\n const handleMouseLeave = useCallback(() => {\n isDragging.current = false;\n setActivePointIndex(null);\n setHoveredPointIndex(null);\n }, []);\n\n const handleDoubleClick = useCallback(\n (e: MouseEvent<HTMLCanvasElement>) => {\n if (disabled) return;\n\n const pos = getCanvasPosition(e);\n const pointIndex = findPointAtPosition(pos.x, pos.y);\n\n if (pointIndex !== null) {\n onRemovePoint(channel, pointIndex);\n }\n },\n [disabled, getCanvasPosition, findPointAtPosition, channel, onRemovePoint]\n );\n\n // Handle global mouse up (in case mouse leaves canvas while dragging)\n useEffect(() => {\n const handleGlobalMouseUp = () => {\n isDragging.current = false;\n setActivePointIndex(null);\n };\n\n window.addEventListener('mouseup', handleGlobalMouseUp);\n return () => {\n window.removeEventListener('mouseup', handleGlobalMouseUp);\n };\n }, []);\n\n return {\n activePointIndex,\n hoveredPointIndex,\n handleMouseDown,\n handleMouseMove,\n handleMouseUp,\n handleMouseLeave,\n handleDoubleClick,\n };\n}\n","import {\n useRef,\n useEffect,\n useCallback,\n memo,\n CSSProperties,\n} from 'react';\nimport {\n CurvePoint,\n Channel,\n GridStyle,\n CurveLineStyle,\n ControlPointStyle,\n HistogramStyle,\n} from '../types';\nimport {\n sortPoints,\n monotoneCubicInterpolation,\n catmullRomInterpolation,\n} from '../utils/curve';\nimport { useCanvasInteraction } from '../hooks/useCanvasInteraction';\nimport { DEFAULT_STYLES } from '../utils/constants';\n\ninterface CurveCanvasProps {\n width: number;\n height: number;\n points: CurvePoint[];\n channel: Channel;\n gridStyle?: GridStyle;\n curveStyle?: CurveLineStyle;\n controlPointStyle?: ControlPointStyle;\n histogramStyle?: HistogramStyle;\n histogramData?: Uint8Array;\n wrapperStyle?: CSSProperties;\n disabled?: boolean;\n interpolation?: 'monotone' | 'catmullRom';\n onAddPoint: (channel: Channel, point: CurvePoint) => void;\n onRemovePoint: (channel: Channel, index: number) => void;\n onUpdatePoint: (channel: Channel, index: number, point: CurvePoint) => void;\n}\n\nexport const CurveCanvas = memo(function CurveCanvas({\n width,\n height,\n points,\n channel,\n gridStyle = DEFAULT_STYLES.grid,\n curveStyle,\n controlPointStyle = DEFAULT_STYLES.controlPoint,\n histogramStyle = DEFAULT_STYLES.histogram,\n histogramData,\n wrapperStyle = DEFAULT_STYLES.canvasWrapper,\n disabled = false,\n interpolation = 'monotone',\n onAddPoint,\n onRemovePoint,\n onUpdatePoint,\n}: CurveCanvasProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n\n const {\n activePointIndex,\n hoveredPointIndex,\n handleMouseDown,\n handleMouseMove,\n handleMouseUp,\n handleMouseLeave,\n handleDoubleClick,\n } = useCanvasInteraction({\n points,\n channel,\n width,\n height,\n disabled,\n onAddPoint,\n onRemovePoint,\n onUpdatePoint,\n });\n\n // Get device pixel ratio for sharp rendering\n const dpr = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n\n // Draw the canvas\n const draw = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n // Clear canvas\n ctx.clearRect(0, 0, width * dpr, height * dpr);\n\n // Scale for device pixel ratio\n ctx.save();\n ctx.scale(dpr, dpr);\n\n // Draw histogram if provided\n if (histogramStyle?.show && histogramData) {\n drawHistogram(ctx, histogramData, histogramStyle, width, height);\n }\n\n // Draw grid\n drawGrid(ctx, gridStyle, width, height);\n\n // Draw curve\n const interpolateFn =\n interpolation === 'monotone'\n ? monotoneCubicInterpolation\n : catmullRomInterpolation;\n drawCurve(ctx, points, curveStyle, width, height, interpolateFn);\n\n // Draw control points\n drawControlPoints(\n ctx,\n points,\n controlPointStyle,\n width,\n height,\n activePointIndex,\n hoveredPointIndex\n );\n\n ctx.restore();\n }, [\n width,\n height,\n dpr,\n points,\n gridStyle,\n curveStyle,\n controlPointStyle,\n histogramStyle,\n histogramData,\n interpolation,\n activePointIndex,\n hoveredPointIndex,\n ]);\n\n // Redraw on changes\n useEffect(() => {\n draw();\n }, [draw]);\n\n // Set canvas size\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n\n draw();\n }, [width, height, dpr, draw]);\n\n return (\n <div style={wrapperStyle}>\n <canvas\n ref={canvasRef}\n style={{\n display: 'block',\n cursor: disabled\n ? 'not-allowed'\n : hoveredPointIndex !== null\n ? 'grab'\n : 'crosshair',\n }}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n onDoubleClick={handleDoubleClick}\n />\n </div>\n );\n});\n\n// Helper function to draw the grid\nfunction drawGrid(\n ctx: CanvasRenderingContext2D,\n style: GridStyle,\n width: number,\n height: number\n) {\n const { color, lineWidth, subdivisions, showDiagonal, diagonalColor } = {\n ...DEFAULT_STYLES.grid,\n ...style,\n };\n\n ctx.strokeStyle = color!;\n ctx.lineWidth = lineWidth!;\n\n // Draw vertical and horizontal lines\n const step = width / subdivisions!;\n for (let i = 1; i < subdivisions!; i++) {\n const pos = i * step;\n\n // Vertical line\n ctx.beginPath();\n ctx.moveTo(pos, 0);\n ctx.lineTo(pos, height);\n ctx.stroke();\n\n // Horizontal line\n ctx.beginPath();\n ctx.moveTo(0, pos);\n ctx.lineTo(width, pos);\n ctx.stroke();\n }\n\n // Draw border\n ctx.strokeRect(0.5, 0.5, width - 1, height - 1);\n\n // Draw diagonal (baseline)\n if (showDiagonal) {\n ctx.strokeStyle = diagonalColor!;\n ctx.setLineDash([4, 4]);\n ctx.beginPath();\n ctx.moveTo(0, height);\n ctx.lineTo(width, 0);\n ctx.stroke();\n ctx.setLineDash([]);\n }\n}\n\n// Helper function to draw the histogram\nfunction drawHistogram(\n ctx: CanvasRenderingContext2D,\n data: Uint8Array,\n style: HistogramStyle,\n width: number,\n height: number\n) {\n const { opacity, fillColor } = { ...DEFAULT_STYLES.histogram, ...style };\n\n // Find max value for normalization\n let max = 0;\n for (let i = 0; i < data.length; i++) {\n if (data[i] > max) max = data[i];\n }\n\n if (max === 0) return;\n\n ctx.fillStyle = fillColor!;\n ctx.globalAlpha = opacity!;\n\n const barWidth = width / 256;\n\n for (let i = 0; i < 256; i++) {\n const barHeight = (data[i] / max) * height;\n const x = i * barWidth;\n ctx.fillRect(x, height - barHeight, barWidth, barHeight);\n }\n\n ctx.globalAlpha = 1;\n}\n\n// Helper function to draw the curve\nfunction drawCurve(\n ctx: CanvasRenderingContext2D,\n points: CurvePoint[],\n style: CurveLineStyle | undefined,\n width: number,\n height: number,\n interpolate: (points: CurvePoint[], x: number) => number\n) {\n const sorted = sortPoints(points);\n if (sorted.length === 0) return;\n\n const { color, width: lineWidth, shadowColor, shadowBlur } = {\n ...DEFAULT_STYLES.curve.master,\n ...style,\n };\n\n // Set up shadow\n if (shadowColor && shadowBlur) {\n ctx.shadowColor = shadowColor;\n ctx.shadowBlur = shadowBlur;\n }\n\n ctx.strokeStyle = color!;\n ctx.lineWidth = lineWidth!;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n ctx.beginPath();\n\n // Draw curve by interpolating each x position\n for (let px = 0; px <= width; px++) {\n const curveX = (px / width) * 255;\n const curveY = interpolate(sorted, curveX);\n const canvasY = height - (curveY / 255) * height;\n\n if (px === 0) {\n ctx.moveTo(px, canvasY);\n } else {\n ctx.lineTo(px, canvasY);\n }\n }\n\n ctx.stroke();\n\n // Reset shadow\n ctx.shadowColor = 'transparent';\n ctx.shadowBlur = 0;\n}\n\n// Helper function to draw control points\nfunction drawControlPoints(\n ctx: CanvasRenderingContext2D,\n points: CurvePoint[],\n style: ControlPointStyle,\n width: number,\n height: number,\n activeIndex: number | null,\n hoveredIndex: number | null\n) {\n const sorted = sortPoints(points);\n const {\n radius,\n fill,\n stroke,\n strokeWidth,\n activeFill,\n activeStroke,\n hoverScale,\n } = {\n ...DEFAULT_STYLES.controlPoint,\n ...style,\n };\n\n sorted.forEach((point, index) => {\n const canvasX = (point.x / 255) * width;\n const canvasY = height - (point.y / 255) * height;\n\n const isActive = index === activeIndex;\n const isHovered = index === hoveredIndex;\n const scale = isHovered || isActive ? hoverScale! : 1;\n const currentRadius = radius! * scale;\n\n ctx.beginPath();\n ctx.arc(canvasX, canvasY, currentRadius, 0, Math.PI * 2);\n\n // Fill\n ctx.fillStyle = isActive ? activeFill! : fill!;\n ctx.fill();\n\n // Stroke\n ctx.strokeStyle = isActive ? activeStroke! : stroke!;\n ctx.lineWidth = strokeWidth!;\n ctx.stroke();\n });\n}\n","import { memo, useState, useCallback, CSSProperties } from 'react';\nimport { Channel, TabsStyle } from '../types';\nimport { CHANNELS, CHANNEL_INFO } from '../utils/curve';\nimport { DEFAULT_STYLES, CHANNEL_COLORS } from '../utils/constants';\n\ninterface ChannelTabsProps {\n activeChannel: Channel;\n onChange: (channel: Channel) => void;\n style?: TabsStyle;\n disabled?: boolean;\n}\n\nexport const ChannelTabs = memo(function ChannelTabs({\n activeChannel,\n onChange,\n style,\n disabled = false,\n}: ChannelTabsProps) {\n const [hoveredChannel, setHoveredChannel] = useState<Channel | null>(null);\n\n const mergedStyle = {\n ...DEFAULT_STYLES.tabs,\n ...style,\n tab: {\n ...DEFAULT_STYLES.tabs.tab,\n ...style?.tab,\n },\n };\n\n const containerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: mergedStyle.gap,\n padding: '4px',\n backgroundColor: mergedStyle.background,\n borderRadius: mergedStyle.borderRadius,\n };\n\n const getTabStyle = useCallback(\n (channel: Channel): CSSProperties => {\n const isActive = channel === activeChannel;\n const isHovered = channel === hoveredChannel;\n const tab = mergedStyle.tab!;\n\n return {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n padding: tab.padding,\n borderRadius: tab.borderRadius,\n fontSize: tab.fontSize,\n fontWeight: tab.fontWeight,\n color: isActive ? tab.activeColor : tab.color,\n backgroundColor: isActive\n ? tab.activeBackground\n : isHovered\n ? tab.hoverBackground\n : tab.background,\n border: 'none',\n cursor: disabled ? 'not-allowed' : 'pointer',\n transition: 'all 0.15s ease',\n opacity: disabled ? 0.5 : 1,\n outline: 'none',\n };\n },\n [activeChannel, hoveredChannel, mergedStyle.tab, disabled]\n );\n\n const getIndicatorStyle = (channel: Channel): CSSProperties => {\n const color = CHANNEL_COLORS[channel];\n const isActive = channel === activeChannel;\n\n return {\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: color,\n boxShadow: isActive ? `0 0 6px ${color}` : 'none',\n transition: 'box-shadow 0.15s ease',\n };\n };\n\n const handleClick = useCallback(\n (channel: Channel) => {\n if (!disabled) {\n onChange(channel);\n }\n },\n [disabled, onChange]\n );\n\n return (\n <div style={containerStyle} role=\"tablist\">\n {CHANNELS.map((channel) => (\n <button\n key={channel}\n role=\"tab\"\n aria-selected={channel === activeChannel}\n aria-disabled={disabled}\n style={getTabStyle(channel)}\n onClick={() => handleClick(channel)}\n onMouseEnter={() => setHoveredChannel(channel)}\n onMouseLeave={() => setHoveredChannel(null)}\n >\n <span style={getIndicatorStyle(channel)} />\n <span>{CHANNEL_INFO[channel].label}</span>\n </button>\n ))}\n </div>\n );\n});\n","import { useState, useCallback, useMemo } from 'react';\nimport {\n CurvePoint,\n ChannelPoints,\n Channel,\n LUTData,\n} from '../types';\nimport {\n getDefaultChannelPoints,\n sortPoints,\n generateLUT,\n clamp,\n} from '../utils/curve';\nimport { MIN_POINT_DISTANCE } from '../utils/constants';\n\ninterface UseCurvePointsOptions {\n defaultPoints?: Partial<ChannelPoints>;\n controlledPoints?: Partial<ChannelPoints>;\n interpolation?: 'monotone' | 'catmullRom';\n onChange?: (points: ChannelPoints, lut: LUTData) => void;\n}\n\ninterface UseCurvePointsReturn {\n points: ChannelPoints;\n lut: LUTData;\n addPoint: (channel: Channel, point: CurvePoint) => void;\n removePoint: (channel: Channel, index: number) => void;\n updatePoint: (channel: Channel, index: number, point: CurvePoint) => void;\n resetChannel: (channel: Channel) => void;\n resetAll: () => void;\n setChannelPoints: (channel: Channel, points: CurvePoint[]) => void;\n setAllPoints: (points: Partial<ChannelPoints>) => void;\n}\n\nexport function useCurvePoints(\n options: UseCurvePointsOptions = {}\n): UseCurvePointsReturn {\n const {\n defaultPoints,\n controlledPoints,\n interpolation = 'monotone',\n onChange,\n } = options;\n\n // Merge default points with provided defaults\n const initialPoints = useMemo(() => {\n const defaults = getDefaultChannelPoints();\n if (defaultPoints) {\n return {\n master: defaultPoints.master || defaults.master,\n red: defaultPoints.red || defaults.red,\n green: defaultPoints.green || defaults.green,\n blue: defaultPoints.blue || defaults.blue,\n };\n }\n return defaults;\n }, [defaultPoints]);\n\n const [internalPoints, setInternalPoints] =\n useState<ChannelPoints>(initialPoints);\n\n // Use controlled points if provided, otherwise internal state\n const points = useMemo(() => {\n if (controlledPoints) {\n const defaults = getDefaultChannelPoints();\n return {\n master: controlledPoints.master || defaults.master,\n red: controlledPoints.red || defaults.red,\n green: controlledPoints.green || defaults.green,\n blue: controlledPoints.blue || defaults.blue,\n };\n }\n return internalPoints;\n }, [controlledPoints, internalPoints]);\n\n // Generate LUT from points\n const lut = useMemo(() => {\n return generateLUT(points, interpolation);\n }, [points, interpolation]);\n\n // Helper to update points and trigger onChange\n const updatePoints = useCallback(\n (newPoints: ChannelPoints) => {\n if (!controlledPoints) {\n setInternalPoints(newPoints);\n }\n if (onChange) {\n const newLut = generateLUT(newPoints, interpolation);\n onChange(newPoints, newLut);\n }\n },\n [controlledPoints, onChange, interpolation]\n );\n\n // Add a new point to a channel\n const addPoint = useCallback(\n (channel: Channel, point: CurvePoint) => {\n const channelPoints = points[channel];\n\n // Check if point is too close to existing points\n const sorted = sortPoints(channelPoints);\n for (const p of sorted) {\n if (Math.abs(p.x - point.x) < MIN_POINT_DISTANCE) {\n return; // Don't add if too close\n }\n }\n\n const newChannelPoints = sortPoints([...channelPoints, point]);\n const newPoints = {\n ...points,\n [channel]: newChannelPoints,\n };\n\n updatePoints(newPoints);\n },\n [points, updatePoints]\n );\n\n // Remove a point from a channel (except first and last)\n const removePoint = useCallback(\n (channel: Channel, index: number) => {\n const channelPoints = points[channel];\n\n // Can't remove if only 2 points left\n if (channelPoints.length <= 2) return;\n\n // Sort to find actual index\n const sorted = sortPoints(channelPoints);\n\n // Can't remove first or last point\n if (index === 0 || index === sorted.length - 1) return;\n\n const newChannelPoints = sorted.filter((_, i) => i !== index);\n const newPoints = {\n ...points,\n [channel]: newChannelPoints,\n };\n\n updatePoints(newPoints);\n },\n [points, updatePoints]\n );\n\n // Update a point's position\n const updatePoint = useCallback(\n (channel: Channel, index: number, newPoint: CurvePoint) => {\n const channelPoints = sortPoints(points[channel]);\n const isFirst = index === 0;\n const isLast = index === channelPoints.length - 1;\n\n // Constrain x position for first and last points\n let x = newPoint.x;\n if (isFirst) {\n x = 0;\n } else if (isLast) {\n x = 255;\n } else {\n // Constrain x between adjacent points\n const prevX = channelPoints[index - 1].x + MIN_POINT_DISTANCE;\n const nextX = channelPoints[index + 1].x - MIN_POINT_DISTANCE;\n x = clamp(x, prevX, nextX);\n }\n\n // Clamp y to valid range\n const y = clamp(newPoint.y, 0, 255);\n\n const newChannelPoints = channelPoints.map((p, i) =>\n i === index ? { x, y } : p\n );\n\n const newPoints = {\n ...points,\n [channel]: newChannelPoints,\n };\n\n updatePoints(newPoints);\n },\n [points, updatePoints]\n );\n\n // Reset a single channel\n const resetChannel = useCallback(\n (channel: Channel) => {\n const defaults = getDefaultChannelPoints();\n const newPoints = {\n ...points,\n [channel]: defaults[channel],\n };\n\n updatePoints(newPoints);\n },\n [points, updatePoints]\n );\n\n // Reset all channels\n const resetAll = useCallback(() => {\n const defaults = getDefaultChannelPoints();\n updatePoints(defaults);\n }, [updatePoints]);\n\n // Set points for a specific channel\n const setChannelPoints = useCallback(\n (channel: Channel, newChannelPoints: CurvePoint[]) => {\n const newPoints = {\n ...points,\n [channel]: sortPoints(newChannelPoints),\n };\n\n updatePoints(newPoints);\n },\n [points, updatePoints]\n );\n\n // Set all points at once\n const setAllPoints = useCallback(\n (newPoints: Partial<ChannelPoints>) => {\n const defaults = getDefaultChannelPoints();\n const mergedPoints: ChannelPoints = {\n master: sortPoints(newPoints.master || defaults.master),\n red: sortPoints(newPoints.red || defaults.red),\n green: sortPoints(newPoints.green || defaults.green),\n blue: sortPoints(newPoints.blue || defaults.blue),\n };\n\n updatePoints(mergedPoints);\n },\n [updatePoints]\n );\n\n return {\n points,\n lut,\n addPoint,\n removePoint,\n updatePoint,\n resetChannel,\n resetAll,\n setChannelPoints,\n setAllPoints,\n };\n}\n","import {\n useState,\n useCallback,\n useMemo,\n forwardRef,\n useImperativeHandle,\n CSSProperties,\n} from 'react';\nimport {\n RGBCurveProps,\n RGBCurveRef,\n Channel,\n CurveChangeData,\n ChannelPoints,\n LUTData,\n} from '../types';\nimport { CurveCanvas } from './CurveCanvas';\nimport { ChannelTabs } from './ChannelTabs';\nimport { useCurvePoints } from '../hooks/useCurvePoints';\nimport { DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_STYLES } from '../utils/constants';\n\nexport const RGBCurve = forwardRef<RGBCurveRef, RGBCurveProps>(\n function RGBCurve(\n {\n width = DEFAULT_WIDTH,\n height = DEFAULT_HEIGHT,\n defaultPoints,\n points: controlledPoints,\n defaultChannel = 'master',\n activeChannel: controlledChannel,\n onChange,\n onChannelChange,\n styles = {},\n showTabs = true,\n showHistogram = false,\n histogramData,\n disabled = false,\n className,\n interpolation = 'monotone',\n },\n ref\n ) {\n // Channel state\n const [internalChannel, setInternalChannel] =\n useState<Channel>(defaultChannel);\n const activeChannel = controlledChannel ?? internalChannel;\n\n // Handle onChange to wrap with channel info\n const handlePointsChange = useCallback(\n (newPoints: ChannelPoints, newLut: LUTData) => {\n if (onChange) {\n const data: CurveChangeData = {\n points: newPoints,\n lut: newLut,\n activeChannel,\n };\n onChange(data);\n }\n },\n [onChange, activeChannel]\n );\n\n // Curve points state\n const {\n points,\n lut,\n addPoint,\n removePoint,\n updatePoint,\n resetChannel,\n resetAll,\n setAllPoints,\n } = useCurvePoints({\n defaultPoints,\n controlledPoints,\n interpolation,\n onChange: handlePointsChange,\n });\n\n // Handle channel change\n const handleChannelChange = useCallback(\n (channel: Channel) => {\n if (!controlledChannel) {\n setInternalChannel(channel);\n }\n if (onChannelChange) {\n onChannelChange(channel);\n }\n },\n [controlledChannel, onChannelChange]\n );\n\n // Expose methods via ref\n useImperativeHandle(\n ref,\n () => ({\n reset: resetAll,\n resetChannel,\n getLUT: () => lut,\n getPoints: () => points,\n setPoints: setAllPoints,\n }),\n [resetAll, resetChannel, lut, points, setAllPoints]\n );\n\n // Merge styles\n const mergedStyles = useMemo(() => {\n return {\n container: { ...DEFAULT_STYLES.container, ...styles.container },\n canvasWrapper: {\n ...DEFAULT_STYLES.canvasWrapper,\n ...styles.canvasWrapper,\n },\n grid: { ...DEFAULT_STYLES.grid, ...styles.grid },\n curve: {\n master: { ...DEFAULT_STYLES.curve.master, ...styles.curve?.master },\n red: { ...DEFAULT_STYLES.curve.red, ...styles.curve?.red },\n green: { ...DEFAULT_STYLES.curve.green, ...styles.curve?.green },\n blue: { ...DEFAULT_STYLES.curve.blue, ...styles.curve?.blue },\n },\n controlPoint: {\n ...DEFAULT_STYLES.controlPoint,\n ...styles.controlPoint,\n },\n tabs: {\n ...DEFAULT_STYLES.tabs,\n ...styles.tabs,\n tab: { ...DEFAULT_STYLES.tabs.tab, ...styles.tabs?.tab },\n },\n histogram: { ...DEFAULT_STYLES.histogram, ...styles.histogram },\n };\n }, [styles]);\n\n // Get current channel's curve style\n const currentCurveStyle = mergedStyles.curve[activeChannel];\n\n const containerStyle: CSSProperties = {\n ...mergedStyles.container,\n width: 'fit-content',\n };\n\n return (\n <div style={containerStyle} className={className}>\n {showTabs && (\n <ChannelTabs\n activeChannel={activeChannel}\n onChange={handleChannelChange}\n style={mergedStyles.tabs}\n disabled={disabled}\n />\n )}\n\n <CurveCanvas\n width={width}\n height={height}\n points={points[activeChannel]}\n channel={activeChannel}\n gridStyle={mergedStyles.grid}\n curveStyle={currentCurveStyle}\n controlPointStyle={mergedStyles.controlPoint}\n histogramStyle={{\n ...mergedStyles.histogram,\n show: showHistogram,\n }}\n histogramData={histogramData}\n wrapperStyle={mergedStyles.canvasWrapper}\n disabled={disabled}\n interpolation={interpolation}\n onAddPoint={addPoint}\n onRemovePoint={removePoint}\n onUpdatePoint={updatePoint}\n />\n </div>\n );\n }\n);\n"],"names":["clamp","value","min","max","getDefaultPoints","getDefaultChannelPoints","sortPoints","points","a","b","monotoneCubicInterpolation","x","sorted","n","i","x0","x1","y0","y1","dx","dy","m0","m1","prevDx","prevDy","nextDx","nextDy","slope","alpha","beta","sum","tau","t","t2","t3","h00","h10","h01","h11","result","catmullRomInterpolation","p0","p1","p2","p3","generateChannelLUT","interpolation","lut","interpolate","generateLUT","channelPoints","applyLUT","r","g","newR","newG","newB","isPointNear","threshold","CHANNELS","CHANNEL_INFO","DEFAULT_WIDTH","DEFAULT_HEIGHT","DEFAULT_STYLES","CHANNEL_COLORS","POINT_HIT_THRESHOLD","MIN_POINT_DISTANCE","useCanvasInteraction","options","channel","width","height","disabled","onAddPoint","onRemovePoint","onUpdatePoint","activePointIndex","setActivePointIndex","useState","hoveredPointIndex","setHoveredPointIndex","isDragging","useRef","canvasToCurve","useCallback","canvasX","canvasY","curveToCanvas","curveX","curveY","findPointAtPosition","canvasPoint","getCanvasPosition","e","rect","handleMouseDown","pos","pointIndex","curvePoint","handleMouseMove","handleMouseUp","handleMouseLeave","handleDoubleClick","useEffect","handleGlobalMouseUp","CurveCanvas","memo","gridStyle","curveStyle","controlPointStyle","histogramStyle","histogramData","wrapperStyle","canvasRef","dpr","draw","canvas","ctx","drawHistogram","drawGrid","drawCurve","drawControlPoints","jsx","style","color","lineWidth","subdivisions","showDiagonal","diagonalColor","step","data","opacity","fillColor","barWidth","barHeight","shadowColor","shadowBlur","px","activeIndex","hoveredIndex","radius","fill","stroke","strokeWidth","activeFill","activeStroke","hoverScale","point","index","isActive","currentRadius","ChannelTabs","activeChannel","onChange","hoveredChannel","setHoveredChannel","mergedStyle","containerStyle","getTabStyle","isHovered","tab","getIndicatorStyle","handleClick","jsxs","useCurvePoints","defaultPoints","controlledPoints","initialPoints","useMemo","defaults","internalPoints","setInternalPoints","updatePoints","newPoints","newLut","addPoint","p","newChannelPoints","removePoint","_","updatePoint","newPoint","isFirst","isLast","prevX","nextX","y","resetChannel","resetAll","setChannelPoints","setAllPoints","mergedPoints","RGBCurve","forwardRef","defaultChannel","controlledChannel","onChannelChange","styles","showTabs","showHistogram","className","ref","internalChannel","setInternalChannel","handlePointsChange","handleChannelChange","useImperativeHandle","mergedStyles","_a","_b","_c","_d","_e","currentCurveStyle"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rgb-curve",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A fast, lightweight RGB curve editor component for React - like Lightroom/Premiere Pro color grading",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./styles.css": "./dist/styles.css"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "vite",
|
|
21
|
+
"build": "vite build",
|
|
22
|
+
"build:lib": "vite build --mode lib",
|
|
23
|
+
"preview": "vite preview",
|
|
24
|
+
"typecheck": "tsc --noEmit"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"rgb",
|
|
28
|
+
"curve",
|
|
29
|
+
"color-grading",
|
|
30
|
+
"lightroom",
|
|
31
|
+
"premiere",
|
|
32
|
+
"react",
|
|
33
|
+
"color-correction",
|
|
34
|
+
"lut",
|
|
35
|
+
"photo-editing",
|
|
36
|
+
"video-editing"
|
|
37
|
+
],
|
|
38
|
+
"author": "contact@sounakdas.in",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"react": ">=18.0.0",
|
|
42
|
+
"react-dom": ">=18.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/react": "^18.2.0",
|
|
46
|
+
"@types/react-dom": "^18.2.0",
|
|
47
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
48
|
+
"react": "^18.2.0",
|
|
49
|
+
"react-dom": "^18.2.0",
|
|
50
|
+
"typescript": "^5.3.0",
|
|
51
|
+
"vite": "^5.0.0",
|
|
52
|
+
"vite-plugin-dts": "^3.7.0"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "https://github.com/LittleBoy9/rgb-curve"
|
|
57
|
+
}
|
|
58
|
+
}
|