// ==UserScript== // @name Image Paster // @namespace http://tampermonkey.net/ // @version 4.0 // @description Paste images to OWOT using quadrants with direct writeCharToXY at cursor position // @author soyim // @match https://www.ourworldoftext.com/* // @match https://ourworldoftext.com/* // @grant none // @run-at document-end // ==/UserScript== //paste at cursor //set dimensions (function() { 'use strict'; window.addEventListener('load', function() { console.log('OWOT Image Paster (Octant Direct) loading...'); setTimeout(initImagePaster, 1000); }); function initImagePaster() { // Octant character map - 8 triangular sectors per character // Sectors arranged: [1][2] // [3][4] // [5][6] // [7][8] const OCTANT_CHARS = [ ' ', // 00000000: None '๐บจ', // 00000001: Sector 1 '๐บซ', // 00000010: Sector 2 '๐ฎ', // 00000011: Sectors 1,2 '๐ด', // 00000100: Sector 3 'โ', // 00000101: Sectors 1,3 '๐ด', // 00000110: Sectors 2,3 '๐ด', // 00000111: Sectors 1,2,3 '๐ด', // 00001000: Sector 4 '๐ด', // 00001001: Sectors 1,4 'โ', // 00001010: Sectors 2,4 '๐ด ', // 00001011: Sectors 1,2,4 '๐ด', // 00001100: Sectors 3,4 '๐ด', // 00001101: Sectors 1,3,4 '๐ด', // 00001110: Sectors 2,3,4 'โ', // 00001111: Sectors 1,2,3,4 '๐ด', // 00010000: Sector 5 '๐ด', // 00010001: Sectors 1,5 '๐ด', // 00010010: Sectors 2,5 '๐ด', // 00010011: Sectors 1,2,5 '๐ฏฆ', // 00010100: Sectors 3,5 '๐ด', // 00010101: Sectors 1,3,5 '๐ด', // 00010110: Sectors 2,3,5 '๐ด', // 00010111: Sectors 1,2,3,5 '๐ด', // 00011000: Sectors 4,5 '๐ด', // 00011001: Sectors 1,4,5 '๐ด', // 00011010: Sectors 2,4,5 '๐ด', // 00011011: Sectors 1,2,4,5 '๐ด', // 00011100: Sectors 3,4,5 '๐ด', // 00011101: Sectors 1,3,4,5 '๐ด', // 00011110: Sectors 2,3,4,5 '๐ด', // 00011111: Sectors 1,2,3,4,5 '๐ด', // 00100000: Sector 6 '๐ด', // 00100001: Sectors 1,6 '๐ด', // 00100010: Sectors 2,6 '๐ด', // 00100011: Sectors 1,2,6 '๐ด', // 00100100: Sectors 3,6 '๐ด', // 00100101: Sectors 1,3,6 '๐ด', // 00100110: Sectors 2,3,6 '๐ด', // 00100111: Sectors 1,2,3,6 '๐ฏง', // 00101000: Sectors 4,6 '๐ด ', // 00101001: Sectors 1,4,6 '๐ดก', // 00101010: Sectors 2,4,6 '๐ดข', // 00101011: Sectors 1,2,4,6 '๐ดฃ', // 00101100: Sectors 3,4,6 '๐ดค', // 00101101: Sectors 1,3,4,6 '๐ดฅ', // 00101110: Sectors 2,3,4,6 '๐ดฆ', // 00101111: Sectors 1,2,3,4,6 '๐ดง', // 00110000: Sectors 5,6 '๐ดจ', // 00110001: Sectors 1,5,6 '๐ดฉ', // 00110010: Sectors 2,5,6 '๐ดช', // 00110011: Sectors 1,2,5,6 '๐ดซ', // 00110100: Sectors 3,5,6 '๐ดฌ', // 00110101: Sectors 1,3,5,6 '๐ดญ', // 00110110: Sectors 2,3,5,6 '๐ดฎ', // 00110111: Sectors 1,2,3,5,6 '๐ดฏ', // 00111000: Sectors 4,5,6 '๐ดฐ', // 00111001: Sectors 1,4,5,6 '๐ดฑ', // 00111010: Sectors 2,4,5,6 '๐ดฒ', // 00111011: Sectors 1,2,4,5,6 '๐ดณ', // 00111100: Sectors 3,4,5,6 '๐ดด', // 00111101: Sectors 1,3,4,5,6 '๐ดต', // 00111110: Sectors 2,3,4,5,6 '๐ฎ ', // 00111111: Sectors 1,2,3,4,5,6 '๐บฃ', // 01000000: Sector 7 '๐ดถ', // 01000001: Sectors 1,7 '๐ดท', // 01000010: Sectors 2,7 '๐ดธ', // 01000011: Sectors 1,2,7 '๐ดน', // 01000100: Sectors 3,7 '๐ดบ', // 01000101: Sectors 1,3,7 '๐ดป', // 01000110: Sectors 2,3,7 '๐ดผ', // 01000111: Sectors 1,2,3,7 '๐ดฝ', // 01001000: Sectors 4,7 '๐ดพ', // 01001001: Sectors 1,4,7 '๐ดฟ', // 01001010: Sectors 2,4,7 '๐ต', // 01001011: Sectors 1,2,4,7 '๐ต', // 01001100: Sectors 3,4,7 '๐ต', // 01001101: Sectors 1,3,4,7 '๐ต', // 01001110: Sectors 2,3,4,7 '๐ต', // 01001111: Sectors 1,2,3,4,7 'โ', // 01010000: Sectors 5,7 '๐ต ', // 01010001: Sectors 1,5,7 '๐ต', // 01010010: Sectors 2,5,7 '๐ต', // 01010011: Sectors 1,2,5,7 '๐ต', // 01010100: Sectors 3,5,7 'โ', // 01010101: Sectors 1,3,5,7 (left half) '๐ต', // 01010110: Sectors 2,3,5,7 '๐ต', // 01010111: Sectors 1,2,3,5,7 '๐ต', // 01011000: Sectors 4,5,7 '๐ต', // 01011001: Sectors 1,4,5,7 'โ', // 01011010: Sectors 2,4,5,7 '๐ต', // 01011011: Sectors 1,2,4,5,7 '๐ต', // 01011100: Sectors 3,4,5,7 '๐ต', // 01011101: Sectors 1,3,4,5,7 '๐ต', // 01011110: Sectors 2,3,4,5,7 'โ', // 01011111: Sectors 1,2,3,4,5,7 '๐ต', // 01100000: Sectors 6,7 '๐ต', // 01100001: Sectors 1,6,7 '๐ต', // 01100010: Sectors 2,6,7 '๐ต', // 01100011: Sectors 1,2,6,7 '๐ต', // 01100100: Sectors 3,6,7 '๐ต', // 01100101: Sectors 1,3,6,7 '๐ต', // 01100110: Sectors 2,3,6,7 '๐ต', // 01100111: Sectors 1,2,3,6,7 '๐ต', // 01101000: Sectors 4,6,7 '๐ต', // 01101001: Sectors 1,4,6,7 '๐ต', // 01101010: Sectors 2,4,6,7 '๐ต', // 01101011: Sectors 1,2,4,6,7 '๐ต', // 01101100: Sectors 3,4,6,7 '๐ต', // 01101101: Sectors 1,3,4,6,7 '๐ต', // 01101110: Sectors 2,3,4,6,7 '๐ต ', // 01101111: Sectors 1,2,3,4,6,7 '๐ตก', // 01110000: Sectors 5,6,7 '๐ตข', // 01110001: Sectors 1,5,6,7 '๐ตฃ', // 01110010: Sectors 2,5,6,7 '๐ตค', // 01110011: Sectors 1,2,5,6,7 '๐ตฅ', // 01110100: Sectors 3,5,6,7 '๐ตฆ', // 01110101: Sectors 1,3,5,6,7 '๐ตง', // 01110110: Sectors 2,3,5,6,7 '๐ตจ', // 01110111: Sectors 1,2,3,5,6,7 '๐ตฉ', // 01111000: Sectors 4,5,6,7 '๐ตช', // 01111001: Sectors 1,4,5,6,7 '๐ตซ', // 01111010: Sectors 2,4,5,6,7 '๐ตฌ', // 01111011: Sectors 1,2,4,5,6,7 '๐ตญ', // 01111100: Sectors 3,4,5,6,7 '๐ตฎ', // 01111101: Sectors 1,3,4,5,6,7 '๐ตฏ', // 01111110: Sectors 2,3,4,5,6,7 '๐ตฐ', // 01111111: Sectors 1,2,3,4,5,6,7 '๐บ ', // 10000000: Sector 8 '๐ตฑ', // 10000001: Sectors 1,8 '๐ตฒ', // 10000010: Sectors 2,8 '๐ตณ', // 10000011: Sectors 1,2,8 '๐ตด', // 10000100: Sectors 3,8 '๐ตต', // 10000101: Sectors 1,3,8 '๐ตถ', // 10000110: Sectors 2,3,8 '๐ตท', // 10000111: Sectors 1,2,3,8 '๐ตธ', // 10001000: Sectors 4,8 '๐ตน', // 10001001: Sectors 1,4,8 '๐ตบ', // 10001010: Sectors 2,4,8 '๐ตป', // 10001011: Sectors 1,2,4,8 '๐ตผ', // 10001100: Sectors 3,4,8 '๐ตฝ', // 10001101: Sectors 1,3,4,8 '๐ตพ', // 10001110: Sectors 2,3,4,8 '๐ตฟ', // 10001111: Sectors 1,2,3,4,8 '๐ถ', // 10010000: Sectors 5,8 '๐ถ', // 10010001: Sectors 1,5,8 '๐ถ', // 10010010: Sectors 2,5,8 '๐ถ', // 10010011: Sectors 1,2,5,8 '๐ถ', // 10010100: Sectors 3,5,8 '๐ถ ', // 10010101: Sectors 1,3,5,8 '๐ถ', // 10010110: Sectors 2,3,5,8 '๐ถ', // 10010111: Sectors 1,2,3,5,8 '๐ถ', // 10011000: Sectors 4,5,8 '๐ถ', // 10011001: Sectors 1,4,5,8 '๐ถ', // 10011010: Sectors 2,4,5,8 '๐ถ', // 10011011: Sectors 1,2,4,5,8 '๐ถ', // 10011100: Sectors 3,4,5,8 '๐ถ', // 10011101: Sectors 1,3,4,5,8 '๐ถ', // 10011110: Sectors 2,3,4,5,8 '๐ถ', // 10011111: Sectors 1,2,3,4,5,8 'โ', // 10100000: Sectors 6,8 '๐ถ', // 10100001: Sectors 1,6,8 '๐ถ', // 10100010: Sectors 2,6,8 '๐ถ', // 10100011: Sectors 1,2,6,8 '๐ถ', // 10100100: Sectors 3,6,8 'โ', // 10100101: Sectors 1,3,6,8 '๐ถ', // 10100110: Sectors 2,3,6,8 '๐ถ', // 10100111: Sectors 1,2,3,6,8 '๐ถ', // 10101000: Sectors 4,6,8 '๐ถ', // 10101001: Sectors 1,4,6,8 'โ', // 10101010: Sectors 2,4,6,8 (right half) '๐ถ', // 10101011: Sectors 1,2,4,6,8 '๐ถ', // 10101100: Sectors 3,4,6,8 '๐ถ', // 10101101: Sectors 1,3,4,6,8 '๐ถ', // 10101110: Sectors 2,3,4,6,8 'โ', // 10101111: Sectors 1,2,3,4,6,8 '๐ถ', // 10110000: Sectors 5,6,8 '๐ถ', // 10110001: Sectors 1,5,6,8 '๐ถ', // 10110010: Sectors 2,5,6,8 '๐ถ', // 10110011: Sectors 1,2,5,6,8 '๐ถ ', // 10110100: Sectors 3,5,6,8 '๐ถก', // 10110101: Sectors 1,3,5,6,8 '๐ถข', // 10110110: Sectors 2,3,5,6,8 '๐ถฃ', // 10110111: Sectors 1,2,3,5,6,8 '๐ถค', // 10111000: Sectors 4,5,6,8 '๐ถฅ', // 10111001: Sectors 1,4,5,6,8 '๐ถฆ', // 10111010: Sectors 2,4,5,6,8 '๐ถง', // 10111011: Sectors 1,2,4,5,6,8 '๐ถจ', // 10111100: Sectors 3,4,5,6,8 '๐ถฉ', // 10111101: Sectors 1,3,4,5,6,8 '๐ถช', // 10111110: Sectors 2,3,4,5,6,8 '๐ถซ', // 10111111: Sectors 1,2,3,4,5,6,8 'โ', // 11000000: Sectors 7,8 '๐ถฌ', // 11000001: Sectors 1,7,8 '๐ถญ', // 11000010: Sectors 2,7,8 '๐ถฎ', // 11000011: Sectors 1,2,7,8 '๐ถฏ', // 11000100: Sectors 3,7,8 '๐ถฐ', // 11000101: Sectors 1,3,7,8 '๐ถฑ', // 11000110: Sectors 2,3,7,8 '๏ฟฝยฒ', // 11000111: Sectors 1,2,3,7,8 '๐ถณ', // 11001000: Sectors 4,7,8 '๐ถด', // 11001001: Sectors 1,4,7,8 '๐ถต', // 11001010: Sectors 2,4,7,8 '๐ถถ', // 11001011: Sectors 1,2,4,7,8 '๐ถท', // 11001100: Sectors 3,4,7,8 '๐ถธ', // 11001101: Sectors 1,3,4,7,8 '๐ถน', // 11001110: Sectors 2,3,4,7,8 '๐ถบ', // 11001111: Sectors 1,2,3,4,7,8 '๐ถป', // 11010000: Sectors 5,7,8 '๐ถผ', // 11010001: Sectors 1,5,7,8 '๐ถฝ', // 11010010: Sectors 2,5,7,8 '๐ถพ', // 11010011: Sectors 1,2,5,7,8 '๐ถฟ', // 11010100: Sectors 3,5,7,8 '๐ท', // 11010101: Sectors 1,3,5,7,8 '๐ท', // 11010110: Sectors 2,3,5,7,8 '๐ท', // 11010111: Sectors 1,2,3,5,7,8 '๐ท', // 11011000: Sectors 4,5,7,8 '๐ท', // 11011001: Sectors 1,4,5,7,8 '๐ท ', // 11011010: Sectors 2,4,5,7,8 '๐ท', // 11011011: Sectors 1,2,4,5,7,8 '๐ท', // 11011100: Sectors 3,4,5,7,8 '๐ท', // 11011101: Sectors 1,3,4,5,7,8 '๐ท', // 11011110: Sectors 2,3,4,5,7,8 '๐ท', // 11011111: Sectors 1,2,3,4,5,7,8 '๐ท', // 11100000: Sectors 6,7,8 '๐ท', // 11100001: Sectors 1,6,7,8 '๐ท', // 11100010: Sectors 2,6,7,8 '๐ท', // 11100011: Sectors 1,2,6,7,8 '๐ท', // 11100100: Sectors 3,6,7,8 '๐ท', // 11100101: Sectors 1,3,6,7,8 '๐ท', // 11100110: Sectors 2,3,6,7,8 '๐ท', // 11100111: Sectors 1,2,3,6,7,8 '๐ท', // 11101000: Sectors 4,6,7,8 '๐ท', // 11101001: Sectors 1,4,6,7,8 '๐ท', // 11101010: Sectors 2,4,6,7,8 '๐ท', // 11101011: Sectors 1,2,4,6,7,8 '๐ท', // 11101100: Sectors 3,4,6,7,8 '๐ท', // 11101101: Sectors 1,3,4,6,7,8 '๐ท', // 11101110: Sectors 2,3,4,6,7,8 '๐ท', // 11101111: Sectors 1,2,3,4,6,7,8 'โ', // 11110000: Sectors 5,6,7,8 (lower half) '๐ท', // 11110001: Sectors 1,5,6,7,8 '๐ท', // 11110010: Sectors 2,5,6,7,8 '๐ท', // 11110011: Sectors 1,2,5,6,7,8 '๐ท', // 11110100: Sectors 3,5,6,7,8 'โ', // 11110101: Sectors 1,3,5,6,7,8 '๐ท', // 11110110: Sectors 2,3,5,6,7,8 '๐ท ', // 11110111: Sectors 1,2,3,5,6,7,8 '๐ทก', // 11111000: Sectors 4,5,6,7,8 '๐ทข', // 11111001: Sectors 1,4,5,6,7,8 'โ', // 11111010: Sectors 2,4,5,6,7,8 '๐ทฃ', // 11111011: Sectors 1,2,4,5,6,7,8 'โ', // 11111100: Sectors 3,4,5,6,7,8 '๐ทค', // 11111101: Sectors 1,3,4,5,6,7,8 '๐ทฅ', // 11111110: Sectors 2,3,4,5,6,7,8 'โ' // 11111111: All sectors (full block) ]; // K-means clustering for 2-color reduction function kMeans2Colors(pixels) { if (pixels.length === 0) return [0, 0]; if (pixels.length === 1) return [pixels[0], pixels[0]]; let c1 = Math.min(...pixels); let c2 = Math.max(...pixels); for (let iter = 0; iter < 10; iter++) { let cluster1 = []; let cluster2 = []; for (let color of pixels) { const dist1 = colorDistance(color, c1); const dist2 = colorDistance(color, c2); if (dist1 < dist2) { cluster1.push(color); } else { cluster2.push(color); } } if (cluster1.length > 0) { c1 = averageColor(cluster1); } if (cluster2.length > 0) { c2 = averageColor(cluster2); } } return [c1, c2]; } function colorDistance(c1, c2) { const r1 = (c1 >> 16) & 0xFF; const g1 = (c1 >> 8) & 0xFF; const b1 = c1 & 0xFF; const r2 = (c2 >> 16) & 0xFF; const g2 = (c2 >> 8) & 0xFF; const b2 = c2 & 0xFF; return Math.sqrt((r1-r2)**2 + (g1-g2)**2 + (b1-b2)**2); } function averageColor(colors) { let r = 0, g = 0, b = 0; for (let color of colors) { r += (color >> 16) & 0xFF; g += (color >> 8) & 0xFF; b += color & 0xFF; } r = Math.round(r / colors.length); g = Math.round(g / colors.length); b = Math.round(b / colors.length); return (r << 16) | (g << 8) | b; } class OWOTImagePasterOctantDirect { constructor() { this.canvas = new OffscreenCanvas(0, 0); this.ctx = this.canvas.getContext('2d', { willReadFrequently: true }); this.maxWidth = 50; this.maxHeight = 50; this.maintainAspectRatio = true; this.currentImageData = null; this.isPasting = false; this.isSelectingRegion = false; this.regionStart = null; this.regionEnd = null; this.createUI(); this.setupPasteListener(); } createUI() { const existing = document.getElementById('owot-image-paster-ui'); if (existing) existing.remove(); const ui = document.createElement('div'); ui.id = 'owot-image-paster-ui'; ui.style.cssText = ` position: fixed; top: 20px; right: 20px; background: #2c3e50; color: white; padding: 20px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.5); z-index: 10000; font-family: Arial, sans-serif; width: 400px; max-height: 90vh; overflow-y: auto; `; ui.innerHTML = `