Compare commits

...

3 commits

Author SHA1 Message Date
Jan-Henrik Bruhn
93ca7ea406
Merge pull request #25 from jhbruhn/feature/brother-color-mapping
Some checks are pending
Build, Test, and Lint / Build, Test, and Lint (push) Waiting to run
Draft Release / Draft Release (push) Waiting to run
Draft Release / Build Web App (push) Blocked by required conditions
Draft Release / Build Release - macos-latest (push) Blocked by required conditions
Draft Release / Build Release - ubuntu-latest (push) Blocked by required conditions
Draft Release / Build Release - windows-latest (push) Blocked by required conditions
Draft Release / Upload to GitHub Release (push) Blocked by required conditions
Feature: brother color mapping
2025-12-21 20:54:14 +01:00
69eb7c9986 feature: Add RGB color matching for Brother thread identification
Enhances the Brother color mapping to support exact RGB color matching in
addition to catalog number matching. This follows the logic from the
BrotherColor.FromColor method in the App codebase.

Changes:
- Added optional RGB matching to enhanceThreadWithBrotherColor function
- RGB matching is enabled by default but can be disabled via options
- Enhanced logging to show breakdown of matches (catalog vs RGB)
- Matching priority: catalog number first, then RGB (both exact match only)

Example: A thread with RGB(255,255,255) will now match Brother color "WHITE"
(code 001) even if the catalog number is missing or doesn't match.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 20:52:32 +01:00
32e96d7709 feature: Add Brother thread color mapping to PES importer
This commit incorporates the Brother thread color mapping from the App codebase
into the web application. When importing PES files, thread colors are now
automatically enhanced with official Brother Embroidery thread information
including proper color names and chart codes.

Changes:
- Added BrotherColor.json database with 56 Brother embroidery thread colors
- Created brotherColors utility module with mapping functions that replicate
  the logic from Asura.Core.Models.EmbroideryUtil.GetThreadColorListFromPesx
- Enhanced PES importer client to map thread catalog numbers to Brother colors
- Updated PatternCanvas to avoid showing duplicate chart/catalog information
  when they are the same (common for Brother colors)

The mapping logic performs exact color code matching (e.g., "001", "843") and
preserves original thread data when no Brother match is found.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-21 20:37:32 +01:00
4 changed files with 915 additions and 1 deletions

View file

@ -422,7 +422,13 @@ export function PatternCanvas() {
.join(" "); .join(" ");
// Secondary metadata: chart and description // Secondary metadata: chart and description
const secondaryMetadata = [color.chart, color.description] // Only show chart if it's different from catalogNumber
const secondaryMetadata = [
color.chart && color.chart !== color.catalogNumber
? color.chart
: null,
color.description,
]
.filter(Boolean) .filter(Boolean)
.join(" "); .join(" ");

546
src/data/BrotherColor.json Normal file
View file

@ -0,0 +1,546 @@
[
{
"ColorCode": "001",
"BrandCode": 13,
"R": 240,
"G": 240,
"B": 240,
"brandName": "Brother Embroidery",
"ColorName": "WHITE"
},
{
"ColorCode": "843",
"BrandCode": 13,
"R": 239,
"G": 227,
"B": 185,
"brandName": "Brother Embroidery",
"ColorName": "BEIGE"
},
{
"ColorCode": "010",
"BrandCode": 13,
"R": 255,
"G": 255,
"B": 179,
"brandName": "Brother Embroidery",
"ColorName": "CREAM BROWN"
},
{
"ColorCode": "027",
"BrandCode": 13,
"R": 227,
"G": 243,
"B": 91,
"brandName": "Brother Embroidery",
"ColorName": "FRESH GREEN"
},
{
"ColorCode": "542",
"BrandCode": 13,
"R": 168,
"G": 221,
"B": 196,
"brandName": "Brother Embroidery",
"ColorName": "SEACREST"
},
{
"ColorCode": "017",
"BrandCode": 13,
"R": 168,
"G": 222,
"B": 235,
"brandName": "Brother Embroidery",
"ColorName": "LIGHT BLUE"
},
{
"ColorCode": "804",
"BrandCode": 13,
"R": 178,
"G": 175,
"B": 212,
"brandName": "Brother Embroidery",
"ColorName": "LAVENDER"
},
{
"ColorCode": "124",
"BrandCode": 13,
"R": 253,
"G": 217,
"B": 222,
"brandName": "Brother Embroidery",
"ColorName": "FLESH PINK"
},
{
"ColorCode": "079",
"BrandCode": 13,
"R": 252,
"G": 187,
"B": 196,
"brandName": "Brother Embroidery",
"ColorName": "SALMON PINK"
},
{
"ColorCode": "399",
"BrandCode": 13,
"R": 216,
"G": 204,
"B": 198,
"brandName": "Brother Embroidery",
"ColorName": "WARM GRAY"
},
{
"ColorCode": "307",
"BrandCode": 13,
"R": 254,
"G": 227,
"B": 197,
"brandName": "Brother Embroidery",
"ColorName": "LINEN"
},
{
"ColorCode": "005",
"BrandCode": 13,
"R": 168,
"G": 168,
"B": 168,
"ColorName": "SILVER"
},
{
"ColorCode": "812",
"BrandCode": 13,
"R": 255,
"G": 240,
"B": 141,
"brandName": "Brother Embroidery",
"ColorName": "CREAM YELLOW"
},
{
"ColorCode": "202",
"BrandCode": 13,
"R": 240,
"G": 249,
"B": 112,
"brandName": "Brother Embroidery",
"ColorName": "LEMON YELLOW"
},
{
"ColorCode": "502",
"BrandCode": 13,
"R": 158,
"G": 214,
"B": 125,
"ColorName": "MINT GREEN"
},
{
"ColorCode": "509",
"BrandCode": 13,
"R": 102,
"G": 186,
"B": 73,
"brandName": "Brother Embroidery",
"ColorName": "LEAF GREEN"
},
{
"ColorCode": "019",
"BrandCode": 13,
"R": 37,
"G": 132,
"B": 187,
"brandName": "Brother Embroidery",
"ColorName": "SKY BLUE"
},
{
"ColorCode": "612",
"BrandCode": 13,
"R": 145,
"G": 95,
"B": 172,
"ColorName": "LILAC"
},
{
"ColorCode": "810",
"BrandCode": 13,
"R": 228,
"G": 154,
"B": 203,
"brandName": "Brother Embroidery",
"ColorName": "LIGHT LILAC"
},
{
"ColorCode": "085",
"BrandCode": 13,
"R": 249,
"G": 147,
"B": 188,
"brandName": "Brother Embroidery",
"ColorName": "PINK"
},
{
"ColorCode": "086",
"BrandCode": 13,
"R": 246,
"G": 74,
"B": 138,
"brandName": "Brother Embroidery",
"ColorName": "DEEP ROSE"
},
{
"ColorCode": "348",
"BrandCode": 13,
"R": 208,
"G": 166,
"B": 96,
"brandName": "Brother Embroidery",
"ColorName": "KHAKI"
},
{
"ColorCode": "817",
"BrandCode": 13,
"R": 135,
"G": 135,
"B": 135,
"brandName": "Brother Embroidery",
"ColorName": "GRAY"
},
{
"ColorCode": "126",
"BrandCode": 13,
"R": 254,
"G": 179,
"B": 67,
"brandName": "Brother Embroidery",
"ColorName": "PUMPKIN"
},
{
"ColorCode": "205",
"BrandCode": 13,
"R": 255,
"G": 255,
"B": 0,
"brandName": "Brother Embroidery",
"ColorName": "YELLOW"
},
{
"ColorCode": "513",
"BrandCode": 13,
"R": 112,
"G": 188,
"B": 31,
"brandName": "Brother Embroidery",
"ColorName": "LIME GREEN"
},
{
"ColorCode": "534",
"BrandCode": 13,
"R": 0,
"G": 135,
"B": 119,
"brandName": "Brother Embroidery",
"ColorName": "TEAL GREEN"
},
{
"ColorCode": "420",
"BrandCode": 13,
"R": 9,
"G": 91,
"B": 166,
"brandName": "Brother Embroidery",
"ColorName": "ELECTRIC BLUE"
},
{
"ColorCode": "607",
"BrandCode": 13,
"R": 104,
"G": 106,
"B": 176,
"brandName": "Brother Embroidery",
"ColorName": "WISTERIA VIOLET"
},
{
"ColorCode": "620",
"BrandCode": 13,
"R": 145,
"G": 54,
"B": 151,
"brandName": "Brother Embroidery",
"ColorName": "MAGENTA"
},
{
"ColorCode": "807",
"BrandCode": 13,
"R": 247,
"G": 56,
"B": 102,
"brandName": "Brother Embroidery",
"ColorName": "CARMINE"
},
{
"ColorCode": "339",
"BrandCode": 13,
"R": 209,
"G": 84,
"B": 0,
"brandName": "Brother Embroidery",
"ColorName": "CLAY BROWN"
},
{
"ColorCode": "328",
"BrandCode": 13,
"R": 186,
"G": 152,
"B": 0,
"brandName": "Brother Embroidery",
"ColorName": "BRASS"
},
{
"ColorCode": "704",
"BrandCode": 13,
"R": 79,
"G": 85,
"B": 86,
"brandName": "Brother Embroidery",
"ColorName": "PEWTER"
},
{
"ColorCode": "209",
"BrandCode": 13,
"R": 254,
"G": 158,
"B": 50,
"brandName": "Brother Embroidery",
"ColorName": "TANGERINE"
},
{
"ColorCode": "206",
"BrandCode": 13,
"R": 255,
"G": 217,
"B": 17,
"brandName": "Brother Embroidery",
"ColorName": "HARVEST GOLD"
},
{
"ColorCode": "515",
"BrandCode": 13,
"R": 47,
"G": 126,
"B": 32,
"brandName": "Brother Embroidery",
"ColorName": "MOSS GREEN"
},
{
"ColorCode": "507",
"BrandCode": 13,
"R": 0,
"G": 103,
"B": 62,
"brandName": "Brother Embroidery",
"ColorName": "EMERALD GREEN"
},
{
"ColorCode": "405",
"BrandCode": 13,
"R": 10,
"G": 85,
"B": 163,
"brandName": "Brother Embroidery",
"ColorName": "BLUE"
},
{
"ColorCode": "070",
"BrandCode": 13,
"R": 75,
"G": 107,
"B": 175,
"ColorName": "CORNFLOWER BLUE"
},
{
"ColorCode": "869",
"BrandCode": 13,
"R": 119,
"G": 1,
"B": 118,
"brandName": "Brother Embroidery",
"ColorName": "ROYAL PURPLE"
},
{
"ColorCode": "107",
"BrandCode": 13,
"R": 199,
"G": 1,
"B": 86,
"brandName": "Brother Embroidery",
"ColorName": "DARK FUCHSIA"
},
{
"ColorCode": "030",
"BrandCode": 13,
"R": 254,
"G": 55,
"B": 15,
"brandName": "Brother Embroidery",
"ColorName": "VERMILLION"
},
{
"ColorCode": "330",
"BrandCode": 13,
"R": 125,
"G": 111,
"B": 0,
"brandName": "Brother Embroidery",
"ColorName": "RUSSET BROWN"
},
{
"ColorCode": "707",
"BrandCode": 13,
"R": 41,
"G": 49,
"B": 51,
"brandName": "Brother Embroidery",
"ColorName": "DARK GRAY"
},
{
"ColorCode": "214",
"BrandCode": 13,
"R": 232,
"G": 169,
"B": 0,
"brandName": "Brother Embroidery",
"ColorName": "DEEP GOLD"
},
{
"ColorCode": "208",
"BrandCode": 13,
"R": 254,
"G": 186,
"B": 53,
"brandName": "Brother Embroidery",
"ColorName": "ORANGE"
},
{
"ColorCode": "517",
"BrandCode": 13,
"R": 67,
"G": 86,
"B": 7,
"brandName": "Brother Embroidery",
"ColorName": "DARK OLIVE"
},
{
"ColorCode": "415",
"BrandCode": 13,
"R": 19,
"G": 74,
"B": 70,
"brandName": "Brother Embroidery",
"ColorName": "PEACOCK BLUE"
},
{
"ColorCode": "406",
"BrandCode": 13,
"R": 11,
"G": 61,
"B": 145,
"brandName": "Brother Embroidery",
"ColorName": "ULTRA MARINE"
},
{
"ColorCode": "614",
"BrandCode": 13,
"R": 78,
"G": 41,
"B": 144,
"brandName": "Brother Embroidery",
"ColorName": "PURPLE"
},
{
"ColorCode": "613",
"BrandCode": 13,
"R": 106,
"G": 28,
"B": 138,
"brandName": "Brother Embroidery",
"ColorName": "VIOLET"
},
{
"ColorCode": "333",
"BrandCode": 13,
"R": 181,
"G": 76,
"B": 100,
"brandName": "Brother Embroidery",
"ColorName": "AMBER RED"
},
{
"ColorCode": "800",
"BrandCode": 13,
"R": 237,
"G": 23,
"B": 31,
"brandName": "Brother Embroidery",
"ColorName": "RED"
},
{
"ColorCode": "337",
"BrandCode": 13,
"R": 209,
"G": 92,
"B": 0,
"brandName": "Brother Embroidery",
"ColorName": "REDDISH BROWN"
},
{
"ColorCode": "900",
"BrandCode": 13,
"R": 0,
"G": 0,
"B": 0,
"ColorName": "BLACK"
},
{
"ColorCode": "058",
"BrandCode": 13,
"R": 42,
"G": 19,
"B": 1,
"brandName": "Brother Embroidery",
"ColorName": "DARK BROWN"
},
{
"ColorCode": "323",
"BrandCode": 13,
"R": 178,
"G": 118,
"B": 36,
"brandName": "Brother Embroidery",
"ColorName": "LIGHT BROWN"
},
{
"ColorCode": "519",
"BrandCode": 13,
"R": 19,
"G": 43,
"B": 26,
"brandName": "Brother Embroidery",
"ColorName": "OLIVE GREEN"
},
{
"ColorCode": "808",
"BrandCode": 13,
"R": 0,
"G": 56,
"B": 34,
"brandName": "Brother Embroidery",
"ColorName": "DEEP GREEN"
},
{
"ColorCode": "007",
"BrandCode": 13,
"R": 14,
"G": 31,
"B": 124,
"brandName": "Brother Embroidery",
"ColorName": "PRUSSIAN BLUE"
}
]

View file

@ -2,6 +2,7 @@ import type { WorkerMessage, WorkerResponse } from "./worker";
import PatternConverterWorker from "./worker?worker"; import PatternConverterWorker from "./worker?worker";
import { decodePenData } from "../pen/decoder"; import { decodePenData } from "../pen/decoder";
import type { DecodedPenData } from "../pen/types"; import type { DecodedPenData } from "../pen/types";
import { enhanceThreadWithBrotherColor } from "../../utils/brotherColors";
export type PyodideState = "not_loaded" | "loading" | "ready" | "error"; export type PyodideState = "not_loaded" | "loading" | "ready" | "error";
@ -203,8 +204,68 @@ class PatternConverterClient {
"colors", "colors",
); );
// Enhance thread data with Brother color mapping (with RGB matching enabled)
let catalogMatches = 0;
let rgbMatches = 0;
const enhancedThreads = message.data.threads.map((thread) => {
const hadCatalog = !!thread.catalogNumber;
const hadBrotherBrand = thread.brand === "Brother Embroidery";
const enhanced = enhanceThreadWithBrotherColor(thread, {
matchByRGB: true,
});
// Track what type of match occurred
const isBrother = enhanced.brand === "Brother Embroidery";
if (isBrother && !hadBrotherBrand) {
if (hadCatalog) {
catalogMatches++;
} else {
rgbMatches++;
}
}
return {
color: thread.color,
hex: enhanced.hex,
brand: enhanced.brand,
catalogNumber: enhanced.catalogNumber,
description: enhanced.description,
chart: enhanced.chart,
};
});
// Also enhance unique colors
const enhancedUniqueColors = message.data.uniqueColors.map(
(color) => {
const enhanced = enhanceThreadWithBrotherColor(color, {
matchByRGB: true,
});
return {
color: color.color,
hex: enhanced.hex,
brand: enhanced.brand,
catalogNumber: enhanced.catalogNumber,
description: enhanced.description,
chart: enhanced.chart,
threadIndices: color.threadIndices,
};
},
);
console.log(
"[PatternConverter] Enhanced threads with Brother color mapping:",
enhancedThreads.filter((t) => t.brand === "Brother Embroidery")
.length,
"Brother colors found",
`(${catalogMatches} by catalog, ${rgbMatches} by RGB)`,
);
const result: PesPatternData = { const result: PesPatternData = {
...message.data, ...message.data,
threads: enhancedThreads,
uniqueColors: enhancedUniqueColors,
penData, penData,
penStitches, penStitches,
}; };

301
src/utils/brotherColors.ts Normal file
View file

@ -0,0 +1,301 @@
/**
* Brother Color Mapping Utilities
*
* This module provides utilities for mapping thread colors to official Brother
* embroidery thread colors with their proper names and chart codes.
*
* Based on the Brother Embroidery thread catalog, this mapping ensures accurate
* color identification for embroidery patterns.
*
* The mapping logic follows the implementation in Asura.Core.Models.EmbroideryUtil.GetThreadColorListFromPesx
*/
import brotherColorData from "../data/BrotherColor.json";
/**
* Brother thread color data structure
*/
export interface BrotherColor {
/** RGB red value (0-255) */
R: number;
/** RGB green value (0-255) */
G: number;
/** RGB blue value (0-255) */
B: number;
/** Brother thread chart code (e.g., "001", "843") */
ColorCode: string;
/** Color name (e.g., "WHITE", "BEIGE") */
ColorName: string;
/** Brand code (13 for Brother Embroidery) */
BrandCode: number;
/** Brand name */
brandName?: string;
}
/**
* Thread color information with Brother mapping
*/
export interface ThreadColorInfo {
/** RGB color as hex string */
hex: string;
/** Brand name (e.g., "Brother Embroidery") */
brand: string | null;
/** Color catalog/chart code (e.g., "001", "843") */
catalogNumber: string | null;
/** Color description/name (e.g., "WHITE", "BEIGE") */
description: string | null;
/** Chart code (same as catalogNumber for Brother) */
chart: string | null;
/** RGB values */
rgb: {
r: number;
g: number;
b: number;
};
}
// Type-safe Brother color data
const brotherColors = brotherColorData as BrotherColor[];
/**
* Convert RGB values to hex color string
*/
function rgbToHex(r: number, g: number, b: number): string {
return `#${((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1).toUpperCase()}`;
}
/**
* Pad a color code to 3 digits with leading zeros
* e.g., "5" -> "005", "43" -> "043", "900" -> "900"
*
* This replicates the logic:
* ```csharp
* if (int.TryParse(threadCode, NumberStyles.Number, CultureInfo.InvariantCulture, out result))
* threadCode = $"{result:000}";
* ```
*/
function padColorCode(code: string | number): string {
const codeStr = typeof code === "number" ? code.toString() : code;
const parsed = parseInt(codeStr, 10);
if (!isNaN(parsed)) {
return parsed.toString().padStart(3, "0");
}
return codeStr;
}
/**
* Find Brother color by color code (exact match only)
*
* This replicates:
* ```csharp
* IEnumerable<BrotherColor> source2 = BrotherColor.Colors.Where<BrotherColor>((c => c.ColorCode == threadCode));
* ```
*
* @param colorCode - Brother thread code (e.g., "001", "5", 843)
* @returns Brother color data or undefined if not found
*/
export function findBrotherColorByCode(
colorCode: string | number,
): BrotherColor | undefined {
const paddedCode = padColorCode(colorCode);
return brotherColors.find((c) => c.ColorCode === paddedCode);
}
/**
* Find Brother color by RGB values (exact match only)
*
* @param r - Red value (0-255)
* @param g - Green value (0-255)
* @param b - Blue value (0-255)
* @returns Brother color data or undefined if no exact match found
*/
export function findBrotherColorByRGB(
r: number,
g: number,
b: number,
): BrotherColor | undefined {
return brotherColors.find((c) => c.R === r && c.G === g && c.B === b);
}
/**
* Convert Brother color to ThreadColorInfo
*
* This replicates:
* ```csharp
* threadColor1.BrandName = brotherColor.BrandName;
* threadColor1.BrandCode = brotherColor.BrandCode;
* threadColor1.ColorName = brotherColor.ColorName;
* threadColor1.ColorCode = brotherColor.ColorCode;
* threadColor1.R = brotherColor.R;
* threadColor1.G = brotherColor.G;
* threadColor1.B = brotherColor.B;
* ```
*
* @param brotherColor - Brother color data
* @returns Thread color information
*/
export function brotherColorToThreadInfo(
brotherColor: BrotherColor,
): ThreadColorInfo {
return {
hex: rgbToHex(brotherColor.R, brotherColor.G, brotherColor.B),
brand: brotherColor.brandName || "Brother Embroidery",
catalogNumber: brotherColor.ColorCode,
description: brotherColor.ColorName,
chart: brotherColor.ColorCode,
rgb: {
r: brotherColor.R,
g: brotherColor.G,
b: brotherColor.B,
},
};
}
/**
* Map a thread color code to full Brother thread information
*
* This is the main mapping function that replicates the logic from
* EmbroideryUtil.GetThreadColorListFromPesx in the C# app.
*
* Returns null if the color code doesn't match any Brother color (exact match only).
*
* @param threadCode - Thread code from pattern file (can be string or number)
* @returns Thread color information with Brother mapping, or null if code doesn't match
*/
export function mapThreadCode(
threadCode: string | number,
): ThreadColorInfo | null {
// Parse and pad the thread code
const code = padColorCode(threadCode);
// Look up the Brother color (exact match only)
const brotherColor = findBrotherColorByCode(code);
if (!brotherColor) {
return null;
}
return brotherColorToThreadInfo(brotherColor);
}
/**
* Create a custom thread color (for non-Brother colors)
*
* This replicates the custom color handling for chartcodes 250-253:
* ```csharp
* if ("000".Equals(threadCode) && num >= 250 && num <= 253) {
* Color colorLong = EmbroideryUtil.GetColorLong(element);
* threadColor1.BrandName = "";
* threadColor1.BrandCode = num;
* threadColor1.ColorName = "";
* threadColor1.ColorCode = "0";
* threadColor1.R = colorLong.R;
* threadColor1.G = colorLong.G;
* threadColor1.B = colorLong.B;
* }
* ```
*
* @param r - Red value (0-255)
* @param g - Green value (0-255)
* @param b - Blue value (0-255)
* @param chartCode - Chart code (250-253 for custom colors)
* @returns Thread color information for custom color
*/
export function createCustomThreadColor(
r: number,
g: number,
b: number,
chartCode?: number,
): ThreadColorInfo {
return {
hex: rgbToHex(r, g, b),
brand: chartCode !== undefined ? "" : null,
catalogNumber: chartCode !== undefined ? "0" : null,
description: chartCode !== undefined ? "" : null,
chart: chartCode !== undefined ? chartCode.toString() : null,
rgb: { r, g, b },
};
}
/**
* Get all available Brother colors
*
* @returns Array of all Brother thread colors
*/
export function getAllBrotherColors(): BrotherColor[] {
return [...brotherColors];
}
/**
* Get all Brother colors as ThreadColorInfo
*
* @returns Array of all Brother thread colors as ThreadColorInfo
*/
export function getAllBrotherThreads(): ThreadColorInfo[] {
return brotherColors.map(brotherColorToThreadInfo);
}
/**
* Enhance thread data with Brother color mapping
*
* Takes thread data from a PES file and enhances it with Brother color information
* using exact matching by catalog number or RGB values.
*
* This follows the logic from BrotherColor.FromColor and EmbroideryUtil.GetThreadColorListFromPesx:
* 1. If catalogNumber matches a Brother color code, use Brother data
* 2. Optionally, try exact RGB color matching
* 3. If no match, preserve the original thread data
*
* @param thread - Thread data from PES file
* @param options - Enhancement options
* @param options.matchByRGB - Enable exact RGB color matching (default: true)
* @returns Enhanced thread data with Brother mapping if applicable
*/
export function enhanceThreadWithBrotherColor(
thread: {
color: number;
hex: string;
brand: string | null;
catalogNumber: string | null;
description: string | null;
chart: string | null;
},
options: {
matchByRGB?: boolean;
} = {},
): ThreadColorInfo {
const { matchByRGB = true } = options;
// First, try to match by catalog number
if (thread.catalogNumber) {
const brotherInfo = mapThreadCode(thread.catalogNumber);
if (brotherInfo) {
// Found a Brother color match by catalog number - use Brother data
return brotherInfo;
}
}
// Second, try exact RGB matching if enabled (replicates BrotherColor.FromColor logic)
const cleanHex = thread.hex.replace("#", "");
const r = parseInt(cleanHex.slice(0, 2), 16);
const g = parseInt(cleanHex.slice(2, 4), 16);
const b = parseInt(cleanHex.slice(4, 6), 16);
if (matchByRGB) {
const brotherColor = findBrotherColorByRGB(r, g, b);
if (brotherColor) {
// Found exact RGB match - use Brother data
return brotherColorToThreadInfo(brotherColor);
}
}
// No Brother match - return thread data as-is
return {
hex: thread.hex,
brand: thread.brand,
catalogNumber: thread.catalogNumber,
description: thread.description,
chart: thread.chart,
rgb: { r, g, b },
};
}