🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

rgb-curve

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rgb-curve

A fast, lightweight RGB curve editor component for React - like Lightroom/Premiere Pro color grading

latest
Source
npmnpm
Version
1.0.2
Version published
Maintainers
1
Created
Source

🎨 RGB Curve

A fast, lightweight RGB curve editor for React

Professional color grading curves like Adobe Lightroom, Premiere Pro, and Photoshop

npm version npm bundle size npm downloads license TypeScript


Demo

Demo

🚀 Live Demo📖 Full Docs🌐 Website



✨ Features

🎛️ Professional Grade

  • 4 channels: Master (RGB), Red, Green, Blue
  • Smooth cubic spline interpolation
  • Returns control points + 256-value LUT for pixel processing

🎨 Beautiful UI

  • Dark theme by default (Lightroom/Premiere Pro inspired)
  • Fully customizable via JSON style props
  • Smooth animations and interactions

⚡ Fast & Lightweight

  • Zero dependencies (only React as peer dep)
  • ~6KB gzipped
  • Optimized canvas rendering

🔧 Developer Friendly

  • Full TypeScript support
  • Comprehensive API
  • Extensive documentation


📦 Installation

Choose your preferred package manager:

# npm
npm install rgb-curve

# yarn
yarn add rgb-curve

# pnpm
pnpm add rgb-curve

# bun
bun add rgb-curve


� Table of Contents



�🚀 Quick Start

Get up and running in seconds:

import { RGBCurve } from 'rgb-curve';

function App() {
  return (
    <RGBCurve
      onChange={({ points, lut, activeChannel }) => {
        console.log('Control points:', points);
        console.log('LUT:', lut);
        console.log('Active channel:', activeChannel);
      }}
    />
  );
}


🎮 How to Use

ActionDescription
Click on curveAdd a new control point
Drag a pointAdjust the curve shape
Double-click a pointRemove the control point
Click tabsSwitch between Master/R/G/B channels


📖 Documentation

Props API

PropTypeDefaultDescription
widthnumber300Width of the curve editor in pixels
heightnumber300Height of the curve editor in pixels
defaultPointsPartial<ChannelPoints>Initial control points for each channel
pointsPartial<ChannelPoints>Controlled points (makes component controlled)
defaultChannelChannel'master'Initial active channel
activeChannelChannelControlled active channel
onChange(data: CurveChangeData) => voidCallback when curve changes
onChannelChange(channel: Channel) => voidCallback when channel changes
stylesRGBCurveStylesCustom styles (see Styling section)
showTabsbooleantrueShow/hide channel tabs
showHistogrambooleanfalseShow/hide histogram overlay
histogramDataUint8ArrayHistogram data (256 values)
disabledbooleanfalseDisable all interactions
classNamestringCSS class for container
interpolation'monotone' | 'catmullRom''monotone'Curve interpolation algorithm

onChange Data Structure

The onChange callback receives an object with:

interface CurveChangeData {
  // Control points for all channels
  points: {
    master: CurvePoint[];
    red: CurvePoint[];
    green: CurvePoint[];
    blue: CurvePoint[];
  };

  // Look-Up Table (256 values per channel) for pixel processing
  lut: {
    master: Uint8Array;
    red: Uint8Array;
    green: Uint8Array;
    blue: Uint8Array;
  };

  // Currently active channel
  activeChannel: 'master' | 'red' | 'green' | 'blue';
}

interface CurvePoint {
  x: number; // Input value: 0-255
  y: number; // Output value: 0-255
}

Ref Methods

Access component methods using React refs:

import { useRef } from 'react';
import { RGBCurve, RGBCurveRef } from 'rgb-curve';

function App() {
  const curveRef = useRef<RGBCurveRef>(null);

  return (
    <>
      <RGBCurve ref={curveRef} />

      <button onClick={() => curveRef.current?.reset()}>
        Reset All Channels
      </button>

      <button onClick={() => curveRef.current?.resetChannel('red')}>
        Reset Red Channel
      </button>

      <button onClick={() => {
        const lut = curveRef.current?.getLUT();
        console.log('Current LUT:', lut);
      }}>
        Get LUT Data
      </button>
    </>
  );
}

Available Methods

MethodDescription
reset()Reset all channels to default (diagonal line)
resetChannel(channel)Reset a specific channel
getLUT()Get current LUT data for all channels
getPoints()Get current control points for all channels
setPoints(points)Set control points programmatically


🎨 Styling

The component comes with a beautiful dark theme by default. You can customize every aspect using the styles prop.

Complete Styles Example

<RGBCurve
  styles={{
    // Container wrapper
    container: {
      background: '#1a1a1a',
      borderRadius: 12,
      padding: 16,
    },

    // Canvas wrapper
    canvasWrapper: {
      borderRadius: 8,
      overflow: 'hidden',
      background: '#0d0d0d',
    },

    // Grid lines
    grid: {
      color: '#2a2a2a',
      lineWidth: 1,
      subdivisions: 4,
      showDiagonal: true,
      diagonalColor: '#333333',
    },

    // Curve lines (per channel)
    curve: {
      master: {
        color: '#e0e0e0',
        width: 2,
        shadowColor: 'rgba(255, 255, 255, 0.3)',
        shadowBlur: 4,
      },
      red: {
        color: '#ff6b6b',
        width: 2,
        shadowColor: 'rgba(255, 107, 107, 0.4)',
        shadowBlur: 4,
      },
      green: {
        color: '#51cf66',
        width: 2,
        shadowColor: 'rgba(81, 207, 102, 0.4)',
        shadowBlur: 4,
      },
      blue: {
        color: '#339af0',
        width: 2,
        shadowColor: 'rgba(51, 154, 240, 0.4)',
        shadowBlur: 4,
      },
    },

    // Control points
    controlPoint: {
      radius: 6,
      fill: '#ffffff',
      stroke: '#000000',
      strokeWidth: 2,
      activeFill: '#ffd43b',
      activeStroke: '#000000',
      hoverScale: 1.2,
    },

    // Channel tabs
    tabs: {
      background: '#252525',
      borderRadius: 8,
      gap: 4,
      tab: {
        padding: '8px 16px',
        borderRadius: 6,
        fontSize: 13,
        fontWeight: 500,
        color: '#808080',
        background: 'transparent',
        hoverBackground: '#333333',
        activeColor: '#ffffff',
        activeBackground: '#404040',
      },
    },

    // Histogram (if enabled)
    histogram: {
      show: true,
      opacity: 0.3,
      fillColor: '#666666',
    },
  }}
/>

Style Reference

Container Style

container: CSSProperties

Standard React CSS properties for the outer container.

styles={{
  container: {
    background: 'linear-gradient(135deg, #1a1a2e, #16213e)',
    borderRadius: 16,
    padding: 20,
    boxShadow: '0 10px 40px rgba(0,0,0,0.5)',
  }
}}

Canvas Wrapper Style

canvasWrapper: CSSProperties

Standard React CSS properties for the canvas container.

styles={{
  canvasWrapper: {
    borderRadius: 12,
    border: '1px solid #333',
    overflow: 'hidden',
  }
}}

Grid Style

interface GridStyle {
  color?: string;        // Grid line color
  lineWidth?: number;    // Grid line width
  subdivisions?: number; // Number of grid divisions (default: 4)
  showDiagonal?: boolean; // Show diagonal baseline
  diagonalColor?: string; // Diagonal line color
}
styles={{
  grid: {
    color: '#333333',
    lineWidth: 1,
    subdivisions: 4,
    showDiagonal: true,
    diagonalColor: '#444444',
  }
}}

Curve Style

interface CurveLineStyle {
  color?: string;       // Curve line color
  width?: number;       // Curve line width
  shadowColor?: string; // Glow effect color
  shadowBlur?: number;  // Glow blur radius
}
styles={{
  curve: {
    master: { color: '#ffffff', width: 2 },
    red: { color: '#ff0000', width: 2, shadowColor: 'rgba(255,0,0,0.5)', shadowBlur: 8 },
    green: { color: '#00ff00', width: 2 },
    blue: { color: '#0088ff', width: 3 },
  }
}}

Control Point Style

interface ControlPointStyle {
  radius?: number;       // Point radius
  fill?: string;         // Point fill color
  stroke?: string;       // Point border color
  strokeWidth?: number;  // Point border width
  activeFill?: string;   // Fill when dragging
  activeStroke?: string; // Border when dragging
  hoverScale?: number;   // Scale on hover (1.2 = 120%)
}
styles={{
  controlPoint: {
    radius: 8,
    fill: '#ffffff',
    stroke: '#000000',
    strokeWidth: 2,
    activeFill: '#ffcc00',
    activeStroke: '#000000',
    hoverScale: 1.3,
  }
}}

Tabs Style

interface TabsStyle {
  background?: string;    // Tabs container background
  borderRadius?: number;  // Tabs container border radius
  gap?: number;           // Gap between tabs
  tab?: {
    padding?: string;
    borderRadius?: number;
    fontSize?: number;
    fontWeight?: number | string;
    color?: string;           // Inactive tab text color
    background?: string;      // Inactive tab background
    hoverBackground?: string; // Hover background
    activeColor?: string;     // Active tab text color
    activeBackground?: string; // Active tab background
  };
}
styles={{
  tabs: {
    background: '#1a1a1a',
    borderRadius: 10,
    gap: 8,
    tab: {
      padding: '10px 20px',
      borderRadius: 8,
      fontSize: 14,
      fontWeight: 600,
      color: '#666666',
      background: 'transparent',
      hoverBackground: '#2a2a2a',
      activeColor: '#ffffff',
      activeBackground: '#3a3a3a',
    },
  }
}}

Histogram Style

interface HistogramStyle {
  show?: boolean;     // Show/hide histogram
  opacity?: number;   // Histogram opacity (0-1)
  fillColor?: string; // Histogram bar color
}
<RGBCurve
  showHistogram={true}
  histogramData={myHistogramData} // Uint8Array of 256 values
  styles={{
    histogram: {
      opacity: 0.4,
      fillColor: '#888888',
    }
  }}
/>


🌈 Theme Examples

Light Theme

<RGBCurve
  styles={{
    container: {
      background: '#f5f5f5',
      borderRadius: 12,
      padding: 16,
    },
    canvasWrapper: {
      background: '#ffffff',
      borderRadius: 8,
      border: '1px solid #e0e0e0',
    },
    grid: {
      color: '#e0e0e0',
      diagonalColor: '#d0d0d0',
    },
    curve: {
      master: { color: '#333333', width: 2 },
      red: { color: '#e53935', width: 2 },
      green: { color: '#43a047', width: 2 },
      blue: { color: '#1e88e5', width: 2 },
    },
    controlPoint: {
      fill: '#ffffff',
      stroke: '#333333',
      activeFill: '#ffca28',
    },
    tabs: {
      background: '#e0e0e0',
      tab: {
        color: '#666666',
        activeColor: '#000000',
        activeBackground: '#ffffff',
        hoverBackground: '#eeeeee',
      },
    },
  }}
/>

Neon Theme

<RGBCurve
  styles={{
    container: {
      background: '#0a0a0a',
      borderRadius: 16,
      padding: 20,
      border: '1px solid #333',
    },
    canvasWrapper: {
      background: '#000000',
      borderRadius: 12,
    },
    grid: {
      color: '#1a1a1a',
      diagonalColor: '#2a2a2a',
    },
    curve: {
      master: {
        color: '#00ffff',
        width: 2,
        shadowColor: '#00ffff',
        shadowBlur: 10
      },
      red: {
        color: '#ff0066',
        width: 2,
        shadowColor: '#ff0066',
        shadowBlur: 10
      },
      green: {
        color: '#00ff66',
        width: 2,
        shadowColor: '#00ff66',
        shadowBlur: 10
      },
      blue: {
        color: '#0066ff',
        width: 2,
        shadowColor: '#0066ff',
        shadowBlur: 10
      },
    },
    controlPoint: {
      radius: 5,
      fill: '#ffffff',
      stroke: '#00ffff',
      strokeWidth: 2,
      activeFill: '#ff00ff',
      hoverScale: 1.4,
    },
    tabs: {
      background: '#111111',
      tab: {
        color: '#666666',
        activeColor: '#00ffff',
        activeBackground: '#1a1a1a',
        hoverBackground: '#1a1a1a',
      },
    },
  }}
/>

Minimal Theme

<RGBCurve
  styles={{
    container: {
      background: 'transparent',
      padding: 0,
    },
    canvasWrapper: {
      background: '#1a1a1a',
      borderRadius: 4,
    },
    grid: {
      color: '#252525',
      showDiagonal: false,
      subdivisions: 2,
    },
    curve: {
      master: { color: '#888', width: 1.5, shadowBlur: 0 },
      red: { color: '#f66', width: 1.5, shadowBlur: 0 },
      green: { color: '#6f6', width: 1.5, shadowBlur: 0 },
      blue: { color: '#66f', width: 1.5, shadowBlur: 0 },
    },
    controlPoint: {
      radius: 4,
      fill: '#fff',
      stroke: 'transparent',
      strokeWidth: 0,
      hoverScale: 1.5,
    },
    tabs: {
      background: 'transparent',
      gap: 8,
      tab: {
        padding: '6px 12px',
        background: 'transparent',
        hoverBackground: '#252525',
        activeBackground: '#333',
      },
    },
  }}
/>


🖼️ Applying LUT to Images

The LUT (Look-Up Table) returned by onChange enables fast, real-time pixel processing:

import { RGBCurve, applyLUT, LUTData } from 'rgb-curve';

function ImageEditor() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const originalImageData = useRef<ImageData | null>(null);

  const handleCurveChange = ({ lut }: { lut: LUTData }) => {
    const canvas = canvasRef.current;
    if (!canvas || !originalImageData.current) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // Clone original data
    const imageData = new ImageData(
      new Uint8ClampedArray(originalImageData.current.data),
      originalImageData.current.width,
      originalImageData.current.height
    );

    // Apply LUT to each pixel
    const data = imageData.data;
    for (let i = 0; i < data.length; i += 4) {
      const [r, g, b] = applyLUT(data[i], data[i + 1], data[i + 2], lut);
      data[i] = r;
      data[i + 1] = g;
      data[i + 2] = b;
    }

    ctx.putImageData(imageData, 0, 0);
  };

  return (
    <div>
      <RGBCurve onChange={handleCurveChange} />
      <canvas ref={canvasRef} />
    </div>
  );
}


🔧 Utility Exports

The package exports several utilities for advanced use cases:

import {
  // Components
  RGBCurve,
  CurveCanvas,
  ChannelTabs,

  // Hooks
  useCurvePoints,
  useCanvasInteraction,

  // Utilities
  generateLUT,
  generateChannelLUT,
  applyLUT,
  getDefaultPoints,
  getDefaultChannelPoints,
  monotoneCubicInterpolation,
  catmullRomInterpolation,
  sortPoints,
  clamp,

  // Constants
  CHANNELS,
  CHANNEL_INFO,
  CHANNEL_COLORS,
  DEFAULT_STYLES,
  DEFAULT_WIDTH,
  DEFAULT_HEIGHT,

  // Types
  type CurvePoint,
  type Channel,
  type ChannelPoints,
  type LUTData,
  type CurveChangeData,
  type RGBCurveProps,
  type RGBCurveRef,
  type RGBCurveStyles,
} from 'rgb-curve';


📘 TypeScript

Full TypeScript support is included. Import types as needed:

import type {
  CurvePoint,
  Channel,
  ChannelPoints,
  LUTData,
  CurveChangeData,
  RGBCurveProps,
  RGBCurveRef,
  RGBCurveStyles,
  CurveLineStyle,
  ControlPointStyle,
  GridStyle,
  TabsStyle,
  HistogramStyle,
} from 'rgb-curve';


🌐 Browser Support

BrowserVersion
ChromeLatest ✅
FirefoxLatest ✅
SafariLatest ✅
EdgeLatest ✅

Requirements: Browsers with Canvas 2D support.



🤝 Contributing

Contributions are welcome! Here's how you can help:

  • 🐛 Report bugs - Open an issue with a reproduction
  • 💡 Suggest features - Share your ideas for improvements
  • 🔧 Submit PRs - Fix bugs or add features
  • 📖 Improve docs - Help make the documentation better

Development Setup

# Clone the repository
git clone https://github.com/LittleBoy9/rgb-curve.git

# Install dependencies
npm install

# Start development server
npm run dev

# Build the library
npm run build:lib


📄 License

MIT © Sounak Das


Made with ❤️ by Sounak Das

If you find this project helpful, consider giving it a ⭐️ on GitHub!

Keywords

rgb

FAQs

Package last updated on 06 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts