Module: Termpix::Protocols::W3m
- Defined in:
- lib/termpix/protocols.rb
Overview
w3mimgdisplay Protocol
Class Method Summary collapse
- .clear(x:, y:, width:, height:, term_width:, term_height:) ⇒ Object
- .display(image_path, x:, y:, max_width:, max_height:) ⇒ Object
Class Method Details
.clear(x:, y:, width:, height:, term_width:, term_height:) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/termpix/protocols.rb', line 216 def self.clear(x:, y:, width:, height:, term_width:, term_height:) # Clear only the image overlay in the specified area terminfo = `xwininfo -id $(xdotool getactivewindow 2>/dev/null) 2>/dev/null` return true unless terminfo && !terminfo.empty? w_match = terminfo.match(/Width: (\d+)/) h_match = terminfo.match(/Height: (\d+)/) return true unless w_match && h_match term_w = w_match[1].to_i term_h = h_match[1].to_i # Calculate character dimensions char_w = term_w / term_width char_h = term_h / term_height # Convert to pixel coordinates with slight margin adjustment img_x = (char_w * x) - char_w img_y = char_h * y img_max_w = (char_w * width) + char_w + 2 img_max_h = char_h * height + 2 # Use w3mimgdisplay command "6" to clear just the image area cmd = "6;#{img_x};#{img_y};#{img_max_w};#{img_max_h};\n4;\n3;\n" IO.popen([@imgdisplay], 'w', err: '/dev/null') { |io| io.write(cmd) } true end |
.display(image_path, x:, y:, max_width:, max_height:) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/termpix/protocols.rb', line 147 def self.display(image_path, x:, y:, max_width:, max_height:) # Get terminal pixel dimensions terminfo = `xwininfo -id $(xdotool getactivewindow 2>/dev/null) 2>/dev/null` return unless terminfo && !terminfo.empty? w_match = terminfo.match(/Width: (\d+)/) h_match = terminfo.match(/Height: (\d+)/) return unless w_match && h_match term_w = w_match[1].to_i term_h = h_match[1].to_i # Calculate character dimensions cols = `tput cols`.to_i cols = 80 if cols <= 0 lines = `tput lines`.to_i lines = 24 if lines <= 0 char_w = term_w / cols char_h = term_h / lines # Convert to pixel coordinates img_x = char_w * x img_y = char_h * y img_max_w = char_w * max_width img_max_h = char_h * max_height # Check if image has EXIF orientation data before auto-orienting # This avoids unnecessary temp file creation for most images escaped = Shellwords.escape(image_path) # Quick check: only auto-orient if image has EXIF orientation tag has_orientation = `identify -format "%[EXIF:Orientation]" #{escaped}[0] 2>/dev/null`.strip if has_orientation && !has_orientation.empty? && has_orientation != "1" # Image needs rotation - create cached temp file require 'digest' file_hash = Digest::MD5.hexdigest(image_path) temp_file = "/tmp/termpix_#{file_hash}.jpg" unless File.exist?(temp_file) system("convert #{escaped}[0] -auto-orient #{temp_file} 2>/dev/null") end display_path = File.exist?(temp_file) ? temp_file : image_path else # No rotation needed - use original image display_path = image_path end dimensions = `identify -format "%wx%h" #{Shellwords.escape(display_path)}[0] 2>/dev/null`.strip return if dimensions.empty? || !dimensions.match?(/\A\d+x\d+\z/) img_w, img_h = dimensions.split('x').map(&:to_i) # Scale if needed - preserve aspect ratio if img_w > img_max_w || img_h > img_max_h scale_w = img_max_w.to_f / img_w scale_h = img_max_h.to_f / img_h scale = [scale_w, scale_h].min img_w = (img_w * scale).to_i img_h = (img_h * scale).to_i end # Display using w3mimgdisplay protocol cmd = "0;1;#{img_x};#{img_y};#{img_w};#{img_h};;;;;#{display_path}\n4;\n3;\n" IO.popen([@imgdisplay], 'w', err: '/dev/null') { |io| io.write(cmd) } # Don't delete temp file - keep it cached for performance end |