Implement --scale-up and --place

This commit is contained in:
Kovid Goyal 2023-01-02 10:30:27 +05:30
parent 73a055fe12
commit df06578c2d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 92 additions and 1 deletions

View File

@ -46,7 +46,9 @@ Choose where on the screen to display the image. The image will be scaled to fit
into the specified rectangle. The syntax for specifying rectangles is into the specified rectangle. The syntax for specifying rectangles is
<:italic:`width`>x<:italic:`height`>@<:italic:`left`>x<:italic:`top`>. <:italic:`width`>x<:italic:`height`>@<:italic:`left`>x<:italic:`top`>.
All measurements are in cells (i.e. cursor positions) with the origin All measurements are in cells (i.e. cursor positions) with the origin
:italic:`(0, 0)` at the top-left corner of the screen. :italic:`(0, 0)` at the top-left corner of the screen. Note that the :option:`--align`
option will horizontally align the image within this rectangle. By default, the image
is horizontally centered within the rectangle.
--scale-up --scale-up

View File

@ -50,6 +50,15 @@ func load_one_frame_image(imgd *image_data, src *opened_input) (image.Image, err
imgd.canvas_height = img.Bounds().Dy() imgd.canvas_height = img.Bounds().Dy()
set_basic_metadata(imgd) set_basic_metadata(imgd)
} }
if imgd.needs_scaling {
if imgd.canvas_width < imgd.available_width && opts.ScaleUp && place != nil {
r := float64(imgd.available_width) / float64(imgd.canvas_width)
imgd.canvas_width, imgd.canvas_height = imgd.available_width, int(r*float64(imgd.canvas_height))
}
imgd.canvas_width, imgd.canvas_height = images.FitImage(imgd.canvas_width, imgd.canvas_height, imgd.available_width, imgd.available_height)
img = imaging.Resize(img, imgd.canvas_width, imgd.canvas_height, imaging.Lanczos)
imgd.needs_scaling = false
}
return img, err return img, err
} }

View File

@ -151,6 +151,9 @@ type image_data struct {
needs_scaling, needs_conversion bool needs_scaling, needs_conversion bool
frames []*image_frame frames []*image_frame
image_number uint32 image_number uint32
cell_x_offset int
move_x_by int
move_to struct{ x, y int }
// for error reporting // for error reporting
err error err error

View File

@ -10,6 +10,7 @@ import (
"kitty/tools/tui/graphics" "kitty/tools/tui/graphics"
"kitty/tools/utils" "kitty/tools/utils"
"kitty/tools/utils/shm" "kitty/tools/utils/shm"
"math"
"math/rand" "math/rand"
"os" "os"
"path/filepath" "path/filepath"
@ -22,6 +23,9 @@ func gc_for_image(imgd *image_data, frame_num int, frame *image_frame) *graphics
gc.SetAction(graphics.GRT_action_transmit_and_display) gc.SetAction(graphics.GRT_action_transmit_and_display)
gc.SetDataWidth(uint64(frame.width)).SetDataHeight(uint64(frame.height)) gc.SetDataWidth(uint64(frame.width)).SetDataHeight(uint64(frame.height))
gc.SetQuiet(graphics.GRT_quiet_silent) gc.SetQuiet(graphics.GRT_quiet_silent)
if frame_num == 0 && imgd.cell_x_offset > 0 {
gc.SetXOffset(uint64(imgd.cell_x_offset))
}
if z_index != 0 { if z_index != 0 {
gc.SetZIndex(z_index) gc.SetZIndex(z_index)
} }
@ -151,6 +155,44 @@ func transmit_stream(imgd *image_data, frame_num int, frame *image_frame) (err e
return nil return nil
} }
func calculate_in_cell_x_offset(width, cell_width int) int {
extra_pixels := width % cell_width
if extra_pixels == 0 {
return 0
}
switch opts.Align {
case "left":
return 0
case "right":
return cell_width - extra_pixels
default:
return (cell_width - extra_pixels) / 2
}
}
func place_cursor(imgd *image_data) {
cw := int(screen_size.CellWidth)
imgd.cell_x_offset = calculate_in_cell_x_offset(imgd.canvas_width, cw)
num_of_cells_needed := int(math.Ceil(float64(imgd.canvas_width) / float64(cw)))
if place == nil {
switch opts.Align {
case "center":
imgd.move_x_by = (int(screen_size.WidthCells) - num_of_cells_needed) / 2
case "right":
imgd.move_x_by = (int(screen_size.WidthCells) - num_of_cells_needed)
}
} else {
imgd.move_to.x = place.left + 1
imgd.move_to.y = place.top + 1
switch opts.Align {
case "center":
imgd.move_to.x += (place.width - num_of_cells_needed) / 2
case "right":
imgd.move_to.x += (place.width - num_of_cells_needed)
}
}
}
func transmit_image(imgd *image_data) { func transmit_image(imgd *image_data) {
defer func() { defer func() {
for _, frame := range imgd.frames { for _, frame := range imgd.frames {
@ -189,10 +231,21 @@ func transmit_image(imgd *image_data) {
if len(imgd.frames) > 1 { if len(imgd.frames) > 1 {
imgd.image_number = rand.Uint32() imgd.image_number = rand.Uint32()
} }
place_cursor(imgd)
lp.QueueWriteString("\r")
if imgd.move_x_by > 0 {
lp.MoveCursorHorizontally(imgd.move_x_by)
}
if imgd.move_to.x > 0 {
lp.MoveCursorTo(imgd.move_to.x, imgd.move_to.y)
}
for frame_num, frame := range imgd.frames { for frame_num, frame := range imgd.frames {
err := f(imgd, frame_num, frame) err := f(imgd, frame_num, frame)
if err != nil { if err != nil {
print_error("Failed to transmit %s with error: %v", imgd.source_name, err) print_error("Failed to transmit %s with error: %v", imgd.source_name, err)
} }
} }
if imgd.move_to.x == 0 {
lp.Println() // ensure cursor is on new line
}
} }

View File

@ -261,6 +261,12 @@ func (self *Loop) SetCursorVisible(visible bool) {
} }
} }
func (self *Loop) MoveCursorTo(x, y int) {
if x > 0 && y > 0 {
self.QueueWriteString(fmt.Sprintf("\x1b[%d;%dH", y, x))
}
}
func (self *Loop) MoveCursorHorizontally(amt int) { func (self *Loop) MoveCursorHorizontally(amt int) {
if amt != 0 { if amt != 0 {
suffix := "C" suffix := "C"

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"image" "image"
"image/color" "image/color"
"math"
"runtime" "runtime"
"sync" "sync"
) )
@ -390,3 +391,20 @@ func PasteCenter(background image.Image, img image.Image, opaque_bg *color.NRGBA
Paste(background, img, image.Pt(x0, y0), opaque_bg) Paste(background, img, image.Pt(x0, y0), opaque_bg)
} }
func FitImage(width, height, pwidth, pheight int) (final_width int, final_height int) {
if height > pheight {
corrf := float64(pheight) / float64(height)
width, height = int(math.Floor(corrf*float64(width))), pheight
}
if width > pwidth {
corrf := float64(pwidth) / float64(width)
width, height = pwidth, int(math.Floor(corrf*float64(height)))
}
if height > pheight {
corrf := float64(pheight) / float64(height)
width, height = int(math.Floor(corrf*float64(width))), pheight
}
return width, height
}