mirror of
https://github.com/mpv-player/mpv.git
synced 2026-10-17 06:50:45 +08:00
vo_sixel: size the canvas from the terminal's cells
--vo-sixel-rows and --vo-sixel-cols replaced the terminal's cell counts while the canvas kept the terminal's pixel size, and --vo-sixel-top and --vo-sixel-left kept it too, so the image ran past the bottom and scrolled the terminal. Take the cell size from what the terminal reports, and size the canvas in those cells from where the image starts, or as the options say.
This commit is contained in:
+10
-11
@@ -485,21 +485,20 @@ Available video output drivers are:
|
||||
Sixel size and alignment options:
|
||||
|
||||
``--vo-sixel-cols=<columns>``, ``--vo-sixel-rows=<rows>`` (default: 0)
|
||||
Specify the terminal size in character cells, otherwise (0) read it
|
||||
from the terminal, or fall back to 80x25. Note that mpv doesn't use the
|
||||
the last row with sixel because this seems to result in scrolling.
|
||||
Size of the area the image may use, in character cells. The default
|
||||
(0) is the terminal size from the position the image starts at, or
|
||||
80x25 if the terminal size cannot be read. The last row is left free
|
||||
for the status line.
|
||||
|
||||
``--vo-sixel-width=<width>``, ``--vo-sixel-height=<height>`` (default: 0)
|
||||
Specify the available size in pixels, otherwise (0) read it from the
|
||||
terminal, or fall back to 320x240. Other than excluding the last line,
|
||||
the height is also further rounded down to a multiple of 6 (sixel unit
|
||||
height) to avoid overflowing below the designated size.
|
||||
Size of the area the image may use, in pixels. The default (0) is what
|
||||
the terminal reports for the rows and columns above, or 320x240 if it
|
||||
reports nothing. Other than excluding the last row, the height is
|
||||
rounded down to a multiple of 6, the height of a sixel band.
|
||||
|
||||
``--vo-sixel-left=<col>``, ``--vo-sixel-top=<row>`` (default: 0)
|
||||
Specify the position in character cells where the image starts (1 is
|
||||
the first column or row). If 0 (default) then try to automatically
|
||||
determine it according to the other values and the image aspect ratio
|
||||
and zoom.
|
||||
Position in character cells where the area the image may use starts
|
||||
(1 is the first column or row). 0 (default) is the same as 1.
|
||||
|
||||
``--vo-sixel-pad-x=<pad_x>``, ``--vo-sixel-pad-y=<pad_y>`` (default: -1)
|
||||
Used only when mpv reads the size in pixels from the terminal.
|
||||
|
||||
+45
-36
@@ -70,7 +70,7 @@ struct priv {
|
||||
|
||||
int left, top; // image origin cell (1 based)
|
||||
int width, height; // actual image px size - always reflects dst_rect.
|
||||
int num_cols, num_rows; // terminal size in cells
|
||||
int num_cols, num_rows; // canvas size in cells
|
||||
int canvas_ok; // whether canvas vo->dwidth and vo->dheight are positive
|
||||
|
||||
int previous_histogram_colors;
|
||||
@@ -194,53 +194,62 @@ static void update_canvas_dimensions(struct vo *vo)
|
||||
// this function sets the vo canvas size in pixels vo->dwidth, vo->dheight,
|
||||
// and the number of rows and columns available in priv->num_rows/cols
|
||||
struct priv *priv = vo->priv;
|
||||
int num_rows = TERMINAL_FALLBACK_ROWS;
|
||||
int num_cols = TERMINAL_FALLBACK_COLS;
|
||||
int term_rows = TERMINAL_FALLBACK_ROWS;
|
||||
int term_cols = TERMINAL_FALLBACK_COLS;
|
||||
int total_px_width = 0;
|
||||
int total_px_height = 0;
|
||||
|
||||
terminal_get_size2(&num_rows, &num_cols, &total_px_width, &total_px_height);
|
||||
|
||||
// If the user has specified rows/cols use them for further calculations
|
||||
num_rows = (priv->opts.rows > 0) ? priv->opts.rows : num_rows;
|
||||
num_cols = (priv->opts.cols > 0) ? priv->opts.cols : num_cols;
|
||||
terminal_get_size2(&term_rows, &term_cols, &total_px_width, &total_px_height);
|
||||
|
||||
// If the pad value is set in between 0 and width/2 - 1, then we
|
||||
// subtract from the detected width. Otherwise, we assume that the width
|
||||
// output must be a integer multiple of num_cols and accordingly set
|
||||
// total_width to be an integer multiple of num_cols. So in case the padding
|
||||
// added by terminal is less than the number of cells in that axis, then rounding
|
||||
// down will take care of correcting the detected width and remove padding.
|
||||
if (priv->opts.width > 0) {
|
||||
// option - set by the user, hard truth
|
||||
total_px_width = priv->opts.width;
|
||||
} else {
|
||||
if (total_px_width <= 0) {
|
||||
// ioctl failed to read terminal width
|
||||
total_px_width = TERMINAL_FALLBACK_PX_WIDTH;
|
||||
// output must be a integer multiple of the number of cells and accordingly
|
||||
// set total_width to be an integer multiple of it. So in case the padding
|
||||
// added by terminal is less than the number of cells in that axis, then
|
||||
// rounding down will take care of correcting the detected width and remove
|
||||
// padding. What is left gives the size of a cell.
|
||||
int cell_w = 0, cell_h = 0;
|
||||
if (total_px_width > 0) {
|
||||
if (priv->opts.pad_x >= 0 && priv->opts.pad_x < total_px_width / 2) {
|
||||
// explicit padding set by the user
|
||||
total_px_width -= (2 * priv->opts.pad_x);
|
||||
} else {
|
||||
if (priv->opts.pad_x >= 0 && priv->opts.pad_x < total_px_width / 2) {
|
||||
// explicit padding set by the user
|
||||
total_px_width -= (2 * priv->opts.pad_x);
|
||||
} else {
|
||||
// rounded "auto padding"
|
||||
total_px_width = total_px_width / num_cols * num_cols;
|
||||
}
|
||||
// rounded "auto padding"
|
||||
total_px_width = total_px_width / term_cols * term_cols;
|
||||
}
|
||||
if (total_px_width % term_cols == 0)
|
||||
cell_w = total_px_width / term_cols;
|
||||
}
|
||||
if (total_px_height > 0) {
|
||||
if (priv->opts.pad_y >= 0 && priv->opts.pad_y < total_px_height / 2) {
|
||||
total_px_height -= (2 * priv->opts.pad_y);
|
||||
} else {
|
||||
total_px_height = total_px_height / term_rows * term_rows;
|
||||
}
|
||||
if (total_px_height % term_rows == 0)
|
||||
cell_h = total_px_height / term_rows;
|
||||
}
|
||||
|
||||
// The canvas is the terminal from where the image starts, unless the user
|
||||
// gives its size in cells or in pixels.
|
||||
int top = (priv->opts.top > 0) ? priv->opts.top : 1;
|
||||
int left = (priv->opts.left > 0) ? priv->opts.left : 1;
|
||||
int num_rows = (priv->opts.rows > 0) ? priv->opts.rows : MPMAX(term_rows - (top - 1), 2);
|
||||
int num_cols = (priv->opts.cols > 0) ? priv->opts.cols : MPMAX(term_cols - (left - 1), 1);
|
||||
if (priv->opts.width > 0) {
|
||||
total_px_width = priv->opts.width;
|
||||
} else if (total_px_width <= 0) {
|
||||
// ioctl failed to read terminal width
|
||||
total_px_width = TERMINAL_FALLBACK_PX_WIDTH;
|
||||
} else if (num_cols != term_cols && cell_w > 0) {
|
||||
total_px_width = num_cols * cell_w;
|
||||
}
|
||||
if (priv->opts.height > 0) {
|
||||
total_px_height = priv->opts.height;
|
||||
} else {
|
||||
if (total_px_height <= 0) {
|
||||
total_px_height = TERMINAL_FALLBACK_PX_HEIGHT;
|
||||
} else {
|
||||
if (priv->opts.pad_y >= 0 && priv->opts.pad_y < total_px_height / 2) {
|
||||
total_px_height -= (2 * priv->opts.pad_y);
|
||||
} else {
|
||||
total_px_height = total_px_height / num_rows * num_rows;
|
||||
}
|
||||
}
|
||||
} else if (total_px_height <= 0) {
|
||||
total_px_height = TERMINAL_FALLBACK_PX_HEIGHT;
|
||||
} else if (num_rows != term_rows && cell_h > 0) {
|
||||
total_px_height = num_rows * cell_h;
|
||||
}
|
||||
|
||||
// use n-1 rows for height
|
||||
|
||||
Reference in New Issue
Block a user