npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rn-color-thief

v1.0.2

Published

A powerful React Native library for extracting prominent colors from images and SVGs using Skia rendering engine

Readme

React Native Color Thief

A powerful React Native library for extracting prominent colors from images and SVGs using Skia rendering engine. Extract color palettes, dominant colors, and perform detailed color analysis with high performance and accuracy.

Features

  • 🎨 Extract prominent colors from images and SVGs
  • 🚀 High-performance color extraction using React Native Skia
  • 🎯 Get dominant colors, complete palettes, or specific color formats
  • 📊 Detailed color statistics and analysis
  • 🔧 Highly configurable with quality, count, and filtering options
  • 📱 Optimized for React Native applications
  • 🎪 Support for multiple color formats (HEX, RGB, HSL, CSS keywords)
  • 🖼️ Support for various image formats (JPG, PNG, GIF, BMP, WebP, SVG)

| iOS | Android | |-----|---------| | | |

Installation

npm install rn-color-thief
# or
yarn add rn-color-thief

Dependencies

This library requires @shopify/react-native-skia as a peer dependency:

npm install @shopify/react-native-skia
# or
yarn add @shopify/react-native-skia

Version Compatibility

Supported Versions

For full feature support (recommended):

  • React: >=19.0.0
  • React Native: >=0.79.0
  • React Native Skia: >=2.0.0

Legacy support:

  • React: >=18.0.0
  • React Native: >=0.70.0
  • React Native Skia: >=1.0.0

Platform Requirements

  • iOS: 14.0 or higher
  • Android: API level 21 (Android 5.0) or higher
  • Android with video support: API level 26 (Android 8.0) or higher

Version-Specific Compatibility

React Native ≤0.78 with React ≤18

If you're using React Native 0.78 or below with React 18 or below, you must use React Native Skia version 1.12.4 or below:

npm install @shopify/[email protected]
# or
yarn add @shopify/[email protected]

React Native ≥0.79 with React ≥19

For React Native 0.79+ with React 19+, use the latest React Native Skia:

npm install @shopify/react-native-skia@latest
# or
yarn add @shopify/react-native-skia@latest

Expo Compatibility

This library is fully compatible with Expo projects using:

  • Expo SDK 50+ (React Native 0.73+)
  • Custom development builds (required for React Native Skia)

Note: React Native Skia requires a custom development build and cannot be used with Expo Go.

Automatic Compatibility Checking

The library automatically checks version compatibility on initialization and will warn you about any issues:

import { ReactNativeColorThief } from 'rn-color-thief';

// Automatic compatibility check on initialization
const colorThief = new ReactNativeColorThief();

// Suppress compatibility warnings (not recommended)
const colorThief = new ReactNativeColorThief({
  suppressCompatibilityWarnings: true
});

// Manual compatibility check
const compatibility = colorThief.checkVersionCompatibility();
if (!compatibility.isCompatible) {
  console.error('Version compatibility issues:', compatibility);
}

Quick Start

import { ReactNativeColorThief } from 'rn-color-thief';

const colorThief = new ReactNativeColorThief();

// Extract prominent colors
const colors = await colorThief.getProminentColors('https://example.com/image.jpg');
console.log(colors[0].formats.hex); // "#FF5733"

// Get dominant color only
const dominant = await colorThief.getDominantColor('https://example.com/image.jpg');
console.log(dominant.formats.rgb); // "rgb(255, 87, 51)"

API Reference

ReactNativeColorThief Class

Constructor

const colorThief = new ReactNativeColorThief(config?: ColorThiefConfig);

Configuration Options

interface ColorThiefConfig {
  quality?: number;        // 1-10, higher = better quality but slower (default: 10)
  colorCount?: number;     // Number of colors to extract (default: 5)
  minAlpha?: number;       // Minimum alpha value for pixel inclusion (default: 125)
  excludeWhite?: boolean;  // Exclude near-white colors (default: true)
  whiteThreshold?: number; // White threshold for exclusion (default: 250)
  canvasSize?: number;     // Canvas size for processing (default: 256)
}

Core Methods

getProminentColors()

Extract all prominent colors from an image.

const colors = await colorThief.getProminentColors(imageURI);

Returns: Promise<ColorResult[]>

getDominantColor()

Get only the most prominent color.

const dominant = await colorThief.getDominantColor(imageURI);

Returns: Promise<ColorResult>

getPalette()

Get a complete palette with dominant and secondary colors.

const palette = await colorThief.getPalette(imageURI);

Returns: Promise<PaletteResult>

getColorsInFormat()

Get colors in a specific string format.

const hexColors = await colorThief.getColorsInFormat(imageURI, 'hex');
const rgbColors = await colorThief.getColorsInFormat(imageURI, 'rgbString');

Returns: Promise<string[]>

Utility Methods

getColorStatistics()

Get detailed color statistics and analysis.

const stats = await colorThief.getColorStatistics(imageURI);
// Returns: { totalColors, averageBrightness, colorDistribution }

isSupportedFormat()

Check if an image format is supported.

const isSupported = colorThief.isSupportedFormat('image.jpg'); // true

updateConfig() / getConfig() / resetConfig()

Manage configuration dynamically.

colorThief.updateConfig({ quality: 5, colorCount: 8 });
const config = colorThief.getConfig();
colorThief.resetConfig(); // Reset to defaults

Usage Examples

Basic Usage

import { ReactNativeColorThief } from 'rn-color-thief';

const extractColors = async (imageURI: string) => {
  const colorThief = new ReactNativeColorThief();
  
  try {
    const colors = await colorThief.getProminentColors(imageURI);
    
    colors.forEach((color, index) => {
      console.log(`Color ${index + 1}:`, {
        hex: color.formats.hex,
        rgb: color.formats.rgb,
        hsl: color.formats.hsl,
        keyword: color.formats.keyword
      });
    });
    
    return colors;
  } catch (error) {
    console.error('Color extraction failed:', error);
    return [];
  }
};

Custom Configuration

const colorThief = new ReactNativeColorThief({
  quality: 5,           // Faster processing
  colorCount: 8,        // Extract 8 colors
  minAlpha: 100,        // Lower alpha threshold
  excludeWhite: false,  // Include white colors
  canvasSize: 512,      // Higher quality processing
});

const palette = await colorThief.getPalette(imageURI);

React Native Component Integration

import React, { useState, useEffect } from 'react';
import { View, Image, Text } from 'react-native';
import { ReactNativeColorThief } from 'rn-color-thief';

const ColorfulImageCard = ({ imageURI }) => {
  const [colors, setColors] = useState(null);
  const colorThief = new ReactNativeColorThief();

  useEffect(() => {
    const extractColors = async () => {
      try {
        const palette = await colorThief.getPalette(imageURI);
        setColors({
          primary: palette.dominant.formats.hex,
          secondary: palette.secondary[0]?.formats.hex,
          textColor: getContrastColor(palette.dominant.rgb),
        });
      } catch (error) {
        console.error('Failed to extract colors:', error);
      }
    };

    extractColors();
  }, [imageURI]);

  const getContrastColor = (rgb) => {
    const brightness = (rgb[0] + rgb[1] + rgb[2]) / 3;
    return brightness > 128 ? '#000000' : '#FFFFFF';
  };

  return (
    <View style={{ backgroundColor: colors?.primary }}>
      <Image source={{ uri: imageURI }} style={{ width: 200, height: 200 }} />
      <Text style={{ color: colors?.textColor }}>
        Themed with extracted colors!
      </Text>
    </View>
  );
};

Batch Processing

const procesMultipleImages = async (imageURIs: string[]) => {
  const colorThief = new ReactNativeColorThief();
  const results = [];

  for (const uri of imageURIs) {
    try {
      const colors = await colorThief.getProminentColors(uri);
      results.push({ uri, colors, success: true });
    } catch (error) {
      results.push({ uri, error: error.message, success: false });
    }
  }

  return results;
};

Performance Optimization

// Reuse instance for multiple operations
const colorThief = new ReactNativeColorThief({
  quality: 5, // Lower quality for faster processing
});

// Parallel processing for multiple operations on same image
const analyzeImage = async (imageURI: string) => {
  const [colors, stats, dominant] = await Promise.all([
    colorThief.getProminentColors(imageURI),
    colorThief.getColorStatistics(imageURI),
    colorThief.getDominantColor(imageURI),
  ]);

  return { colors, stats, dominant };
};

Error Handling

const safeColorExtraction = async (imageURI: string) => {
  const colorThief = new ReactNativeColorThief();

  try {
    // Validate format
    if (!colorThief.isSupportedFormat(imageURI)) {
      throw new Error('Unsupported image format');
    }

    const colors = await colorThief.getProminentColors(imageURI);
    
    if (colors.length === 0) {
      console.warn('No colors found in image');
      return getDefaultColors();
    }

    return colors;
  } catch (error) {
    console.error('Color extraction failed:', error);
    return getDefaultColors();
  }
};

const getDefaultColors = () => [
  {
    rgb: [128, 128, 128],
    formats: {
      hex: '#808080',
      rgb: 'rgb(128, 128, 128)',
      hsl: 'hsl(0, 0%, 50%)',
      keyword: 'gray',
    },
  },
];

Data Types

ColorResult

interface ColorResult {
  rgb: [number, number, number];  // RGB values [0-255]
  formats: {
    hex: string;      // "#FF5733"
    rgb: string;      // "rgb(255, 87, 51)"
    hsl: string;      // "hsl(12, 100%, 60%)"
    keyword: string;  // "red" (CSS keyword if available)
  };
  weight?: number;    // Color frequency in image
}

PaletteResult

interface PaletteResult {
  colors: ColorResult[];     // All extracted colors
  dominant: ColorResult;     // Most prominent color
  secondary: ColorResult[];  // Secondary colors
  pixelCount: number;        // Total pixels analyzed
}

Convenience Functions

Factory Function

import { createColorThief } from 'rn-color-thief';

const colorThief = createColorThief({
  quality: 8,
  colorCount: 6,
});

Default Instance

import { defaultColorThief } from 'rn-color-thief';

const colors = await defaultColorThief.getProminentColors(imageURI);

Legacy Function (Deprecated)

import { getProminentColors } from 'rn-color-thief';

// Returns hex strings only
const hexColors = await getProminentColors(imageURI);

Supported Formats

  • Images: JPG, JPEG, PNG, GIF, BMP, WebP
  • Vector: SVG
  • Sources: URLs, local files, base64 data URIs

Performance Tips

  1. Adjust Quality: Lower quality (1-5) for faster processing
  2. Reduce Color Count: Extract fewer colors for better performance
  3. Reuse Instances: Create one instance and reuse for multiple operations
  4. Optimize Canvas Size: Use smaller canvas for faster processing
  5. Batch Operations: Use Promise.all for parallel processing

Error Handling

The library throws descriptive errors for various scenarios:

  • Invalid image URIs
  • Unsupported image formats
  • Network failures
  • Canvas initialization failures
  • Empty or corrupted images

Always wrap calls in try-catch blocks for production use.

Troubleshooting

Version Compatibility Issues

If you encounter compatibility warnings or errors, follow these steps:

  1. Check your versions:

    npm list react react-native @shopify/react-native-skia
  2. For React Native ≤0.78 projects:

    npm install @shopify/[email protected]
  3. For React Native ≥0.79 projects:

    npm install @shopify/react-native-skia@latest
  4. Run the compatibility checker:

    npx rn-color-thief-check

Common Issues

"Skia not found" Error

  • Ensure @shopify/react-native-skia is installed
  • For Expo projects, make sure you're using a custom development build
  • Rebuild your project after installing Skia

"Incompatible Skia version" Warning

  • Check your React Native version
  • Install the appropriate Skia version (see compatibility table above)
  • Clear your cache: npx react-native start --reset-cache

Metro bundler issues

  • Add to your metro.config.js:
    module.exports = {
      resolver: {
        alias: {
          'rn-color-thief': require.resolve('rn-color-thief'),
        },
      },
    };

Platform-Specific Issues

iOS Build Errors

  • Ensure iOS deployment target is set to 14.0 or higher in Xcode
  • Run cd ios && pod install after installing dependencies

Android Build Errors

  • Set minSdkVersion to 21 or higher in android/build.gradle
  • For video support, set minSdkVersion to 26 or higher

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

ISC License

Dependencies