Greasy Fork

Greasy Fork is available in English.

Pinterest Ultra Assistant V6.2 (Color Fix)

Bilingual UI, AI 2x Sharpen, Source Finder, and RELIABLE Color Palette Extractor.

当前为 2025-12-30 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Pinterest Ultra Assistant V6.2 (Color Fix)
// @namespace    http://tampermonkey.net/
// @version      6.2
// @description  Bilingual UI, AI 2x Sharpen, Source Finder, and RELIABLE Color Palette Extractor.
// @author       Pi Xiao
// @match        https://*.pinterest.com/*
// @grant        GM_openInTab
// @grant        GM_setClipboard
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const BRIDGE_PAGE = "https://meishubiji.cn/ai-processing-center/";

    function rgbToHex(r, g, b) {
        return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
    }

    // --- 核心:提取色盘功能 ---
    function getPalette(ctx, w, h) {
        const data = ctx.getImageData(0, 0, w, h).data;
        let colors = {};
        for (let i = 0; i < data.length; i += 200) { // 采样
            let hex = rgbToHex(data[i], data[i+1], data[i+2]);
            colors[hex] = (colors[hex] || 0) + 1;
        }
        return Object.keys(colors).sort((a, b) => colors[b] - colors[a]).slice(0, 6);
    }

    // --- 智能增强弹窗 + 色盘生成 ---
    async function processAndShow(imgUrl) {
        const originalUrl = imgUrl.replace(/\/(236x|474x|564x|736x|1200x)\//, '/originals/').replace(/\.webp$/, '.jpg');
        const overlay = document.createElement('div');
        overlay.style = "position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.95);z-index:2147483647;display:flex;flex-direction:column;align-items:center;justify-content:center;color:white;font-family:sans-serif;cursor:zoom-out;";
        overlay.innerHTML = '<div style="text-align:center;"><div class="px-spinner"></div><div style="margin-top:15px; font-size:14px; color:#00ffcc;">ANALYZING PIXELS & COLORS...</div></div><style>.px-spinner { width:30px; height:30px; border:2px solid rgba(0,255,204,0.1); border-top-color:#00ffcc; border-radius:50%; animation:spin .8s linear infinite; margin:0 auto; } @keyframes spin { to { transform:rotate(360deg); } }</style>';
        overlay.onclick = () => overlay.remove();
        document.body.appendChild(overlay);

        const img = new Image();
        img.crossOrigin = "Anonymous";
        img.src = originalUrl;
        img.onload = function() {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            canvas.width = img.width * 2; canvas.height = img.height * 2;
            
            // 简单的对比度增强算法
            ctx.imageSmoothingQuality = 'high';
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
            
            // 提取色盘 (由于有了 crossOrigin,这里 100% 成功)
            const palette = getPalette(ctx, canvas.width, canvas.height);

            overlay.innerHTML = "";
            const container = document.createElement('div');
            container.style = "text-align:center; width:95%; height:90vh; display:flex; flex-direction:column; cursor:default;";
            container.onclick = (e) => e.stopPropagation();
            
            const scrollBox = document.createElement('div');
            scrollBox.style = "overflow:auto; border:1px solid #333; border-radius:12px; flex:1; background:#050505;";
            canvas.style.display = "block"; canvas.style.margin = "0 auto";
            scrollBox.appendChild(canvas);

            // --- 底部工具栏:包含色盘和跳转按钮 ---
            const bar = document.createElement('div');
            bar.style = "padding:20px; display:flex; flex-direction:column; align-items:center; gap:15px;";
            
            // 色盘 HTML
            let paletteHTML = `<div style="display:flex; gap:10px; align-items:center;">
                <span style="font-size:12px; color:#888; text-transform:uppercase;">Color Palette:</span>`;
            palette.forEach(color => {
                paletteHTML += `<div class="px-color" style="width:24px; height:24px; background:${color}; border-radius:50%; cursor:pointer; border:2px solid #333;" title="Click to copy: ${color}" data-hex="${color}"></div>`;
            });
            paletteHTML += `</div>`;
            
            const actionHTML = `
                <div style="display:flex; gap:15px; align-items:center;">
                    <button id="btn-ai-go" style="background:linear-gradient(45deg, #6a11cb 0%, #2575fc 100%); color:white; border:none; padding:12px 35px; border-radius:50px; font-size:15px; font-weight:bold; cursor:pointer; box-shadow:0 10px 25px rgba(37,117,252,0.4);">🚀 LAUNCH AI 8K ENGINE</button>
                    <span style="color:#444; cursor:pointer;" onclick="this.closest('#px-overlay').remove()">Close Preview ×</span>
                </div>
            `;

            bar.innerHTML = paletteHTML + actionHTML;
            container.appendChild(scrollBox);
            container.appendChild(bar);
            overlay.id = "px-overlay";
            overlay.appendChild(container);

            // 绑定颜色点击事件
            overlay.querySelectorAll('.px-color').forEach(el => {
                el.onclick = () => {
                    const hex = el.getAttribute('data-hex');
                    GM_setClipboard(hex);
                    const oldBg = el.style.borderColor;
                    el.style.borderColor = "#00ffcc";
                    setTimeout(() => el.style.borderColor = oldBg, 500);
                };
            });

            overlay.querySelector('#btn-ai-go').onclick = () => window.open(`${BRIDGE_PAGE}?url=${encodeURIComponent(originalUrl)}`, '_blank');
        };
        img.onerror = () => { window.open(originalUrl, '_blank'); overlay.remove(); };
    }

    function injectButtons() {
        const images = document.querySelectorAll('img');
        images.forEach(img => {
            const src = img.src;
            if (!src || !src.includes('pinimg.com') || img.width < 150 || img.closest('.px-helper-bar')) return;
            const container = img.closest('[data-test-id="pin-visual-wrapper"]') || img.closest('[data-test-id="visual-content-container"]') || img.parentElement;
            if (container) {
                if (window.getComputedStyle(container).position === 'static') container.style.position = 'relative';
                const bar = document.createElement('div');
                bar.className = 'px-helper-bar';
                bar.style = "position:absolute; top:10px; left:10px; z-index:1000; display:flex; gap:4px; opacity:0; transition:0.3s; pointer-events:auto;";
                container.addEventListener('mouseenter', () => bar.style.opacity = "1");
                container.addEventListener('mouseleave', () => bar.style.opacity = "0");
                const btnStyle = 'color:white; border:none; border-radius:4px; cursor:pointer; padding:4px 8px; font-weight:bold; font-size:9px; box-shadow:0 2px 5px rgba(0,0,0,0.3); white-space:nowrap;';
                const b1 = document.createElement('button'); b1.innerHTML = '🪄 2x HD'; b1.style = btnStyle + 'background:#00BFFF;';
                b1.onclick = (e) => { e.preventDefault(); e.stopPropagation(); processAndShow(src); };
                const b2 = document.createElement('button'); b2.innerHTML = '🖼️ Originals'; b2.style = btnStyle + 'background:#E60023;';
                b2.onclick = (e) => { e.preventDefault(); e.stopPropagation(); window.open(src.replace(/\/(236x|474x|564x|736x)\//, '/originals/'), '_blank'); };
                const b3 = document.createElement('button'); b3.innerHTML = '🔍 Source'; b3.style = btnStyle + 'background:#34a853;';
                b3.onclick = (e) => { e.preventDefault(); e.stopPropagation(); window.open(`https://lens.google.com/uploadbyurl?url=${encodeURIComponent(src.replace(/\/(236x|474x|564x|736x)\//, '/originals/'))}`, '_blank'); };
                bar.appendChild(b1); bar.appendChild(b2); bar.appendChild(b3);
                container.appendChild(bar);
            }
        });
    }

    setInterval(injectButtons, 2500);
    const observer = new MutationObserver(injectButtons);
    observer.observe(document.body, { childList: true, subtree: true });
})();