Commit c59d53a2 authored by Kim, Hyeonseo's avatar Kim, Hyeonseo
Browse files

Refactor rgbTo256Color function to improve grayscale handling and optimize RGB color mapping

parent 8172d254
Loading
Loading
Loading
Loading
+38 −13
Original line number Diff line number Diff line
@@ -277,23 +277,48 @@ const ASCII_CHARS =
  "█▓▒░@#B8&WM%*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. ";
// cSpell: enable

function rgbTo256Color(r: number, g: number, b: number): number {
  // Handle grayscale colors (colors 232-255)
export function rgbTo256Color(r: number, g: number, b: number): number {
  // Check if it's a grayscale color first (when all RGB values are very close)
  const gray = Math.round((r + g + b) / 3);
  if (
    Math.abs(r - gray) < 10 && Math.abs(g - gray) < 10 &&
    Math.abs(b - gray) < 10
  ) {
    if (gray < 8) return 16; // Black
    if (gray > 248) return 231; // White
    return Math.round(((gray - 8) / 240) * 23) + 232;
  const isGrayscale = Math.abs(r - gray) <= 5 && Math.abs(g - gray) <= 5 &&
    Math.abs(b - gray) <= 5;

  // Handle grayscale colors (colors 232-255) - but exclude exact cube values
  if (isGrayscale) {
    const cubeValues = [0, 95, 135, 175, 215, 255];
    const isExactCubeValue = cubeValues.includes(r) && r === g && g === b;

    if (!isExactCubeValue) {
      if (gray < 8) return 232; // Darkest grayscale
      if (gray > 238) return 255; // Brightest grayscale

      // Map to grayscale range 232-255 (24 levels)
      // XTerm grayscale: 8, 18, 28, ..., 238 maps to 232, 233, 234, ..., 255
      const grayIndex = Math.round((gray - 8) / 10);
      return Math.max(232, Math.min(255, 232 + grayIndex));
    }
  }

  // Handle RGB colors (colors 16-231)
  // Convert to 6x6x6 cube
  const r6 = Math.round((r / 255) * 5);
  const g6 = Math.round((g / 255) * 5);
  const b6 = Math.round((b / 255) * 5);
  // XTerm 256 color cube values: [0, 95, 135, 175, 215, 255]
  const cubeValues = [0, 95, 135, 175, 215, 255];

  const findClosestIndex = (value: number): number => {
    let minDiff = Infinity;
    let closestIndex = 0;
    for (let i = 0; i < cubeValues.length; i++) {
      const diff = Math.abs(value - cubeValues[i]);
      if (diff < minDiff) {
        minDiff = diff;
        closestIndex = i;
      }
    }
    return closestIndex;
  };

  const r6 = findClosestIndex(r);
  const g6 = findClosestIndex(g);
  const b6 = findClosestIndex(b);

  return 16 + (36 * r6) + (6 * g6) + b6;
}