1 คะแนน โดย GN⁺ 2026-02-19 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • บทความนี้เสนอให้สร้าง พาเลต 256 สี โดยอัตโนมัติจาก ธีม base16 ของผู้ใช้ เพื่อปรับปรุงความสม่ำเสมอของสีและความสามารถในการอ่านของเทอร์มินัล
  • ธีม base16 แบบเดิมนั้นเรียบง่าย แต่มีจำนวนสีจำกัด ขณะที่ truecolor มีความซับซ้อนในการตั้งค่าและมีปัญหาด้านความเข้ากันได้
  • พาเลต 256 สีเริ่มต้นมีคุณภาพด้านภาพต่ำ เนื่องจาก ความสว่างไม่สมดุล, ธีมไม่สอดคล้องกัน, และ การอินเทอร์โพเลตที่ไม่ถูกต้อง
  • หากสร้างพาเลตแบบขยายจากสี base16 ด้วย การอินเทอร์โพเลตใน LAB color space ก็จะสามารถรักษาความสม่ำเสมอของความสว่างและคอนทราสต์ พร้อมทั้งให้การแสดงสีที่หลากหลายได้
  • เทอร์มินัลหลักหลายตัว (เช่น Ghostty, iTerm2, SwiftTerm) ได้เริ่มนำไปใช้แล้ว และมีความเป็นไปได้ที่ ฟีเจอร์การสร้างพาเลตอัตโนมัติแบบมาตรฐาน จะช่วยยกระดับคุณภาพของระบบนิเวศเทอร์มินัลโดยรวม

ภาพรวมของพาเลต 256 สี

  • พาเลต 256 สีประกอบด้วย สีพื้นฐาน 16 สี, คิวบ์ 216 สี, และ grayscale 24 ระดับ
    • สีพื้นฐาน 16 สีประกอบด้วยสีดำ สีขาว สีหลัก และเฉดสว่างของแต่ละสี
    • คิวบ์ 216 สีคำนวณโดยใช้ 6 ระดับ (0~5) สำหรับแต่ละช่อง RGB: 16 + (36 * R) + (6 * G) + B
    • grayscale ประกอบด้วย 24 ระดับระหว่างขาวดำ: 232 + S (S คือ 0~23)
  • โครงสร้างนี้เป็น เวอร์ชันแบบย่อของ RGB 24 บิต ที่ลดจำนวนสีลงแต่ยังคงความสามารถในการแสดงผลไว้

ปัญหาของพาเลต 256 สีแบบเดิม

  • เกิดความขัดแย้งของสีจาก ความไม่สอดคล้องกับธีม Base16
    • พาเลตเริ่มต้นส่วนใหญ่ไม่เข้ากันกับธีม base16 ส่วนมาก
  • การอินเทอร์โพเลตสีที่ไม่ถูกต้อง ทำให้ความสามารถในการอ่านบนพื้นหลังมืดลดลง
    • เฉดแรกของพาเลตเริ่มต้นถูกคำนวณให้สว่างกว่าความเป็นจริง ทำให้คอนทราสต์อ่อนลง
  • มีปัญหาเรื่อง คอนทราสต์ไม่สม่ำเสมอ
    • เนื่องจากใช้สีอิ่มตัวเต็มที่จึงทำให้สมดุลความสว่างไม่พอดี และแม้จะอยู่ในระดับเดียวกัน สีน้ำเงินก็ดูมืดกว่าสีเขียว

วิธีการสร้างพาเลต

  • แนวทางแก้คือ สร้างพาเลต 256 สีโดยอัตโนมัติจากสี base16 ของผู้ใช้
    • แมปสีพื้นฐาน 8 สีของ base16 ไปยังมุมทั้ง 8 ของคิวบ์ 216 สี
    • สร้างคิวบ์ด้วย การอินเทอร์โพเลตแบบ trilinear โดยใช้สีพื้นหลังและสีตัวอักษร
    • ใช้ LAB color space เพื่อรักษา ความสม่ำเสมอของความสว่างตามการมองเห็น ระหว่างสีต่าง ๆ
  • grayscale สร้างขึ้นด้วยการอินเทอร์โพเลตแบบง่ายจากพื้นหลังไปยังสีตัวอักษร
  • ในตัวอย่างโค้ด Python มีการใช้ฟังก์ชัน rgb_to_lab, lab_to_rgb, lerp_lab เพื่อทำการแปลง

สถานะการนำไปใช้และการประยุกต์ใช้

  • โค้ดที่เสนอนี้เผยแพร่เป็น public domain จึงสามารถแก้ไขและนำไปใช้ได้อย่างอิสระ
  • เทอร์มินัลหลักอย่าง Ghostty, iTerm2, SwiftTerm ได้ติดตั้งใช้งานแล้ว
  • ใน kitty, Wezterm, Tabby, Windows Terminal ก็มีการร้องขอให้นำไปใช้หรือกำลังอยู่ระหว่างการพัฒนา
  • นักพัฒนาบางส่วนเสนอให้ใช้ OKLAB/OKLCH color space และโครงการมีแผนจะทำให้มาตรฐาน color space เป็นแบบเดียวกัน ตามการตัดสินใจของ Ghostty
  • สามารถใช้พาเลตได้โดยตรงผ่านสคริปต์ Python หรือสร้างไฟล์ตั้งค่าเทอร์มินัลโดยอัตโนมัติได้

บทสรุปและข้อเสนอ

  • พาเลต 256 สีเริ่มต้นถูกนักพัฒนาโปรแกรมหลีกเลี่ยง เนื่องจาก ความสามารถในการอ่านลดลงและธีมไม่สอดคล้องกัน
  • หากเทอร์มินัล สร้างพาเลต 256 สีโดยอัตโนมัติโดยอิงจากธีม base16 ก็จะได้ประโยชน์ดังนี้
    • ใช้ ช่วงสีที่กว้างขึ้น ได้โดยไม่ต้องมีไฟล์ตั้งค่า
    • ไม่ต้องให้นักพัฒนาเข้ามาเกี่ยวข้องเมื่อ สลับโหมดสว่าง/มืด
    • รักษา ความเข้ากันได้กับเทอร์มินัลอย่างกว้างขวาง
  • ผู้เสนอเน้นว่าฟีเจอร์นี้ควรถูก เปิดใช้งานเป็นค่าเริ่มต้นแบบ opt-out และในระยะยาวควร กลายเป็นฟีเจอร์มาตรฐาน

1 ความคิดเห็น

 
GN⁺ 2026-02-19
ความเห็นจาก Hacker News
  • ข้อดีของพาเลต 256 สีคือสีหมายเลข 16~255 ถูกกำหนดตายตัว
    ดังนั้นจึงมั่นใจได้ว่าอย่างเช่นสีหมายเลข 146 จะเป็น “ม่วงอ่อน” เสมอ
    สิ่งนี้มีประโยชน์มากสำหรับนักพัฒนาธีมสีที่ต้องการมอบ ประสบการณ์สีที่สม่ำเสมอ บนเทอร์มินัลอีมูเลเตอร์หลากหลายตัว
    ถ้าพาเลต 256 สีถูกสร้างจากพาเลต 16 สีที่เปลี่ยนแปลงได้ สีหมายเลข 146 ก็อาจไม่ใช่สีที่คาดไว้
    ผมคิดว่าการทำให้ช่วง 16~255 ไม่เสถียรเหมือนช่วง 0~15 นั้นเป็นทิศทางที่ผิด

    • แม้การใช้แค่ 16 สีจะมีข้อจำกัด แต่การให้ผู้พัฒนา CLI/TUI ออกแบบ ธีมสีตามใจชอบ นอกเหนือจากช่วงนั้นก็ไม่สะดวก
      มันทำให้อ่านยากสำหรับผู้มีความบกพร่องทางการมองเห็น ผู้ที่ตาบอดสี หรือคนที่ชอบพื้นหลังสีขาว
      สุดท้ายผู้ใช้ก็ต้องตั้งค่าสีทั้งของเทอร์มินัลพื้นฐานและของแต่ละแอปแยกกัน
      คนใช้เทอร์มินัลเพราะ ประสิทธิภาพ ไม่ใช่เพราะ UI สวย ถ้าอยากได้ของสวยก็ไปทำเว็บฟรอนต์เอนด์แทน
    • สีในเทอร์มินัลควรถูกใช้โดยยึด ความหมายเชิง semantic ไม่ใช่สไตล์
      เราไม่ได้ต้องการ “ประสบการณ์ที่สม่ำเสมอ” สีควรถูกใช้อย่างพอเหมาะและเคารพการตั้งค่าของผู้ใช้
    • ต่อให้รู้ว่าสี 146 คือ “ม่วงอ่อน” ก็ไม่มีความหมายถ้าไม่รู้สีพื้นหลัง
      พื้นหลังอาจเป็นสีม่วงอยู่แล้ว หรืออาจเป็นตัวอักษรสีม่วงบนพื้นหลังสีขาวก็ได้
      พูดอีกอย่างคือ ถ้าแอปไม่รู้การตั้งค่าสีของเทอร์มินัลของฉัน ก็ไม่ควรใช้สีนั้น
    • จริง ๆ แล้วฟีเจอร์นี้เหมาะกับผู้ใช้ที่สร้างพาเลตของตัวเองมากกว่า นักพัฒนาธีมสี
      ผมใช้ธีม base16 เริ่มต้น และไม่ได้คาดหวังให้มันตรงกับธีมจากบุคคลที่สาม
      ผมคิดว่าความต่างระหว่างการเข้าถึงสีระดับเทอร์มินัลกับระดับแอปนั้นใกล้เคียงกับประเด็นเชิงปรัชญามากกว่า
    • เทอร์มินัลอย่าง iTerm2 ก็มีฟีเจอร์ Minimum Contrast อยู่แล้ว แต่บางครั้งมันก็บิดเบือนสีอย่างหนัก
  • ผมสร้างตัวเรนเดอร์ Markdown แบบสตรีมมิงชื่อ Streamdown
    โดยอิงกับ HSV แค่กำหนด สีอ้างอิงเพียงสีเดียว ที่เหลือจะถูกปรับอัตโนมัติเป็นทวีคูณของสีนั้น
    ตัวอย่างเช่น องค์ประกอบที่มืดจะลดความอิ่มตัวลง และสัญลักษณ์จะดูสดขึ้น
    ต่อให้ปรับ HSV ในการตั้งค่าเพียงเล็กน้อย โทนโดยรวมก็จะเปลี่ยนอย่างเป็นธรรมชาติ จึงไม่ต้องมานั่งไล่ปรับทีละสี
    มี โค้ดตัวอย่าง ด้วย

  • แม้แต่พาเลตพื้นฐาน 16 สีก็ยังมีปัญหา
    คำว่า ‘black’, ‘white’, ‘bright black’, ‘bright white’ จริง ๆ แล้วควรสื่อถึง ความต่างของความสว่าง แต่กลับถูกตั้งชื่อเป็นสี
    ผมมองมันว่าเป็น “สีที่แทบมองไม่เห็นบนพื้นหลัง”, “สีที่มีคอนทราสต์สูง”, “สีที่มองเห็นได้แต่ไม่เด่น”, และ “สีที่คอนทราสต์สูงที่สุด”
    อยากให้มันถูกนิยามโดยยึด คอนทราสต์เป็นหลัก มากกว่าชื่อสี

    • วิธีที่ถูกต้องคือไม่ไปแตะสีของเทอร์มินัล แต่ตั้งค่าให้โปรแกรมใช้สีอื่นแทน
      สี foreground/background ของเทอร์มินัลนั้นแยกจากมาตรฐาน 16 สี จึงยิ่งซับซ้อนกว่าเดิม
    • ถ้าไม่มีการตั้งค่าสีให้ใช้ได้ ก็ควรใช้แค่คุณสมบัติอย่าง bold·reverse·standout จะดีกว่า
      และเมื่อไม่รู้พื้นหลัง ก็ควรหลีกเลี่ยงสีดำกับสีขาว หากจะใช้ 256 สี ก็ควรมีธีมเอนจินที่ผู้ใช้ตั้งค่าได้
  • ผมคิดว่าควรเพิ่มฟีเจอร์นี้ในทุกเทอร์มินัล
    ถ้าขยายไปเป็น 24-bit color ก็น่าจะยิ่งดี แต่ต้อง ทำเป็นตัวเลือก
    เช่น ถ้าใช้ธีม Solarized ทั้งในเทอร์มินัลและเอดิเตอร์ ก็อาจมีการแปลงสีซ้ำซ้อนกันได้

    • ยังสามารถสร้าง LUT (lookup table) จากพาเลต 16 สีแล้วแมปไปยังพื้นที่สี 24 บิตได้ด้วย
      ถ้าเปิดให้ควบคุมผ่าน environment variable โดยที่แอปไม่ต้องไปเขียนทับการตั้งค่าเอง ก็จะยืดหยุ่นกว่า
  • ตอนนี้ผมเจอและกำลังใช้ tinted-theming/base24 อยู่
    สามารถสลับธีมสีได้ง่ายด้วย tinted shell ถือเป็นวิธีแก้ชั่วคราวที่ค่อนข้างดี

  • ใน cargo/rustc ก็มีปัญหาเรื่องจำนวนสีไม่พอเหมือนกัน
    ถ้าใช้แค่สีเชิงความหมายแบบพื้นฐาน สีที่เหลือก็มีแค่มาเจนตา ดำ และขาว ซึ่งเสี่ยงขึ้นอยู่กับธีม

    • ถ้าตัดสีแดงกับเขียวออก ผมคิดว่าเครื่องมือ CLI ไม่ควรพึ่งสีมากเกินไป และควรรองรับ ตัวทำเครื่องหมายแบบข้อความ แทน
  • ใช้แค่ โหมด true color 24 บิต ก็ไม่ต้องมีพาเลตแล้ว
    ตาม termstandard/colors เทอร์มินัลสมัยใหม่ส่วนใหญ่รองรับสิ่งนี้

    • แต่ในต้นฉบับก็มี ข้อโต้แย้งชัดเจน ต่อ true color อยู่
    • urxvt ยังไม่รองรับ true color อย่างสมบูรณ์
    • เพราะเราไม่อาจควบคุมทุกสีได้ทั้งหมด สุดท้ายก็ยังต้อง ตั้งสมมติฐาน อยู่ดี และนั่นแหละคือประเด็นสำคัญ
    • แก่นของการถกเถียงนี้ไม่ใช่ true color แต่คือการใช้ ธีมที่ผู้ใช้ตั้งค่าได้บนฐาน 256 สี
    • ถ้าเทคโนโลยีพัฒนาไป ก็อาจมี มาตรฐานสีเชิงการรับรู้ ที่ 48 บิตขึ้นไปได้
      ถึงขั้นว่าหากคำนึงถึงข้อจำกัดทางฟิสิกส์ เช่น ความไม่แน่นอนของไฮเซนเบิร์ก หรือ quantum noise ก็อาจต้องใช้ข้อมูลระดับ 6000 บิตต่อพิกเซล
      จินตนาการแบบนี้เป็นการทดลองทางความคิดที่น่าสนใจซึ่งชี้ทิศทางของความก้าวหน้าทางเทคโนโลยี คล้ายกับ มาตราคาดาเชฟ หรือแนวคิดเวลาแห่งจักรวาลแบบโบราณ
  • ไม่ใช่ผู้ใช้ทุกคนจะตั้งค่า สีพื้นฐานเริ่มต้น ไว้อย่างเหมาะสม
    บางเทอร์มินัลอาจออกเขียวทั้งจอหรือส้มทั้งจอก็ได้
    วิธีเอาความอิ่มตัวของสีพื้นฐานไปใช้กับทั้งพาเลตก็อาจจะยังดีกว่า

  • ผมเป็น คนตาบอดสี เลยลำบากกับธีมสีมาตลอด
    เลยใช้โมเดล AI เพื่อสร้าง ชุดสีที่อ่านง่าย แบบอัตโนมัติ
    พอมันเพิ่มคอนทราสต์จากธีมที่เดิมชอบอยู่แล้ว ก็ทำให้ดูสบายตาขึ้นมาก
    คิดว่าวิธีแบบนี้น่าจะช่วยคนอื่นได้ด้วย

    • ผมไม่ได้ตาบอดสี แต่เจอปัญหาคล้ายกัน
      แต่ละแอปใช้สีไม่เหมือนกัน บางธีมจึงอ่านง่ายใน CLI บางตัว แต่จางเกินไปในอีกตัว
      สุดท้ายก็ต้องมานั่งปรับธีมสีแยกเป็นรายแอป ซึ่งไม่สะดวก
  • ผมมี protanomaly (ภาวะการรับสีแดงบกพร่อง) เลยใช้ ametameric อยู่
    ถ้าใช้ร่วมกับฟีเจอร์นี้ก็น่าจะได้ผลที่ดียิ่งขึ้น