Implement --scale-up and --place
This commit is contained in:
parent
73a055fe12
commit
df06578c2d
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user