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
<:italic:`width`>x<:italic:`height`>@<:italic:`left`>x<:italic:`top`>.
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

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()
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
}

View File

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

View File

@ -10,6 +10,7 @@ import (
"kitty/tools/tui/graphics"
"kitty/tools/utils"
"kitty/tools/utils/shm"
"math"
"math/rand"
"os"
"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.SetDataWidth(uint64(frame.width)).SetDataHeight(uint64(frame.height))
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 {
gc.SetZIndex(z_index)
}
@ -151,6 +155,44 @@ func transmit_stream(imgd *image_data, frame_num int, frame *image_frame) (err e
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) {
defer func() {
for _, frame := range imgd.frames {
@ -189,10 +231,21 @@ func transmit_image(imgd *image_data) {
if len(imgd.frames) > 1 {
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 {
err := f(imgd, frame_num, frame)
if err != nil {
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) {
if amt != 0 {
suffix := "C"

View File

@ -6,6 +6,7 @@ import (
"fmt"
"image"
"image/color"
"math"
"runtime"
"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)
}
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
}