joermd commited on
Commit
ddc6b50
·
verified ·
1 Parent(s): 0e35c8a

Create ocr.html

Browse files
Files changed (1) hide show
  1. ocr.html +868 -0
ocr.html ADDED
@@ -0,0 +1,868 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>مكتب الريحان للترجمة المعتمدة - نظام OCR</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.min.js"></script>
9
+ <style>
10
+ body {
11
+ font-family: Arial, sans-serif;
12
+ margin: 0;
13
+ padding: 20px;
14
+ background-color: #f8f9fa;
15
+ }
16
+ .header {
17
+ background-color: #3b82f6;
18
+ color: white;
19
+ padding: 15px;
20
+ border-radius: 10px;
21
+ margin-bottom: 20px;
22
+ text-align: center;
23
+ }
24
+ .container {
25
+ max-width: 800px;
26
+ margin: 0 auto;
27
+ }
28
+ .card {
29
+ background-color: white;
30
+ border-radius: 10px;
31
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
32
+ padding: 20px;
33
+ margin-bottom: 20px;
34
+ }
35
+ .pdf-grid {
36
+ display: grid;
37
+ grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
38
+ gap: 10px;
39
+ margin-top: 15px;
40
+ }
41
+ .pdf-page {
42
+ border: 1px solid #ddd;
43
+ border-radius: 5px;
44
+ padding: 5px;
45
+ position: relative;
46
+ cursor: pointer;
47
+ transition: all 0.2s;
48
+ }
49
+ .pdf-page:hover {
50
+ transform: translateY(-3px);
51
+ box-shadow: 0 3px 10px rgba(0,0,0,0.1);
52
+ }
53
+ .pdf-page.selected {
54
+ border: 2px solid #3b82f6;
55
+ }
56
+ .pdf-page img {
57
+ width: 100%;
58
+ height: auto;
59
+ border-radius: 3px;
60
+ }
61
+ .page-number {
62
+ position: absolute;
63
+ bottom: 0;
64
+ left: 0;
65
+ right: 0;
66
+ background-color: rgba(0,0,0,0.6);
67
+ color: white;
68
+ text-align: center;
69
+ font-size: 12px;
70
+ padding: 2px;
71
+ }
72
+ .btn-primary {
73
+ background-color: #3b82f6;
74
+ border-color: #3b82f6;
75
+ }
76
+ .btn-success {
77
+ background-color: #10b981;
78
+ border-color: #10b981;
79
+ }
80
+ .result-text {
81
+ max-height: 300px;
82
+ overflow-y: auto;
83
+ white-space: pre-wrap;
84
+ direction: rtl;
85
+ border: 1px solid #ddd;
86
+ padding: 10px;
87
+ border-radius: 5px;
88
+ background-color: #f8f9fa;
89
+ }
90
+ .spinner-border {
91
+ width: 1.5rem;
92
+ height: 1.5rem;
93
+ margin-left: 0.5rem;
94
+ }
95
+ .logo {
96
+ font-weight: bold;
97
+ font-size: 24px;
98
+ display: inline-block;
99
+ margin-bottom: 5px;
100
+ }
101
+ .logo span {
102
+ color: #bfdbfe;
103
+ }
104
+ .stats-badge {
105
+ background-color: #3b82f6;
106
+ color: white;
107
+ font-size: 14px;
108
+ padding: 5px 10px;
109
+ border-radius: 20px;
110
+ margin-right: 10px;
111
+ }
112
+ .stats-container {
113
+ display: flex;
114
+ align-items: center;
115
+ margin-bottom: 15px;
116
+ }
117
+ .page-preview {
118
+ margin-bottom: 10px;
119
+ border: 1px solid #ddd;
120
+ border-radius: 5px;
121
+ padding: 10px;
122
+ }
123
+ .page-preview h4 {
124
+ background-color: #f0f8ff;
125
+ padding: 5px;
126
+ border-radius: 3px;
127
+ margin-bottom: 10px;
128
+ }
129
+ </style>
130
+ </head>
131
+ <body>
132
+ <div class="container">
133
+ <div class="header">
134
+ <div class="logo">مكتب <span>الريحان</span></div>
135
+ <h1>نظام التعرف الضوئي على النصوص</h1>
136
+ <p class="mb-0">للترجمة المعتمدة - استخراج النصوص من الصور والملفات متعددة الصفحات</p>
137
+ </div>
138
+
139
+ <!-- بطاقة الإحصائيات -->
140
+ <div class="card" id="statsCard">
141
+ <h3>إحصائيات النظام</h3>
142
+ <div class="stats-container">
143
+ <div class="stats-badge">
144
+ عدد الصفحات المعالجة: <span id="ocrCounter">0</span>
145
+ </div>
146
+ <div class="stats-badge">
147
+ تاريخ آخر معالجة: <span id="lastOcrDate">-</span>
148
+ </div>
149
+ </div>
150
+ </div>
151
+
152
+ <!-- بطاقة تحميل الملف -->
153
+ <div class="card">
154
+ <h3>تحميل الملف</h3>
155
+ <div class="mb-3">
156
+ <input type="file" class="form-control" id="fileInput" accept=".pdf,.jpg,.jpeg,.png">
157
+ <div class="form-text">يمكنك تحميل ملف PDF (حتى 100 صفحة) أو صورة</div>
158
+ </div>
159
+ <button id="processBtn" class="btn btn-primary">معالجة الملف</button>
160
+ </div>
161
+
162
+ <!-- عرض حالة المعالجة -->
163
+ <div id="processingStatus" class="card d-none">
164
+ <h3>حالة المعالجة</h3>
165
+ <div class="alert alert-info">
166
+ <div class="d-flex align-items-center">
167
+ <div class="spinner-border text-primary" role="status"></div>
168
+ <span id="statusText" class="ms-2">جاري معالجة الملف...</span>
169
+ </div>
170
+ </div>
171
+ <div class="progress mt-2">
172
+ <div id="progressBar" class="progress-bar" role="progressbar" style="width: 0%"></div>
173
+ </div>
174
+ </div>
175
+
176
+ <!-- عرض صفحات PDF -->
177
+ <div id="pdfPagesCard" class="card d-none">
178
+ <h3>صفحات الملف</h3>
179
+ <p>اختر الصفحات التي تريد معالجتها (انقر للتحديد)</p>
180
+
181
+ <div class="mb-3">
182
+ <button id="selectAllBtn" class="btn btn-sm btn-outline-primary me-2">تحديد الكل</button>
183
+ <button id="deselectAllBtn" class="btn btn-sm btn-outline-secondary">إلغاء تحديد الكل</button>
184
+ </div>
185
+
186
+ <div id="pdfPagesContainer" class="pdf-grid"></div>
187
+
188
+ <div class="mt-3">
189
+ <button id="extractImagesBtn" class="btn btn-success me-2">تحويل إلى صور</button>
190
+ <button id="extractTextBtn" class="btn btn-primary">استخراج النص</button>
191
+ </div>
192
+ </div>
193
+
194
+ <!-- عرض النتائج -->
195
+ <div id="resultsCard" class="card d-none">
196
+ <h3>النص المستخرج</h3>
197
+ <div id="resultPreview"></div>
198
+ <div id="resultText" class="result-text mt-3">
199
+ لم يتم استخراج نص بعد.
200
+ </div>
201
+ <div class="mt-3">
202
+ <button id="copyTextBtn" class="btn btn-outline-primary me-2">نسخ النص</button>
203
+ <button id="downloadTextBtn" class="btn btn-success me-2">تنزيل النص</button>
204
+ <button id="downloadWordBtn" class="btn btn-success">تنزيل النص إلى Word</button>
205
+ </div>
206
+ </div>
207
+ </div>
208
+
209
+ <script>
210
+ // تهيئة PDF.js
211
+ pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.worker.min.js';
212
+
213
+ // إعدادات API4AI OCR
214
+ const RAPIDAPI_KEY = 'eb11693cddmshb8bd157e05b74acp1f6aa4jsn4369fa546e55';
215
+ const OCR_API_URL = 'https://ocr43.p.rapidapi.com/v1/results';
216
+
217
+ // متغيرات عامة
218
+ let documentPages = [];
219
+ let selectedPages = [];
220
+ let extractedTexts = [];
221
+ let extractedPageNumbers = [];
222
+ let ocrPagesCount = 0; // عداد لعدد الصفحات المعالجة
223
+
224
+ // استرداد العداد من localStorage عند تحميل الصفحة
225
+ document.addEventListener('DOMContentLoaded', function() {
226
+ const savedCount = localStorage.getItem('ocrPagesCount');
227
+ const lastDate = localStorage.getItem('lastOcrDate');
228
+
229
+ if (savedCount) {
230
+ ocrPagesCount = parseInt(savedCount);
231
+ document.getElementById('ocrCounter').textContent = ocrPagesCount;
232
+ }
233
+
234
+ if (lastDate) {
235
+ document.getElementById('lastOcrDate').textContent = lastDate;
236
+ }
237
+ });
238
+
239
+ // عناصر DOM
240
+ const fileInput = document.getElementById('fileInput');
241
+ const processBtn = document.getElementById('processBtn');
242
+ const processingStatus = document.getElementById('processingStatus');
243
+ const statusText = document.getElementById('statusText');
244
+ const progressBar = document.getElementById('progressBar');
245
+ const pdfPagesCard = document.getElementById('pdfPagesCard');
246
+ const pdfPagesContainer = document.getElementById('pdfPagesContainer');
247
+ const selectAllBtn = document.getElementById('selectAllBtn');
248
+ const deselectAllBtn = document.getElementById('deselectAllBtn');
249
+ const extractImagesBtn = document.getElementById('extractImagesBtn');
250
+ const extractTextBtn = document.getElementById('extractTextBtn');
251
+ const resultsCard = document.getElementById('resultsCard');
252
+ const resultText = document.getElementById('resultText');
253
+ const resultPreview = document.getElementById('resultPreview');
254
+ const copyTextBtn = document.getElementById('copyTextBtn');
255
+ const downloadTextBtn = document.getElementById('downloadTextBtn');
256
+ const downloadWordBtn = document.getElementById('downloadWordBtn');
257
+ const ocrCounter = document.getElementById('ocrCounter');
258
+ const lastOcrDate = document.getElementById('lastOcrDate');
259
+
260
+ // إضافة مستمعات الأحداث
261
+ document.addEventListener('DOMContentLoaded', function() {
262
+ processBtn.addEventListener('click', processFile);
263
+ selectAllBtn.addEventListener('click', selectAllPages);
264
+ deselectAllBtn.addEventListener('click', deselectAllPages);
265
+ extractImagesBtn.addEventListener('click', extractImages);
266
+ extractTextBtn.addEventListener('click', extractText);
267
+ copyTextBtn.addEventListener('click', copyText);
268
+ downloadTextBtn.addEventListener('click', downloadText);
269
+ downloadWordBtn.addEventListener('click', downloadWord);
270
+ });
271
+
272
+ // تحديث عداد OCR
273
+ function updateOcrCounter(count) {
274
+ ocrPagesCount += count;
275
+ ocrCounter.textContent = ocrPagesCount;
276
+
277
+ // حفظ العداد في localStorage
278
+ localStorage.setItem('ocrPagesCount', ocrPagesCount);
279
+
280
+ // تحديث تاريخ آخر معالجة
281
+ const now = new Date();
282
+ const formattedDate = `${now.getFullYear()}-${(now.getMonth()+1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')} ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
283
+
284
+ lastOcrDate.textContent = formattedDate;
285
+ localStorage.setItem('lastOcrDate', formattedDate);
286
+ }
287
+
288
+ // معالجة الملف
289
+ async function processFile() {
290
+ if (!fileInput.files || fileInput.files.length === 0) {
291
+ alert('الرجاء اختيار ملف أولاً');
292
+ return;
293
+ }
294
+
295
+ const file = fileInput.files[0];
296
+
297
+ // إظهار حالة المعالجة
298
+ processingStatus.classList.remove('d-none');
299
+ statusText.textContent = 'جاري معالجة الملف...';
300
+ progressBar.style.width = '0%';
301
+
302
+ // إخفاء بطاقات أخرى
303
+ pdfPagesCard.classList.add('d-none');
304
+ resultsCard.classList.add('d-none');
305
+
306
+ // إفراغ مصفوفات الصفحات
307
+ documentPages = [];
308
+ selectedPages = [];
309
+ extractedTexts = [];
310
+ extractedPageNumbers = [];
311
+
312
+ try {
313
+ const fileType = file.name.split('.').pop().toLowerCase();
314
+
315
+ if (fileType === 'pdf') {
316
+ await processPdf(file);
317
+ } else if (['jpg', 'jpeg', 'png'].includes(fileType)) {
318
+ await processImage(file);
319
+ } else {
320
+ throw new Error('نوع الملف غير مدعوم. يرجى اختيار ملف PDF أو صورة.');
321
+ }
322
+
323
+ // إظهار بطاقة صفحات PDF
324
+ pdfPagesCard.classList.remove('d-none');
325
+
326
+ // إخفاء حالة المعالجة
327
+ processingStatus.classList.add('d-none');
328
+
329
+ } catch (error) {
330
+ console.error('Error processing file:', error);
331
+ statusText.textContent = `خطأ: ${error.message}`;
332
+ }
333
+ }
334
+
335
+ // معالجة ملف PDF
336
+ async function processPdf(file) {
337
+ try {
338
+ // تحميل ملف PDF
339
+ const arrayBuffer = await file.arrayBuffer();
340
+ const pdfDoc = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
341
+
342
+ // التحقق من عدد الصفحات
343
+ const numPages = pdfDoc.numPages;
344
+ if (numPages > 100) {
345
+ alert('هذا الملف يحتوي على أكثر من 100 صفحة. سيتم معالجة أول 100 صفحة فقط.');
346
+ }
347
+
348
+ // مسح حاوية الصفحات
349
+ pdfPagesContainer.innerHTML = '';
350
+
351
+ // عرض أول 100 صفحة كصور مصغرة
352
+ const maxPages = Math.min(numPages, 100);
353
+ for (let i = 1; i <= maxPages; i++) {
354
+ // تحديث شريط التقدم
355
+ progressBar.style.width = `${(i / maxPages) * 100}%`;
356
+ statusText.textContent = `جاري معالجة الصفحة ${i} من ${maxPages}...`;
357
+
358
+ // تحويل الصفحة إلى صورة
359
+ const pageImage = await convertPdfPageToImage(pdfDoc, i);
360
+
361
+ // إضافة الصفحة إلى المصفوفة
362
+ documentPages.push({
363
+ pageNumber: i,
364
+ imageData: pageImage.imageData,
365
+ width: pageImage.width,
366
+ height: pageImage.height
367
+ });
368
+
369
+ // إنشاء عنصر للصفحة في واجهة المستخدم
370
+ createPageElement(pageImage.imageData, i);
371
+ }
372
+
373
+ } catch (error) {
374
+ console.error('Error processing PDF:', error);
375
+ throw error;
376
+ }
377
+ }
378
+
379
+ // معالجة ملف صورة
380
+ async function processImage(file) {
381
+ try {
382
+ // قراءة الصورة كـ Data URL
383
+ const imageData = await readFileAsDataURL(file);
384
+
385
+ // إنشاء صورة لقياس أبعادها
386
+ const img = new Image();
387
+ await new Promise((resolve, reject) => {
388
+ img.onload = resolve;
389
+ img.onerror = reject;
390
+ img.src = imageData;
391
+ });
392
+
393
+ // مسح حاوية الصفحات
394
+ pdfPagesContainer.innerHTML = '';
395
+
396
+ // إضافة الصورة إلى المصفوفة
397
+ documentPages = [{
398
+ pageNumber: 1,
399
+ imageData: imageData,
400
+ width: img.width,
401
+ height: img.height
402
+ }];
403
+
404
+ // إنشاء عنصر للصورة في واجهة المستخدم
405
+ createPageElement(imageData, 1);
406
+
407
+ // تحديث شريط التقدم
408
+ progressBar.style.width = '100%';
409
+ statusText.textContent = 'تمت معالجة الصورة بنجاح';
410
+
411
+ } catch (error) {
412
+ console.error('Error processing image:', error);
413
+ throw error;
414
+ }
415
+ }
416
+
417
+ // تحويل صفحة PDF إلى صورة
418
+ async function convertPdfPageToImage(pdfDoc, pageNumber, scale = 1.5) {
419
+ try {
420
+ // الحصول على الصفحة من مستند PDF
421
+ const page = await pdfDoc.getPage(pageNumber);
422
+
423
+ // إنشاء عنصر canvas لرسم الصفحة
424
+ const canvas = document.createElement('canvas');
425
+ const context = canvas.getContext('2d');
426
+
427
+ // ضبط حجم الـ canvas بناءً على حجم الصفحة ومقياس التكبير
428
+ const viewport = page.getViewport({ scale });
429
+ canvas.width = viewport.width;
430
+ canvas.height = viewport.height;
431
+
432
+ // رسم الصفحة على الـ canvas
433
+ await page.render({
434
+ canvasContext: context,
435
+ viewport: viewport
436
+ }).promise;
437
+
438
+ // تحويل الـ canvas إلى صورة بصيغة PNG
439
+ return {
440
+ imageData: canvas.toDataURL('image/png'),
441
+ width: viewport.width,
442
+ height: viewport.height,
443
+ pageNumber: pageNumber
444
+ };
445
+ } catch (error) {
446
+ console.error(`Error converting PDF page ${pageNumber} to image:`, error);
447
+ throw error;
448
+ }
449
+ }
450
+
451
+ // إنشاء عنصر للصفحة في واجهة المستخدم
452
+ function createPageElement(imageData, pageNumber) {
453
+ const pageDiv = document.createElement('div');
454
+ pageDiv.className = 'pdf-page';
455
+ pageDiv.dataset.page = pageNumber;
456
+
457
+ const img = document.createElement('img');
458
+ img.src = imageData;
459
+ img.alt = `صفحة ${pageNumber}`;
460
+
461
+ const pageNumberDiv = document.createElement('div');
462
+ pageNumberDiv.className = 'page-number';
463
+ pageNumberDiv.textContent = `صفحة ${pageNumber}`;
464
+
465
+ pageDiv.appendChild(img);
466
+ pageDiv.appendChild(pageNumberDiv);
467
+
468
+ // إضافة حدث النقر للتحديد
469
+ pageDiv.addEventListener('click', function() {
470
+ this.classList.toggle('selected');
471
+
472
+ // تحديث مصفوفة الصفحات المحددة
473
+ const page = parseInt(this.dataset.page);
474
+ if (this.classList.contains('selected')) {
475
+ if (!selectedPages.includes(page)) {
476
+ selectedPages.push(page);
477
+ }
478
+ } else {
479
+ const index = selectedPages.indexOf(page);
480
+ if (index > -1) {
481
+ selectedPages.splice(index, 1);
482
+ }
483
+ }
484
+ });
485
+
486
+ pdfPagesContainer.appendChild(pageDiv);
487
+ }
488
+
489
+ // قراءة ملف كـ Data URL
490
+ function readFileAsDataURL(file) {
491
+ return new Promise((resolve, reject) => {
492
+ const reader = new FileReader();
493
+ reader.onload = e => resolve(e.target.result);
494
+ reader.onerror = reject;
495
+ reader.readAsDataURL(file);
496
+ });
497
+ }
498
+
499
+ // تحديد كل الصفحات
500
+ function selectAllPages() {
501
+ document.querySelectorAll('.pdf-page').forEach(page => {
502
+ page.classList.add('selected');
503
+ const pageNumber = parseInt(page.dataset.page);
504
+ if (!selectedPages.includes(pageNumber)) {
505
+ selectedPages.push(pageNumber);
506
+ }
507
+ });
508
+ }
509
+
510
+ // إلغاء تحديد كل الصفحات
511
+ function deselectAllPages() {
512
+ document.querySelectorAll('.pdf-page').forEach(page => {
513
+ page.classList.remove('selected');
514
+ });
515
+ selectedPages = [];
516
+ }
517
+
518
+ // استخراج الصور
519
+ function extractImages() {
520
+ if (documentPages.length === 0) {
521
+ alert('لا توجد صفحات للمعالجة');
522
+ return;
523
+ }
524
+
525
+ // اختيار الصفحات المحددة فقط أو كل الصفحات إذا لم يتم تحديد أي صفحة
526
+ const pagesToExtract = selectedPages.length > 0
527
+ ? documentPages.filter(page => selectedPages.includes(page.pageNumber))
528
+ : documentPages;
529
+
530
+ if (pagesToExtract.length === 0) {
531
+ alert('الرجاء تحديد صفحة واحدة على الأقل');
532
+ return;
533
+ }
534
+
535
+ // إنشاء وتنزيل كل صورة
536
+ pagesToExtract.forEach(page => {
537
+ const a = document.createElement('a');
538
+ a.href = page.imageData;
539
+ a.download = `alrihan_page_${page.pageNumber}.png`;
540
+ document.body.appendChild(a);
541
+ a.click();
542
+ document.body.removeChild(a);
543
+ });
544
+
545
+ // إظهار رسالة نجاح
546
+ alert(`تم استخراج ${pagesToExtract.length} صورة بنجاح`);
547
+ }
548
+
549
+ // استخراج النص
550
+ async function extractText() {
551
+ if (documentPages.length === 0) {
552
+ alert('لا توجد صفحات للمعالجة');
553
+ return;
554
+ }
555
+
556
+ // اختيار الصفحات المحددة فقط أو كل الصفحات إذا لم يتم تحديد أي صفحة
557
+ const pagesToProcess = selectedPages.length > 0
558
+ ? documentPages.filter(page => selectedPages.includes(page.pageNumber))
559
+ : documentPages;
560
+
561
+ if (pagesToProcess.length === 0) {
562
+ alert('الرجاء تحديد صفحة واحدة على الأقل');
563
+ return;
564
+ }
565
+
566
+ // إظهار حالة المعالجة
567
+ processingStatus.classList.remove('d-none');
568
+ statusText.textContent = 'جاري استخراج النص...';
569
+ progressBar.style.width = '0%';
570
+
571
+ try {
572
+ extractedTexts = [];
573
+ extractedPageNumbers = [];
574
+
575
+ // معالجة كل صفحة
576
+ for (let i = 0; i < pagesToProcess.length; i++) {
577
+ const page = pagesToProcess[i];
578
+
579
+ // تحديث التقدم
580
+ progressBar.style.width = `${((i + 1) / pagesToProcess.length) * 100}%`;
581
+ statusText.textContent = `جاري معالجة الصفحة ${i + 1} من ${pagesToProcess.length}...`;
582
+
583
+ // استخراج النص من الصورة باستخدام OCR API
584
+ const pageText = await extractTextFromImage(page.imageData, page.pageNumber);
585
+ extractedTexts.push(pageText);
586
+ extractedPageNumbers.push(page.pageNumber);
587
+ }
588
+
589
+ // تحديث عداد OCR
590
+ updateOcrCounter(pagesToProcess.length);
591
+
592
+ // جمع النصوص المستخرجة - حفظ تنسيق الصفوف كما هي
593
+ const combinedText = extractedTexts.join('\n\n');
594
+
595
+ // عرض النص المستخرج
596
+ resultText.textContent = combinedText;
597
+
598
+ // عرض معاينة مرئية منظمة للصفحات
599
+ generateResultPreview();
600
+
601
+ resultsCard.classList.remove('d-none');
602
+
603
+ // إخفاء حالة المعالجة
604
+ processingStatus.classList.add('d-none');
605
+
606
+ // التمرير إلى النتائج
607
+ resultsCard.scrollIntoView({ behavior: 'smooth' });
608
+
609
+ } catch (error) {
610
+ console.error('Error extracting text:', error);
611
+ statusText.textContent = `خطأ: ${error.message}`;
612
+ }
613
+ }
614
+
615
+ // إنشاء معاينة منظمة للنتائج
616
+ function generateResultPreview() {
617
+ resultPreview.innerHTML = '';
618
+
619
+ if (extractedTexts.length === 0) {
620
+ return;
621
+ }
622
+
623
+ // عرض أول ثلاث صفحات كمعاينة
624
+ const previewPages = Math.min(extractedTexts.length, 3);
625
+
626
+ for (let i = 0; i < previewPages; i++) {
627
+ const pageText = extractedTexts[i];
628
+ const pageNumber = extractedPageNumbers[i];
629
+
630
+ // إنشاء معاينة للصفحة
631
+ const previewDiv = document.createElement('div');
632
+ previewDiv.className = 'page-preview';
633
+
634
+ const pageTitle = document.createElement('h4');
635
+ pageTitle.textContent = `صفحة ${pageNumber}`;
636
+
637
+ const textPreview = document.createElement('p');
638
+ // عرض أول 100 حرف من كل صفحة
639
+ const textContent = pageText.replace(`=== صفحة ${pageNumber} ===\n`, '');
640
+ textPreview.textContent = textContent.length > 100 ?
641
+ textContent.substring(0, 100) + '...' :
642
+ textContent;
643
+
644
+ previewDiv.appendChild(pageTitle);
645
+ previewDiv.appendChild(textPreview);
646
+ resultPreview.appendChild(previewDiv);
647
+ }
648
+
649
+ // إضافة رسالة إذا كان هناك المزيد من الصفحات
650
+ if (extractedTexts.length > 3) {
651
+ const morePages = document.createElement('p');
652
+ morePages.className = 'text-muted';
653
+ morePages.textContent = `+ ${extractedTexts.length - 3} صفحات أخرى...`;
654
+ resultPreview.appendChild(morePages);
655
+ }
656
+ }
657
+
658
+ // استخراج النص من صورة باستخدام API4AI OCR
659
+ async function extractTextFromImage(imageData, pageNumber) {
660
+ try {
661
+ // تحويل Data URL إلى Blob
662
+ const response = await fetch(imageData);
663
+ const blob = await response.blob();
664
+
665
+ // إنشاء FormData وإضافة الصورة
666
+ const formData = new FormData();
667
+ formData.append('image', blob, `page_${pageNumber}.png`);
668
+
669
+ // طلب OCR
670
+ const ocrResponse = await fetch(OCR_API_URL, {
671
+ method: 'POST',
672
+ headers: {
673
+ 'X-RapidAPI-Key': RAPIDAPI_KEY,
674
+ 'X-RapidAPI-Host': 'ocr43.p.rapidapi.com'
675
+ },
676
+ body: formData
677
+ });
678
+
679
+ if (!ocrResponse.ok) {
680
+ throw new Error(`فشل في طلب OCR: ${ocrResponse.status}`);
681
+ }
682
+
683
+ const data = await ocrResponse.json();
684
+
685
+ try {
686
+ // استخراج النص من الاستجابة مع الحفاظ على تنسيق الصفوف
687
+ const text = data.results[0].entities[0].objects[0].entities[0].text;
688
+ return `=== صفحة ${pageNumber} ===\n${text}`;
689
+ } catch (e) {
690
+ console.error('Error parsing OCR response:', e);
691
+ return `=== صفحة ${pageNumber} ===\n[خطأ في معالجة النص]`;
692
+ }
693
+ } catch (error) {
694
+ console.error(`Error in OCR for page ${pageNumber}:`, error);
695
+ throw error;
696
+ }
697
+ }
698
+
699
+ // نسخ النص
700
+ function copyText() {
701
+ const text = resultText.textContent;
702
+ if (!text || text === 'لم يتم استخراج نص بعد.') {
703
+ alert('لا يوجد نص للنسخ');
704
+ return;
705
+ }
706
+
707
+ navigator.clipboard.writeText(text)
708
+ .then(() => alert('تم نسخ النص بنجاح'))
709
+ .catch(err => alert('حدث خطأ أثناء نسخ النص: ' + err));
710
+ }
711
+
712
+ // تنزيل النص
713
+ function downloadText() {
714
+ const text = resultText.textContent;
715
+ if (!text || text === 'لم يتم استخراج نص بعد.') {
716
+ alert('لا يوجد نص للتنزيل');
717
+ return;
718
+ }
719
+
720
+ const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
721
+ const url = URL.createObjectURL(blob);
722
+ const a = document.createElement('a');
723
+ a.href = url;
724
+ a.download = 'alrihan_ocr_text.txt';
725
+ document.body.appendChild(a);
726
+ a.click();
727
+ document.body.removeChild(a);
728
+ URL.revokeObjectURL(url);
729
+ }
730
+
731
+ // تنزيل النص إلى Word بصورة منظمة ومقسمة مع الحفاظ على تنسيق الصفوف
732
+ function downloadWord() {
733
+ const text = resultText.textContent;
734
+ if (!text || text === 'لم يتم استخراج نص بعد.') {
735
+ alert('لا يوجد نص للتنزيل');
736
+ return;
737
+ }
738
+
739
+ // تقسيم النص إلى صفحات بناءً على علامات الصفحات
740
+ const pageTexts = [];
741
+ let currentPageText = '';
742
+ const lines = text.split('\n');
743
+
744
+ for (let i = 0; i < lines.length; i++) {
745
+ const line = lines[i];
746
+
747
+ // إذا كان السطر يشير إلى بداية صفحة جديدة
748
+ if (line.startsWith('=== صفحة ') && line.endsWith(' ===')) {
749
+ // إذا كان هناك نص تم استخراجه بالفعل، قم بإضافته إلى المصفوفة
750
+ if (currentPageText) {
751
+ pageTexts.push(currentPageText);
752
+ currentPageText = '';
753
+ }
754
+
755
+ // ابدأ النص الجديد بعنوان الصفحة
756
+ currentPageText = line + '\n';
757
+ } else {
758
+ // إضافة السطر إلى النص الحالي
759
+ currentPageText += line + '\n';
760
+ }
761
+ }
762
+
763
+ // إضافة آخر صفحة
764
+ if (currentPageText) {
765
+ pageTexts.push(currentPageText);
766
+ }
767
+
768
+ // إنشاء مستند Word
769
+ let wordContent = `
770
+ <!DOCTYPE html>
771
+ <html xmlns:o='urn:schemas-microsoft-com:office:office'
772
+ xmlns:w='urn:schemas-microsoft-com:office:word'
773
+ xmlns='http://www.w3.org/TR/REC-html40'>
774
+ <head>
775
+ <meta charset='utf-8'>
776
+ <title>مكتب الريحان للترجمة المعتمدة - نص OCR</title>
777
+ <style>
778
+ @page {
779
+ size: 21cm 29.7cm;
780
+ margin: 2cm;
781
+ }
782
+ body {
783
+ font-family: 'Arial', sans-serif;
784
+ direction: rtl;
785
+ text-align: right;
786
+ }
787
+ .page-title {
788
+ font-size: 18px;
789
+ font-weight: bold;
790
+ color: #3b82f6;
791
+ margin-bottom: 15px;
792
+ padding-bottom: 5px;
793
+ border-bottom: 1px solid #ccc;
794
+ }
795
+ .page-content {
796
+ margin-bottom: 15px;
797
+ line-height: 1.5;
798
+ page-break-after: always;
799
+ white-space: pre-wrap;
800
+ }
801
+ .footer {
802
+ font-size: 10px;
803
+ text-align: center;
804
+ color: #666;
805
+ margin-top: 20px;
806
+ }
807
+ .header {
808
+ text-align: center;
809
+ margin-bottom: 20px;
810
+ }
811
+ .header h1 {
812
+ color: #3b82f6;
813
+ margin-bottom: 5px;
814
+ }
815
+ .date {
816
+ font-size: 12px;
817
+ color: #666;
818
+ }
819
+ </style>
820
+ </head>
821
+ <body>
822
+ <div class="header">
823
+ <h1>مكتب الريحان للترجمة المعتمدة - نص مستخرج بتقنية OCR</h1>
824
+ <div class="date">تاريخ الاستخراج: ${new Date().toLocaleDateString('ar-EG')}</div>
825
+ </div>
826
+ `;
827
+
828
+ // إضافة كل صفحة إلى المستند مع الحفاظ على تنسيق الصفوف
829
+ pageTexts.forEach((pageText, index) => {
830
+ // استخراج رقم الصفحة من العنوان
831
+ const titleMatch = pageText.match(/=== صفحة (\d+) ===/);
832
+ const pageNumber = titleMatch ? titleMatch[1] : (index + 1);
833
+
834
+ // استبدال عنوان الصفحة بتنسيق أفضل
835
+ const formattedPageText = pageText.replace(/=== صفحة \d+ ===\n/, '');
836
+
837
+ // إضافة صفحة جديدة إلى المستند، مع تحويل أسطر النص إلى <br> للحفاظ على التنسيق
838
+ wordContent += `
839
+ <div class="page-content">
840
+ <div class="page-title">صفحة ${pageNumber}</div>
841
+ <div>${formattedPageText.replace(/\n/g, '<br>')}</div>
842
+ </div>
843
+ `;
844
+ });
845
+
846
+ // إضافة تذييل المستند
847
+ wordContent += `
848
+ <div class="footer">
849
+ تم إنشاء هذا المستند بواسطة نظام مكتب الريحان للترجمة المعتمدة للتعرف الضوئي على النصوص
850
+ </div>
851
+ </body>
852
+ </html>
853
+ `;
854
+
855
+ // تنزيل المستند
856
+ const blob = new Blob(['\ufeff', wordContent], { type: 'application/msword' });
857
+ const url = URL.createObjectURL(blob);
858
+ const a = document.createElement('a');
859
+ a.href = url;
860
+ a.download = 'alrihan_ocr_text.doc';
861
+ document.body.appendChild(a);
862
+ a.click();
863
+ document.body.removeChild(a);
864
+ URL.revokeObjectURL(url);
865
+ }
866
+ </script>
867
+ </body>
868
+ </html>