{"id":4438,"date":"2025-05-22T10:02:26","date_gmt":"2025-05-22T10:02:26","guid":{"rendered":"https:\/\/ingenio.vip\/?post_type=tools-pages&#038;p=4438"},"modified":"2025-05-22T10:04:11","modified_gmt":"2025-05-22T10:04:11","slug":"color-palette-extractor","status":"publish","type":"tools-pages","link":"https:\/\/ingenio.vip\/zh\/tools-pages\/color-palette-extractor\/","title":{"rendered":"Color Palette Extractor"},"content":{"rendered":"<div class=\"ingenio-tool color-extractor-wrapper\" role=\"region\" aria-labelledby=\"color-extractor-title\">\r\n  <div class=\"color-extractor\">\r\n    <h2 id=\"color-extractor-title\">\ud83c\udfa8 Color Palette Extractor<\/h2>\r\n    \r\n    <div class=\"extractor-container\">\r\n      <div class=\"upload-section\">\r\n        <div class=\"upload-box\" id=\"drop-zone\">\r\n          <div class=\"upload-content\">\r\n            <svg width=\"48\" height=\"48\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n              <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"><\/path>\r\n              <polyline points=\"17 8 12 3 7 8\"><\/polyline>\r\n              <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"><\/line>\r\n            <\/svg>\r\n            <h3>Drag & Drop Image<\/h3>\r\n            <p>or click to browse files<\/p>\r\n            <input type=\"file\" id=\"image-upload\" accept=\"image\/*\">\r\n          <\/div>\r\n        <\/div>\r\n        \r\n        <div class=\"upload-controls\">\r\n          <div class=\"control-group\">\r\n            <label for=\"color-count\">Number of colors:<\/label>\r\n            <input type=\"range\" id=\"color-count\" min=\"3\" max=\"12\" value=\"6\">\r\n            <input type=\"number\" id=\"color-count-value\" min=\"3\" max=\"12\" value=\"6\">\r\n          <\/div>\r\n          \r\n          <div class=\"control-group\">\r\n            <label for=\"algorithm\">Extraction method:<\/label>\r\n            <select id=\"algorithm\">\r\n              <option value=\"kmeans\">K-Means Clustering<\/option>\r\n              <option value=\"vibrant\">Vibrant Colors<\/option>\r\n              <option value=\"median-cut\">Median Cut<\/option>\r\n            <\/select>\r\n          <\/div>\r\n          \r\n          <button id=\"extract-colors\" class=\"action-btn\">\u2728 Extract Colors<\/button>\r\n        <\/div>\r\n      <\/div>\r\n      \r\n      <div class=\"results-section\">\r\n        <div class=\"image-preview-container\">\r\n          <h3>Image Preview<\/h3>\r\n          <div class=\"image-preview\" id=\"image-preview\">\r\n            <p>Your image will appear here<\/p>\r\n          <\/div>\r\n        <\/div>\r\n        \r\n        <div class=\"color-palette-container\">\r\n          <h3>Extracted Color Palette<\/h3>\r\n          <div class=\"color-palette\" id=\"color-palette\">\r\n            <div class=\"empty-state\">\r\n              <svg width=\"48\" height=\"48\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n                <circle cx=\"12\" cy=\"12\" r=\"10\"><\/circle>\r\n                <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"><\/line>\r\n                <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"16\"><\/line>\r\n              <\/svg>\r\n              <p>Upload an image to extract colors<\/p>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      \r\n      <div class=\"color-schemes\">\r\n        <h3>Suggested Color Schemes<\/h3>\r\n        <div class=\"scheme-grid\" id=\"scheme-grid\">\r\n          <div class=\"scheme-card\">\r\n            <div class=\"scheme-colors\">\r\n              <div class=\"scheme-color\" style=\"background-color: #f5f5f5;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #e0e0e0;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #9e9e9e;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #616161;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #212121;\"><\/div>\r\n            <\/div>\r\n            <div class=\"scheme-info\">\r\n              <h4>Monochromatic<\/h4>\r\n              <p>Variations of a single hue<\/p>\r\n            <\/div>\r\n          <\/div>\r\n          <div class=\"scheme-card\">\r\n            <div class=\"scheme-colors\">\r\n              <div class=\"scheme-color\" style=\"background-color: #f5f5f5;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #e0e0e0;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #9e9e9e;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #616161;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #212121;\"><\/div>\r\n            <\/div>\r\n            <div class=\"scheme-info\">\r\n              <h4>Analogous<\/h4>\r\n              <p>Colors next to each other<\/p>\r\n            <\/div>\r\n          <\/div>\r\n          <div class=\"scheme-card\">\r\n            <div class=\"scheme-colors\">\r\n              <div class=\"scheme-color\" style=\"background-color: #f5f5f5;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #e0e0e0;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #9e9e9e;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #616161;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #212121;\"><\/div>\r\n            <\/div>\r\n            <div class=\"scheme-info\">\r\n              <h4>Complementary<\/h4>\r\n              <p>Opposite colors<\/p>\r\n            <\/div>\r\n          <\/div>\r\n          <div class=\"scheme-card\">\r\n            <div class=\"scheme-colors\">\r\n              <div class=\"scheme-color\" style=\"background-color: #f5f5f5;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #e0e0e0;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #9e9e9e;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #616161;\"><\/div>\r\n              <div class=\"scheme-color\" style=\"background-color: #212121;\"><\/div>\r\n            <\/div>\r\n            <div class=\"scheme-info\">\r\n              <h4>Triadic<\/h4>\r\n              <p>Three balanced colors<\/p>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      \r\n      <div class=\"color-export\">\r\n        <h3>Export Options<\/h3>\r\n        <div class=\"export-options\">\r\n          <button id=\"copy-css\" class=\"action-btn\">\ud83d\udccb Copy CSS Variables<\/button>\r\n          <button id=\"copy-json\" class=\"action-btn\">\ud83d\udccb Copy JSON<\/button>\r\n          <button id=\"copy-sass\" class=\"action-btn\">\ud83d\udccb Copy SCSS<\/button>\r\n          <button id=\"download-palette\" class=\"action-btn\">\ud83d\udcbe Download Palette<\/button>\r\n        <\/div>\r\n        \r\n        <div class=\"export-code\">\r\n          <textarea id=\"css-variables\" readonly>\r\n:root {\r\n  --color-primary: #ffffff;\r\n  --color-secondary: #f5f5f5;\r\n  --color-accent: #e0e0e0;\r\n}<\/textarea>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n    \r\n    <div class=\"color-theory\">\r\n      <h3>\ud83c\udfa8 Color Theory Basics<\/h3>\r\n      <div class=\"theory-content\">\r\n        <div class=\"theory-card\">\r\n          <h4>Color Harmony<\/h4>\r\n          <p>Combinations that are visually pleasing and create an inner sense of balance.<\/p>\r\n        <\/div>\r\n        <div class=\"theory-card\">\r\n          <h4>Color Psychology<\/h4>\r\n          <p>Different colors evoke different emotions and associations in viewers.<\/p>\r\n        <\/div>\r\n        <div class=\"theory-card\">\r\n          <h4>Accessibility<\/h4>\r\n          <p>Ensure sufficient contrast between text and background colors (minimum 4.5:1).<\/p>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<style>\r\n  .color-extractor-wrapper {\r\n    background-color: var(--bg, #f5f5fa);\r\n    padding: 1rem;\r\n  }\r\n\r\n  .color-extractor {\r\n    max-width: 1200px;\r\n    margin: auto;\r\n    background: var(--bg, #fff);\r\n    border-radius: 10px;\r\n    padding: 25px;\r\n    box-shadow: 0 4px 12px rgba(0,0,0,0.08);\r\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif;\r\n  }\r\n\r\n  .color-extractor h2 {\r\n    text-align: center;\r\n    font-size: 1.8rem;\r\n    color: var(--primary, #0a66c2);\r\n    margin-bottom: 1.5rem;\r\n  }\r\n\r\n  .extractor-container {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 30px;\r\n  }\r\n\r\n  .upload-section {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 20px;\r\n  }\r\n\r\n  .upload-box {\r\n    border: 2px dashed #ccc;\r\n    border-radius: 12px;\r\n    padding: 40px;\r\n    text-align: center;\r\n    cursor: pointer;\r\n    transition: all 0.2s;\r\n    background: #f9f9f9;\r\n  }\r\n\r\n  .upload-box:hover {\r\n    border-color: var(--primary, #0a66c2);\r\n    background: #f0f7ff;\r\n  }\r\n\r\n  .upload-box.drag-over {\r\n    border-color: var(--primary, #0a66c2);\r\n    background: #e6f2ff;\r\n  }\r\n\r\n  .upload-content {\r\n    display: flex;\r\n    flex-direction: column;\r\n    align-items: center;\r\n    gap: 10px;\r\n  }\r\n\r\n  .upload-content svg {\r\n    color: var(--primary, #0a66c2);\r\n  }\r\n\r\n  .upload-content h3 {\r\n    margin: 0;\r\n    font-size: 1.2rem;\r\n    color: #333;\r\n  }\r\n\r\n  .upload-content p {\r\n    margin: 0;\r\n    font-size: 0.9rem;\r\n    color: #666;\r\n  }\r\n\r\n  #image-upload {\r\n    display: none;\r\n  }\r\n\r\n  .upload-controls {\r\n    display: flex;\r\n    flex-wrap: wrap;\r\n    gap: 20px;\r\n  }\r\n\r\n  .control-group {\r\n    flex: 1;\r\n    min-width: 200px;\r\n  }\r\n\r\n  .control-group label {\r\n    display: block;\r\n    margin-bottom: 8px;\r\n    font-size: 0.9rem;\r\n    font-weight: 500;\r\n  }\r\n\r\n  .control-group input[type=\"range\"] {\r\n    width: 100%;\r\n    margin-bottom: 5px;\r\n  }\r\n\r\n  .control-group input[type=\"number\"] {\r\n    width: 60px;\r\n    padding: 8px;\r\n    border: 1px solid #ddd;\r\n    border-radius: 4px;\r\n  }\r\n\r\n  .control-group select {\r\n    width: 100%;\r\n    padding: 8px;\r\n    border: 1px solid #ddd;\r\n    border-radius: 4px;\r\n    font-size: 0.9rem;\r\n  }\r\n\r\n  .action-btn {\r\n    padding: 10px 20px;\r\n    border: none;\r\n    border-radius: 6px;\r\n    background: var(--primary, #0a66c2);\r\n    color: white;\r\n    font-size: 0.9rem;\r\n    cursor: pointer;\r\n    transition: all 0.2s;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 8px;\r\n  }\r\n\r\n  .action-btn:hover {\r\n    background: var(--primary-dark, #084a9e);\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  .action-btn:disabled {\r\n    background: #ccc;\r\n    cursor: not-allowed;\r\n  }\r\n\r\n  .results-section {\r\n    display: grid;\r\n    grid-template-columns: 1fr 1fr;\r\n    gap: 30px;\r\n  }\r\n\r\n  .image-preview-container, .color-palette-container {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 15px;\r\n  }\r\n\r\n  .image-preview-container h3, .color-palette-container h3 {\r\n    margin: 0;\r\n    font-size: 1.1rem;\r\n  }\r\n\r\n  .image-preview {\r\n    background: #f5f5f5;\r\n    border-radius: 8px;\r\n    min-height: 250px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    overflow: hidden;\r\n  }\r\n\r\n  .image-preview img {\r\n    max-width: 100%;\r\n    max-height: 100%;\r\n    object-fit: contain;\r\n  }\r\n\r\n  .image-preview p {\r\n    color: #666;\r\n    text-align: center;\r\n    padding: 20px;\r\n  }\r\n\r\n  .color-palette {\r\n    display: grid;\r\n    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\r\n    gap: 10px;\r\n    min-height: 100px;\r\n    background: #f5f5f5;\r\n    border-radius: 8px;\r\n    padding: 15px;\r\n  }\r\n\r\n  .color-swatch {\r\n    height: 80px;\r\n    border-radius: 6px;\r\n    position: relative;\r\n    overflow: hidden;\r\n    cursor: pointer;\r\n    transition: all 0.2s;\r\n    box-shadow: 0 2px 5px rgba(0,0,0,0.1);\r\n  }\r\n\r\n  .color-swatch:hover {\r\n    transform: translateY(-3px);\r\n    box-shadow: 0 5px 15px rgba(0,0,0,0.2);\r\n  }\r\n\r\n  .color-info {\r\n    position: absolute;\r\n    bottom: 0;\r\n    left: 0;\r\n    right: 0;\r\n    background: rgba(0,0,0,0.7);\r\n    color: white;\r\n    padding: 8px;\r\n    font-size: 0.8rem;\r\n    text-align: center;\r\n  }\r\n\r\n  .empty-state {\r\n    grid-column: 1 \/ -1;\r\n    text-align: center;\r\n    padding: 20px;\r\n    color: #666;\r\n  }\r\n\r\n  .empty-state svg {\r\n    color: #999;\r\n    margin-bottom: 10px;\r\n  }\r\n\r\n  .color-schemes {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 20px;\r\n  }\r\n\r\n  .scheme-grid {\r\n    display: grid;\r\n    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\r\n    gap: 20px;\r\n  }\r\n\r\n  .scheme-card {\r\n    background: white;\r\n    border-radius: 8px;\r\n    overflow: hidden;\r\n    box-shadow: 0 2px 5px rgba(0,0,0,0.1);\r\n    transition: all 0.2s;\r\n  }\r\n\r\n  .scheme-card:hover {\r\n    transform: translateY(-3px);\r\n    box-shadow: 0 5px 15px rgba(0,0,0,0.2);\r\n  }\r\n\r\n  .scheme-colors {\r\n    display: flex;\r\n    height: 60px;\r\n  }\r\n\r\n  .scheme-color {\r\n    flex: 1;\r\n  }\r\n\r\n  .scheme-info {\r\n    padding: 15px;\r\n  }\r\n\r\n  .scheme-info h4 {\r\n    margin: 0 0 5px 0;\r\n    font-size: 1rem;\r\n  }\r\n\r\n  .scheme-info p {\r\n    margin: 0;\r\n    font-size: 0.8rem;\r\n    color: #666;\r\n  }\r\n\r\n  .color-export {\r\n    display: flex;\r\n    flex-direction: column;\r\n    gap: 20px;\r\n  }\r\n\r\n  .export-options {\r\n    display: flex;\r\n    flex-wrap: wrap;\r\n    gap: 10px;\r\n  }\r\n\r\n  #copy-css {\r\n    background: #2196F3;\r\n  }\r\n\r\n  #copy-json {\r\n    background: #4CAF50;\r\n  }\r\n\r\n  #copy-sass {\r\n    background: #9C27B0;\r\n  }\r\n\r\n  #download-palette {\r\n    background: #607D8B;\r\n  }\r\n\r\n  .export-code textarea {\r\n    width: 100%;\r\n    min-height: 100px;\r\n    padding: 15px;\r\n    border: 1px solid #ddd;\r\n    border-radius: 8px;\r\n    font-family: monospace;\r\n    font-size: 0.9rem;\r\n    resize: vertical;\r\n    background: #f5f5f5;\r\n  }\r\n\r\n  .color-theory {\r\n    background: #f9f9f9;\r\n    border-radius: 8px;\r\n    padding: 20px;\r\n    margin-top: 30px;\r\n  }\r\n\r\n  .color-theory h3 {\r\n    margin-top: 0;\r\n    margin-bottom: 15px;\r\n    font-size: 1.2rem;\r\n  }\r\n\r\n  .theory-content {\r\n    display: grid;\r\n    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\r\n    gap: 20px;\r\n  }\r\n\r\n  .theory-card {\r\n    background: white;\r\n    border-radius: 8px;\r\n    padding: 15px;\r\n    box-shadow: 0 2px 5px rgba(0,0,0,0.1);\r\n  }\r\n\r\n  .theory-card h4 {\r\n    margin-top: 0;\r\n    margin-bottom: 10px;\r\n    font-size: 1rem;\r\n    color: var(--primary, #0a66c2);\r\n  }\r\n\r\n  .theory-card p {\r\n    margin: 0;\r\n    font-size: 0.9rem;\r\n    line-height: 1.5;\r\n  }\r\n\r\n  @media (max-width: 768px) {\r\n    .results-section {\r\n      grid-template-columns: 1fr;\r\n    }\r\n    \r\n    .upload-controls {\r\n      flex-direction: column;\r\n    }\r\n    \r\n    .control-group {\r\n      min-width: 100%;\r\n    }\r\n    \r\n    .export-options {\r\n      flex-direction: column;\r\n    }\r\n    \r\n    .action-btn {\r\n      width: 100%;\r\n      justify-content: center;\r\n    }\r\n  }\r\n<\/style>\r\n\r\n<script>\r\ndocument.addEventListener(\"DOMContentLoaded\", function() {\r\n  \/\/ DOM elements\r\n  const dropZone = document.getElementById('drop-zone');\r\n  const fileInput = document.getElementById('image-upload');\r\n  const extractBtn = document.getElementById('extract-colors');\r\n  const colorCount = document.getElementById('color-count');\r\n  const colorCountValue = document.getElementById('color-count-value');\r\n  const algorithmSelect = document.getElementById('algorithm');\r\n  const imagePreview = document.getElementById('image-preview');\r\n  const colorPalette = document.getElementById('color-palette');\r\n  const schemeGrid = document.getElementById('scheme-grid');\r\n  const cssVariables = document.getElementById('css-variables');\r\n  const copyCssBtn = document.getElementById('copy-css');\r\n  const copyJsonBtn = document.getElementById('copy-json');\r\n  const copySassBtn = document.getElementById('copy-sass');\r\n  const downloadBtn = document.getElementById('download-palette');\r\n  \r\n  \/\/ Current image and colors\r\n  let currentImage = null;\r\n  let extractedColors = [];\r\n  \r\n  \/\/ Link range and number inputs\r\n  colorCount.addEventListener('input', function() {\r\n    colorCountValue.value = this.value;\r\n  });\r\n  \r\n  colorCountValue.addEventListener('input', function() {\r\n    colorCount.value = this.value;\r\n  });\r\n  \r\n  \/\/ Handle drag and drop\r\n  dropZone.addEventListener('click', function() {\r\n    fileInput.click();\r\n  });\r\n  \r\n  ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {\r\n    dropZone.addEventListener(eventName, preventDefaults, false);\r\n  });\r\n  \r\n  function preventDefaults(e) {\r\n    e.preventDefault();\r\n    e.stopPropagation();\r\n  }\r\n  \r\n  ['dragenter', 'dragover'].forEach(eventName => {\r\n    dropZone.addEventListener(eventName, highlight, false);\r\n  });\r\n  \r\n  ['dragleave', 'drop'].forEach(eventName => {\r\n    dropZone.addEventListener(eventName, unhighlight, false);\r\n  });\r\n  \r\n  function highlight() {\r\n    dropZone.classList.add('drag-over');\r\n  }\r\n  \r\n  function unhighlight() {\r\n    dropZone.classList.remove('drag-over');\r\n  }\r\n  \r\n  dropZone.addEventListener('drop', handleDrop, false);\r\n  \r\n  function handleDrop(e) {\r\n    const dt = e.dataTransfer;\r\n    const files = dt.files;\r\n    handleFiles(files);\r\n  }\r\n  \r\n  fileInput.addEventListener('change', function() {\r\n    if (this.files.length) {\r\n      handleFiles(this.files);\r\n    }\r\n  });\r\n  \r\n  function handleFiles(files) {\r\n    const file = files[0];\r\n    if (!file.type.match('image.*')) {\r\n      alert('Please upload an image file');\r\n      return;\r\n    }\r\n    \r\n    const reader = new FileReader();\r\n    reader.onload = function(e) {\r\n      const img = new Image();\r\n      img.onload = function() {\r\n        currentImage = img;\r\n        displayImagePreview(img);\r\n        extractBtn.disabled = false;\r\n      };\r\n      img.src = e.target.result;\r\n    };\r\n    reader.readAsDataURL(file);\r\n  }\r\n  \r\n  function displayImagePreview(img) {\r\n    imagePreview.innerHTML = '';\r\n    const imgElement = document.createElement('img');\r\n    imgElement.src = img.src;\r\n    imagePreview.appendChild(imgElement);\r\n  }\r\n  \r\n  \/\/ Extract colors from image\r\n  extractBtn.addEventListener('click', function() {\r\n    if (!currentImage) {\r\n      alert('Please upload an image first');\r\n      return;\r\n    }\r\n    \r\n    extractBtn.disabled = true;\r\n    extractBtn.innerHTML = '<span class=\"spinner\"><\/span> Extracting...';\r\n    \r\n    \/\/ Simulate extraction (in a real implementation, you'd use a proper color extraction library)\r\n    setTimeout(() => {\r\n      extractedColors = extractColorsFromImage(currentImage, parseInt(colorCount.value), algorithmSelect.value);\r\n      displayColorPalette(extractedColors);\r\n      generateColorSchemes(extractedColors);\r\n      generateExportCode(extractedColors);\r\n      \r\n      extractBtn.disabled = false;\r\n      extractBtn.innerHTML = '\u2728 Extract Colors';\r\n    }, 1000);\r\n  });\r\n  \r\n  \/\/ Simulated color extraction (replace with actual implementation)\r\n  function extractColorsFromImage(img, count, algorithm) {\r\n    \/\/ This is a placeholder - in a real implementation you would:\r\n    \/\/ 1. Create a canvas element\r\n    \/\/ 2. Draw the image on the canvas\r\n    \/\/ 3. Get the image data\r\n    \/\/ 4. Use a color extraction algorithm (like k-means clustering)\r\n    \r\n    \/\/ For demo purposes, we'll generate random colors based on the image dimensions\r\n    const colors = [];\r\n    const baseHue = (img.width * img.height) % 360; \/\/ Silly \"algorithm\" based on image size\r\n    \r\n    for (let i = 0; i < count; i++) {\r\n      const hue = (baseHue + (i * 30)) % 360;\r\n      const saturation = 70 + Math.random() * 30;\r\n      const lightness = 40 + Math.random() * 30;\r\n      \r\n      colors.push({\r\n        hex: hslToHex(hue, saturation, lightness),\r\n        rgb: hslToRgb(hue, saturation, lightness),\r\n        hsl: [hue, saturation, lightness]\r\n      });\r\n    }\r\n    \r\n    return colors;\r\n  }\r\n  \r\n  \/\/ Color conversion helpers\r\n  function hslToHex(h, s, l) {\r\n    const rgb = hslToRgb(h, s, l);\r\n    return `#${rgb[0].toString(16).padStart(2, '0')}${rgb[1].toString(16).padStart(2, '0')}${rgb[2].toString(16).padStart(2, '0')}`;\r\n  }\r\n  \r\n  function hslToRgb(h, s, l) {\r\n    h \/= 360;\r\n    s \/= 100;\r\n    l \/= 100;\r\n    \r\n    let r, g, b;\r\n    \r\n    if (s === 0) {\r\n      r = g = b = l;\r\n    } else {\r\n      const hue2rgb = (p, q, t) => {\r\n        if (t < 0) t += 1;\r\n        if (t > 1) t -= 1;\r\n        if (t < 1\/6) return p + (q - p) * 6 * t;\r\n        if (t < 1\/2) return q;\r\n        if (t < 2\/3) return p + (q - p) * (2\/3 - t) * 6;\r\n        return p;\r\n      };\r\n      \r\n      const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\r\n      const p = 2 * l - q;\r\n      \r\n      r = hue2rgb(p, q, h + 1\/3);\r\n      g = hue2rgb(p, q, h);\r\n      b = hue2rgb(p, q, h - 1\/3);\r\n    }\r\n    \r\n    return [\r\n      Math.round(r * 255),\r\n      Math.round(g * 255),\r\n      Math.round(b * 255)\r\n    ];\r\n  }\r\n  \r\n  function displayColorPalette(colors) {\r\n    colorPalette.innerHTML = '';\r\n    \r\n    if (colors.length === 0) {\r\n      colorPalette.innerHTML = '<div class=\"empty-state\"><p>No colors extracted<\/p><\/div>';\r\n      return;\r\n    }\r\n    \r\n    colors.forEach(color => {\r\n      const swatch = document.createElement('div');\r\n      swatch.className = 'color-swatch';\r\n      swatch.style.backgroundColor = color.hex;\r\n      \r\n      const info = document.createElement('div');\r\n      info.className = 'color-info';\r\n      info.textContent = color.hex;\r\n      \r\n      swatch.appendChild(info);\r\n      colorPalette.appendChild(swatch);\r\n      \r\n      \/\/ Add click to copy functionality\r\n      swatch.addEventListener('click', function() {\r\n        navigator.clipboard.writeText(color.hex);\r\n        \r\n        \/\/ Show feedback\r\n        const originalText = info.textContent;\r\n        info.textContent = 'Copied!';\r\n        setTimeout(() => {\r\n          info.textContent = originalText;\r\n        }, 2000);\r\n      });\r\n    });\r\n  }\r\n  \r\n  function generateColorSchemes(colors) {\r\n    if (colors.length === 0) return;\r\n    \r\n    \/\/ In a real implementation, you would generate actual color schemes\r\n    \/\/ based on color theory (complementary, analogous, triadic, etc.)\r\n    \r\n    \/\/ For demo purposes, we'll just show the same colors in different arrangements\r\n    const primaryColor = colors[0].hex;\r\n    \r\n    schemeGrid.innerHTML = '';\r\n    \r\n    const schemes = [\r\n      { name: 'Monochromatic', desc: 'Variations of a single hue' },\r\n      { name: 'Analogous', desc: 'Colors next to each other' },\r\n      { name: 'Complementary', desc: 'Opposite colors' },\r\n      { name: 'Triadic', desc: 'Three balanced colors' }\r\n    ];\r\n    \r\n    schemes.forEach(scheme => {\r\n      const card = document.createElement('div');\r\n      card.className = 'scheme-card';\r\n      \r\n      const schemeColors = document.createElement('div');\r\n      schemeColors.className = 'scheme-colors';\r\n      \r\n      \/\/ Generate colors for the scheme\r\n      for (let i = 0; i < 5; i++) {\r\n        const color = document.createElement('div');\r\n        color.className = 'scheme-color';\r\n        \r\n        \/\/ Generate a color based on the scheme type\r\n        let hexColor;\r\n        if (scheme.name === 'Monochromatic') {\r\n          hexColor = adjustLightness(primaryColor, i * 10);\r\n        } else if (scheme.name === 'Analogous') {\r\n          hexColor = adjustHue(primaryColor, i * 15);\r\n        } else if (scheme.name === 'Complementary') {\r\n          hexColor = i % 2 === 0 ? primaryColor : getComplementary(primaryColor);\r\n        } else {\r\n          hexColor = getTriadic(primaryColor, i);\r\n        }\r\n        \r\n        color.style.backgroundColor = hexColor;\r\n        schemeColors.appendChild(color);\r\n      }\r\n      \r\n      const schemeInfo = document.createElement('div');\r\n      schemeInfo.className = 'scheme-info';\r\n      \r\n      const title = document.createElement('h4');\r\n      title.textContent = scheme.name;\r\n      \r\n      const desc = document.createElement('p');\r\n      desc.textContent = scheme.desc;\r\n      \r\n      schemeInfo.appendChild(title);\r\n      schemeInfo.appendChild(desc);\r\n      \r\n      card.appendChild(schemeColors);\r\n      card.appendChild(schemeInfo);\r\n      \r\n      schemeGrid.appendChild(card);\r\n    });\r\n  }\r\n  \r\n  \/\/ Color manipulation helpers for demo\r\n  function adjustLightness(hex, amount) {\r\n    \/\/ Convert hex to HSL, adjust lightness, then back to hex\r\n    const rgb = hexToRgb(hex);\r\n    const hsl = rgbToHsl(rgb[0], rgb[1], rgb[2]);\r\n    hsl[2] = Math.max(0, Math.min(100, hsl[2] + amount));\r\n    return hslToHex(hsl[0], hsl[1], hsl[2]);\r\n  }\r\n  \r\n  function adjustHue(hex, amount) {\r\n    const rgb = hexToRgb(hex);\r\n    const hsl = rgbToHsl(rgb[0], rgb[1], rgb[2]);\r\n    hsl[0] = (hsl[0] + amount) % 360;\r\n    return hslToHex(hsl[0], hsl[1], hsl[2]);\r\n  }\r\n  \r\n  function getComplementary(hex) {\r\n    const rgb = hexToRgb(hex);\r\n    const hsl = rgbToHsl(rgb[0], rgb[1], rgb[2]);\r\n    hsl[0] = (hsl[0] + 180) % 360;\r\n    return hslToHex(hsl[0], hsl[1], hsl[2]);\r\n  }\r\n  \r\n  function getTriadic(hex, index) {\r\n    const rgb = hexToRgb(hex);\r\n    const hsl = rgbToHsl(rgb[0], rgb[1], rgb[2]);\r\n    hsl[0] = (hsl[0] + (index * 120)) % 360;\r\n    return hslToHex(hsl[0], hsl[1], hsl[2]);\r\n  }\r\n  \r\n  function hexToRgb(hex) {\r\n    const r = parseInt(hex.substr(1, 2), 16);\r\n    const g = parseInt(hex.substr(3, 2), 16);\r\n    const b = parseInt(hex.substr(5, 2), 16);\r\n    return [r, g, b];\r\n  }\r\n  \r\n  function rgbToHsl(r, g, b) {\r\n    r \/= 255, g \/= 255, b \/= 255;\r\n    \r\n    const max = Math.max(r, g, b), min = Math.min(r, g, b);\r\n    let h, s, l = (max + min) \/ 2;\r\n    \r\n    if (max === min) {\r\n      h = s = 0; \/\/ achromatic\r\n    } else {\r\n      const d = max - min;\r\n      s = l > 0.5 ? d \/ (2 - max - min) : d \/ (max + min);\r\n      \r\n      switch (max) {\r\n        case r: h = (g - b) \/ d + (g < b ? 6 : 0); break;\r\n        case g: h = (b - r) \/ d + 2; break;\r\n        case b: h = (r - g) \/ d + 4; break;\r\n      }\r\n      \r\n      h \/= 6;\r\n    }\r\n    \r\n    return [\r\n      Math.round(h * 360),\r\n      Math.round(s * 100),\r\n      Math.round(l * 100)\r\n    ];\r\n  }\r\n  \r\n  function generateExportCode(colors) {\r\n    if (colors.length === 0) {\r\n      cssVariables.value = '\/* No colors to export *\/';\r\n      return;\r\n    }\r\n    \r\n    \/\/ Generate CSS variables\r\n    let cssCode = ':root {\\n';\r\n    colors.forEach((color, index) => {\r\n      const name = index === 0 ? '--color-primary' : \r\n                   index === 1 ? '--color-secondary' : \r\n                   index === 2 ? '--color-accent' : \r\n                   `--color-${index + 1}`;\r\n      cssCode += `  ${name}: ${color.hex};\\n`;\r\n    });\r\n    cssCode += '}';\r\n    \r\n    cssVariables.value = cssCode;\r\n    \r\n    \/\/ Set up copy buttons\r\n    copyCssBtn.addEventListener('click', function() {\r\n      cssVariables.select();\r\n      document.execCommand('copy');\r\n      \r\n      \/\/ Show feedback\r\n      const originalText = copyCssBtn.innerHTML;\r\n      copyCssBtn.innerHTML = '\u2705 Copied!';\r\n      setTimeout(() => {\r\n        copyCssBtn.innerHTML = originalText;\r\n      }, 2000);\r\n    });\r\n    \r\n    copyJsonBtn.addEventListener('click', function() {\r\n      const json = JSON.stringify(colors.map(c => c.hex), null, 2);\r\n      navigator.clipboard.writeText(json);\r\n      \r\n      \/\/ Show feedback\r\n      const originalText = copyJsonBtn.innerHTML;\r\n      copyJsonBtn.innerHTML = '\u2705 Copied!';\r\n      setTimeout(() => {\r\n        copyJsonBtn.innerHTML = originalText;\r\n      }, 2000);\r\n    });\r\n    \r\n    copySassBtn.addEventListener('click', function() {\r\n      let sassCode = '\/\/ Color palette variables\\n';\r\n      colors.forEach((color, index) => {\r\n        const name = index === 0 ? '$color-primary' : \r\n                     index === 1 ? '$color-secondary' : \r\n                     index === 2 ? '$color-accent' : \r\n                     `$color-${index + 1}`;\r\n        sassCode += `${name}: ${color.hex};\\n`;\r\n      });\r\n      \r\n      navigator.clipboard.writeText(sassCode);\r\n      \r\n      \/\/ Show feedback\r\n      const originalText = copySassBtn.innerHTML;\r\n      copySassBtn.innerHTML = '\u2705 Copied!';\r\n      setTimeout(() => {\r\n        copySassBtn.innerHTML = originalText;\r\n      }, 2000);\r\n    });\r\n    \r\n    downloadBtn.addEventListener('click', function() {\r\n      const blob = new Blob([cssVariables.value], {type: 'text\/css'});\r\n      const url = URL.createObjectURL(blob);\r\n      \r\n      const a = document.createElement('a');\r\n      a.href = url;\r\n      a.download = 'color-palette.css';\r\n      document.body.appendChild(a);\r\n      a.click();\r\n      document.body.removeChild(a);\r\n      URL.revokeObjectURL(url);\r\n    });\r\n  }\r\n  \r\n  \/\/ Initialize with disabled extract button\r\n  extractBtn.disabled = true;\r\n});\r\n<\/script>","protected":false},"excerpt":{"rendered":"<p>\ud83c\udfa8 Color Palette Extractor Drag &#038; Drop Image or click to browse files Number of colors: Extraction method: K-Means Clustering Vibrant Colors Median Cut \u2728 Extract Colors Image Preview Your image will appear here Extracted Color Palette Upload an image to extract colors Suggested Color Schemes Monochromatic Variations of a single hue Analogous Colors next [&hellip;]<\/p>\n<\/p><div class=\"more-link\"><a href=\"https:\/\/ingenio.vip\/zh\/tools-pages\/color-palette-extractor\/\" class=\"btn btn-small btn--dark btn-hover-shadow\"><span class=\"text\">Continue Reading<\/span><i class=\"seoicon-right-arrow\"><\/i><\/a><\/div>","protected":false},"author":1,"featured_media":0,"menu_order":0,"template":"elementor_header_footer","meta":{"_acf_changed":false,"googlesitekit_rrm_CAowrpbbCw:productID":"","footnotes":""},"tools-categories":[],"class_list":["post-4438","tools-pages","type-tools-pages","status-publish","hentry"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/ingenio.vip\/zh\/wp-json\/wp\/v2\/tools-pages\/4438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ingenio.vip\/zh\/wp-json\/wp\/v2\/tools-pages"}],"about":[{"href":"https:\/\/ingenio.vip\/zh\/wp-json\/wp\/v2\/types\/tools-pages"}],"author":[{"embeddable":true,"href":"https:\/\/ingenio.vip\/zh\/wp-json\/wp\/v2\/users\/1"}],"version-history":[{"count":1,"href":"https:\/\/ingenio.vip\/zh\/wp-json\/wp\/v2\/tools-pages\/4438\/revisions"}],"predecessor-version":[{"id":4439,"href":"https:\/\/ingenio.vip\/zh\/wp-json\/wp\/v2\/tools-pages\/4438\/revisions\/4439"}],"wp:attachment":[{"href":"https:\/\/ingenio.vip\/zh\/wp-json\/wp\/v2\/media?parent=4438"}],"wp:term":[{"taxonomy":"tools-categories","embeddable":true,"href":"https:\/\/ingenio.vip\/zh\/wp-json\/wp\/v2\/tools-categories?post=4438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}