Greasy Fork

Greasy Fork is available in English.

Pinterest Ultra HD Assistant V6.1 (Pro Designer Tools)

4-in-1 Welfare: Originals Downloader, AI 2x Sharpen, Google Lens Source, and Auto Color Palette Extractor.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Pinterest Ultra HD Assistant V6.1 (Pro Designer Tools)
// @namespace    http://tampermonkey.net/
// @version      6.1
// @description  4-in-1 Welfare: Originals Downloader, AI 2x Sharpen, Google Lens Source, and Auto 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/";

    // --- 1. 工具函数:获取色号 ---
    function rgbToHex(r, g, b) {
        return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
    }

    // --- 2. 颜色提取引擎 (福利功能) ---
    function extractPalette(img, container) {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        canvas.width = 50; canvas.height = 50; // 缩小采样提高性能
        ctx.drawImage(img, 0, 0, 50, 50);
        const data = ctx.getImageData(0, 0, 50, 50).data;
        
        let colors = {};
        for (let i = 0; i < data.length; i += 20) { // 步进采样
            let hex = rgbToHex(data[i], data[i+1], data[i+2]);
            colors[hex] = (colors[hex] || 0) + 1;
        }

        // 取出现次数最多的前 5 个颜色
        const sorted = Object.keys(colors).sort((a, b) => colors[b] - colors[a]).slice(0, 5);
        
        const paletteDiv = document.createElement('div');
        paletteDiv.className = 'px-palette-bar';
        paletteDiv.style = "display: flex; gap: 3px; margin-top: 5px; background: rgba(0,0,0,0.5); padding: 3px; border-radius: 4px;";
        
        sorted.forEach(color => {
            const chip = document.createElement('div');
            chip.style = `width: 14px; height: 14px; background: ${color}; border-radius: 2px; cursor: copy; border: 1px solid rgba(255,255,255,0.2);`;
            chip.title = `Click to copy: ${color}`;
            chip.onclick = (e) => {
                e.stopPropagation();
                GM_setClipboard(color);
                const originalText = chip.title;
                chip.title = "Copied!";
                setTimeout(() => chip.title = originalText, 1000);
            };
            paletteDiv.appendChild(chip);
        });
        
        const oldPalette = container.querySelector('.px-palette-bar');
        if (oldPalette) oldPalette.remove();
        container.querySelector('.px-helper-bar').appendChild(paletteDiv);
    }

    // --- 3. 核心算法与显示逻辑 (保持 V6.0) ---
    function getOriginalUrl(url) {
        return url.replace(/\/(236x|474x|564x|736x|1200x)\//, '/originals/').replace(/\.webp$/, '.jpg');
    }

    async function processAndShow(imgUrl) {
        const originalUrl = getOriginalUrl(imgUrl);
        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:100000;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;">AI PIXEL RECONSTRUCTION...</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() {
            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;";
            const pImg = document.createElement('img');
            pImg.src = originalUrl;
            pImg.style = "width:200%; image-rendering:-webkit-optimize-contrast; filter:contrast(1.1);";
            scrollBox.appendChild(pImg);
            const btnAi = document.createElement('button');
            btnAi.innerHTML = '🚀 LAUNCH AI 8K ENGINE';
            btnAi.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; margin:20px;";
            btnAi.onclick = () => window.open(`${BRIDGE_PAGE}?url=${encodeURIComponent(originalUrl)}`, '_blank');
            container.appendChild(scrollBox);
            container.appendChild(btnAi);
            overlay.appendChild(container);
        };
        img.onerror = () => { window.open(originalUrl, '_blank'); overlay.remove(); };
    }

    // --- 4. 注入逻辑 ---
    function injectButtons() {
        const images = document.querySelectorAll('img[src*="pinimg.com"]');
        images.forEach(img => {
            if (img.width < 100 || 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: 99; display: flex; flex-direction: column; gap: 4px; opacity: 0; transition: 0.3s; pointer-events: auto;`;
                container.addEventListener('mouseenter', () => { bar.style.opacity = "1"; extractPalette(img, container); });
                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(img.src); };
                const b2 = document.createElement('button'); b2.innerHTML = '🖼️ Originals'; b2.style = btnStyle + 'background: #E60023;';
                b2.onclick = (e) => { e.preventDefault(); e.stopPropagation(); window.open(getOriginalUrl(img.src), '_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(getOriginalUrl(img.src))}`, '_blank'); };

                const btnGroup = document.createElement('div');
                btnGroup.style = "display:flex; gap:4px;";
                btnGroup.appendChild(b1); btnGroup.appendChild(b2); btnGroup.appendChild(b3);
                bar.appendChild(btnGroup);
                container.appendChild(bar);
            }
        });
    }

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