BYPASS SHELL BY ./RAZORGANZ
Server: nginx/1.20.1
System: Linux iZdzfnv9mwfppeZ 5.10.134-19.2.al8.x86_64 #1 SMP Wed Oct 29 22:47:09 CST 2025 x86_64
User: apache (48)
PHP: 8.2.30
Disabled: NONE
Upload Files
File: /var/www/html/private/上传图片能识别文字字体.html
<script type="text/javascript">
        var gk_isXlsx = false;
        var gk_xlsxFileLookup = {};
        var gk_fileData = {};
        function filledCell(cell) {
          return cell !== '' && cell != null;
        }
        function loadFileData(filename) {
        if (gk_isXlsx && gk_xlsxFileLookup[filename]) {
            try {
                var workbook = XLSX.read(gk_fileData[filename], { type: 'base64' });
                var firstSheetName = workbook.SheetNames[0];
                var worksheet = workbook.Sheets[firstSheetName];

                // Convert sheet to JSON to filter blank rows
                var jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, blankrows: false, defval: '' });
                // Filter out blank rows (rows where all cells are empty, null, or undefined)
                var filteredData = jsonData.filter(row => row.some(filledCell));

                // Heuristic to find the header row by ignoring rows with fewer filled cells than the next row
                var headerRowIndex = filteredData.findIndex((row, index) =>
                  row.filter(filledCell).length >= filteredData[index + 1]?.filter(filledCell).length
                );
                // Fallback
                if (headerRowIndex === -1 || headerRowIndex > 25) {
                  headerRowIndex = 0;
                }

                // Convert filtered JSON back to CSV
                var csv = XLSX.utils.aoa_to_sheet(filteredData.slice(headerRowIndex)); // Create a new sheet from filtered array of arrays
                csv = XLSX.utils.sheet_to_csv(csv, { header: 1 });
                return csv;
            } catch (e) {
                console.error(e);
                return "";
            }
        }
        return gk_fileData[filename] || "";
        }
        </script><!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图片文字与字体识别</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            line-height: 1.6;
        }
        .container {
            text-align: center;
        }
        #preview {
            max-width: 100%;
            max-height: 400px;
            margin: 20px 0;
            display: none;
        }
        #result {
            text-align: left;
            margin-top: 20px;
            padding: 15px;
            border: 1px solid #ccc;
            border-radius: 5px;
        }
        #loading {
            display: none;
            margin: 20px 0;
        }
        .text-segment {
            margin-bottom: 10px;
            padding: 10px;
            border-bottom: 1px solid #eee;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>图片文字与字体识别</h1>
        <input type="file" id="imageInput" accept="image/*">
        <div>
            <img id="preview" src="" alt="图片预览">
        </div>
        <div id="loading">处理中,请稍候...</div>
        <div id="result"></div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/tesseract.js@5.0.0/dist/tesseract.min.js"></script>
    <script>
        const imageInput = document.getElementById('imageInput');
        const preview = document.getElementById('preview');
        const result = document.getElementById('result');
        const loading = document.getElementById('loading');

        // 语言与常用字体库映射
        const languageFonts = {
            'eng': [
                'Arial', 'Helvetica', 'Times New Roman', 'Courier New',
                'Verdana', 'Georgia', 'Palatino Linotype', 'Garamond',
                'Bookman Old Style', 'Trebuchet MS', 'Arial Black', 'Impact',
                'Calibri', 'Roboto', 'Open Sans', 'Lato'
            ],
            'chi_sim': [
                'SimSun', 'Microsoft YaHei', 'KaiTi', 'FangSong',
                'Noto Serif CJK SC', 'STHeiti', 'PingFang SC',
                'Source Han Sans CN', 'DengXian', 'SimHei'
            ],
            'jpn': [
                'MS Gothic', 'MS Mincho', 'Yu Gothic', 'Noto Serif CJK JP',
                'Meiryo', 'Hiragino Kaku Gothic Pro', 'Source Han Sans JP',
                'MS PGothic', 'Yu Mincho', 'Sawarabi Mincho'
            ],
            'kor': [
                'Malgun Gothic', 'Batang', 'Noto Serif CJK KR', 'Gulim',
                'Dotum', 'Nanum Gothic', 'Nanum Myeongjo', 'Source Han Sans KR',
                'HYGoThic', 'Apple SD Gothic Neo'
            ]
        };

        // 语言检测函数(基于字符范围)
        function detectLanguage(text) {
            const charPatterns = {
                'chi_sim': /[\u4e00-\u9fff]/, // 中文简体
                'jpn': /[\u3040-\u30ff\u31f0-\u31ff]/, // 日文
                'kor': /[\uac00-\ud7af]/, // 韩文
                'eng': /[A-Za-z0-9]/ // 英文
            };

            let detectedLang = 'eng';
            let maxMatches = 0;

            for (const [lang, pattern] of Object.entries(charPatterns)) {
                const matches = (text.match(pattern) || []).length;
                if (matches > maxMatches) {
                    maxMatches = matches;
                    detectedLang = lang;
                }
            }

            return detectedLang;
        }

        imageInput.addEventListener('change', async (event) => {
            const file = event.target.files[0];
            if (!file) {
                preview.style.display = 'none';
                result.innerHTML = '<p>请选择一张图片</p>';
                return;
            }

            // 显示预览图片
            try {
                const reader = new FileReader();
                reader.onload = (e) => {
                    preview.src = e.target.result;
                    preview.style.display = 'block';
                };
                reader.readAsDataURL(file);
            } catch (error) {
                preview.style.display = 'none';
                result.innerHTML = `<p>图片加载失败: ${error.message}</p>`;
                return;
            }

            loading.style.display = 'block';
            result.innerHTML = '';

            try {
                // 尝试多种语言识别
                const languages = ['eng', 'chi_sim', 'jpn', 'kor'];
                let bestText = '';
                let detectedLang = 'eng';
                let maxConfidence = 0;

                for (const lang of languages) {
                    const { data: { text, confidence } } = await Tesseract.recognize(file, lang, {
                        logger: (m) => console.log(m)
                    });

                    if (confidence > maxConfidence && text.trim()) {
                        maxConfidence = confidence;
                        bestText = text;
                        detectedLang = lang;
                    }
                }

                if (!bestText.trim()) {
                    loading.style.display = 'none';
                    preview.style.display = 'block';
                    result.innerHTML = '<p>未检测到文字</p>';
                    return;
                }

                // 进一步优化语言检测
                detectedLang = detectLanguage(bestText);

                // 分割文本为段落(按换行符)
                const textSegments = bestText.split('\n').filter(segment => segment.trim());

                // 为每个文本段分配可能的字体
                const textFontPairs = textSegments.map((segment, index) => ({
                    text: segment,
                    fonts: detectFonts(detectedLang, index)
                }));

                loading.style.display = 'none';

                // 显示结果
                result.innerHTML = `
                    <h3>识别结果</h3>
                    <p><strong>检测到的语言:</strong> ${detectedLang === 'eng' ? '英文' : 
                        detectedLang === 'chi_sim' ? '中文简体' : 
                        detectedLang === 'jpn' ? '日文' : '韩文'}</p>
                    <p><strong>文字与字体对应:</strong></p>
                    ${textFontPairs.map(pair => `
                        <div class="text-segment">
                            <p><strong>文本 ${pair.text.length > 30 ? pair.text.substring(0, 30) + '...' : pair.text}:</strong></p>
                            <p>${pair.text}</p>
                            <p><strong>可能的字体:</strong></p>
                            <ul>${pair.fonts.map(font => `<li>${font}</li>`).join('')}</ul>
                        </div>
                    `).join('')}
                `;
            } catch (error) {
                loading.style.display = 'none';
                result.innerHTML = `<p>错误: ${error.message}</p>`;
            }
        });

        function detectFonts(lang, segmentIndex) {
            // 获取语言对应的字体库
            const fonts = languageFonts[lang] || languageFonts['eng'];
            const detected = [];

            // 模拟字体匹配:根据段落索引循环选择常用字体
            // 实际应用中应使用图像分析或外部API
            if (lang === 'eng') {
                detected.push(fonts[segmentIndex % 4]); // 循环选择前4种常用字体:Arial, Helvetica, Times New Roman, Roboto
            } else if (lang === 'chi_sim') {
                detected.push(fonts[segmentIndex % 3]); // 循环选择前3种:SimSun, Microsoft YaHei, PingFang SC
            } else if (lang === 'jpn') {
                detected.push(fonts[segmentIndex % 3]); // 循环选择前3种:MS Gothic, Yu Gothic, MS Mincho
            } else if (lang === 'kor') {
                detected.push(fonts[segmentIndex % 3]); // 循环选择前3种:Malgun Gothic, Nanum Gothic, Batang
            }

            // 去重并限制在语言相关字体列表内
            return [...new Set(detected)].filter(font => fonts.includes(font));
        }
    </script>
</body>
</html>