Greasy Fork

Greasy Fork is available in English.

AI Image Assistant: Pinterest/ArtStation/IG Matrix V5.9

Bilingual UI, Smart AI 2x Sharpen, and Source Finder. Optimized for ArtStation & IG performance.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         AI Image Assistant: Pinterest/ArtStation/IG Matrix V5.9
// @namespace    http://tampermonkey.net/
// @version      5.9
// @description  Bilingual UI, Smart AI 2x Sharpen, and Source Finder. Optimized for ArtStation & IG performance.
// @author       Pi Xiao
// @match        https://*.pinterest.com/*
// @match        https://*.artstation.com/*
// @match        https://*.instagram.com/*
// @grant        GM_openInTab
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

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

    // --- 1. 原图解析 ---
    function getOriginalUrl(img) {
        let url = img.src;
        if (!url) return "";
        const host = location.host;

        if (host.includes('pinterest.com')) {
            return url.replace(/\/(236x|474x|564x|736x|1200x)\//, '/originals/').replace(/\.webp$/, '.jpg');
        } 
        if (host.includes('artstation.com')) {
            // A站原图通常就在 /original/ 目录下
            return url.replace(/\/(large|medium|small|2k|4k|micro_square|small_square)\//, '/original/');
        }
        if (host.includes('instagram.com')) {
            if (img.srcset) {
                const sets = img.srcset.split(',').map(s => s.trim().split(' '));
                return sets[sets.length - 1][0];
            }
        }
        return url;
    }

    // --- 2. 核心算法 (保持 V5.6 逻辑) ---
    function smartProcess(canvas, ctx, img) {
        const w = canvas.width, h = canvas.height;
        ctx.imageSmoothingQuality = 'high';
        ctx.drawImage(img, 0, 0, w, h);
        let imageData = ctx.getImageData(0, 0, w, h);
        let data = imageData.data;
        for (let i = 0; i < data.length; i += 4) {
            data[i] += (data[i] - 128) * 0.5;
            data[i+1] += (data[i+1] - 128) * 0.5;
            data[i+2] += (data[i+2] - 128) * 0.5;
        }
        ctx.putImageData(imageData, 0, 0);
        ctx.globalCompositeOperation = 'overlay';
        ctx.globalAlpha = 0.2;
        ctx.drawImage(canvas, 0, 0);
    }

    // --- 3. 增强弹窗逻辑 ---
    async function processAndShow(imgElement) {
        const originalUrl = getOriginalUrl(imgElement);
        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;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;">RECONSTRUCTING...</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:pxspin .8s linear infinite; margin:0 auto; } @keyframes pxspin { 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;
            smartProcess(canvas, ctx, img);
            overlay.innerHTML = "";
            const scrollBox = document.createElement('div');
            scrollBox.style = "overflow:auto; border:1px solid #333; border-radius:12px; flex:1; background:#050505; width:90%;";
            canvas.style.display = "block"; canvas.style.margin = "0 auto";
            scrollBox.appendChild(canvas);
            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:15px 40px; border-radius:50px; font-size:16px; font-weight:bold; cursor:pointer; margin:20px;";
            btnAi.onclick = () => window.open(`${BRIDGE_PAGE}?url=${encodeURIComponent(originalUrl)}`, '_blank');
            overlay.appendChild(scrollBox);
            overlay.appendChild(btnAi);
        };
        img.onerror = () => { window.open(originalUrl, '_blank'); overlay.remove(); };
    }

    // --- 4. 优化后的注入逻辑 ---
    let isInjecting = false;
    function injectButtons() {
        if (isInjecting) return;
        isInjecting = true;

        const images = document.querySelectorAll('img');
        images.forEach(img => {
            const src = img.src;
            if (!src || img.width < 150 || img.closest('.px-helper-bar')) return;
            
            // 针对 ArtStation 优化容器查找,防止破坏原有布局
            const container = img.closest('.artwork-image-container') || 
                              img.closest('.Project-image-container') ||
                              img.closest('[data-test-id="pin-visual-wrapper"]') ||
                              img.closest('._aagv') || 
                              (location.host.includes('artstation') ? img.parentElement : null);

            if (container) {
                // 仅当容器没有相对定位时才添加,减少 DOM 操作
                const currentStyle = window.getComputedStyle(container);
                if (currentStyle.position === 'static') {
                    container.style.setProperty('position', 'relative', 'important');
                }

                const bar = document.createElement('div');
                bar.className = 'px-helper-bar';
                bar.style = "position:absolute; top:10px; left:10px; z-index:999; display:flex; gap:4px; opacity:0; transition:0.2s; 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:3px 6px; font-weight:bold; font-size:9px; box-shadow:0 2px 4px 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); };

                const b2 = document.createElement('button');
                b2.innerHTML = '🖼️ Originals'; b2.style = btnStyle + 'background:#E60023;';
                b2.onclick = (e) => { e.preventDefault(); e.stopPropagation(); window.open(getOriginalUrl(img), '_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))}`, '_blank'); };

                bar.appendChild(b1); bar.appendChild(b2); bar.appendChild(b3);
                container.appendChild(bar);
            }
        });
        isInjecting = false;
    }

    // 使用 RequestAnimationFrame 优化,不在加载阶段抢资源
    window.addEventListener('load', () => {
        setInterval(injectButtons, 3000);
        const observer = new MutationObserver(injectButtons);
        observer.observe(document.body, { childList: true, subtree: true });
    });
})();