The channel route is the best solution… you make a custom resolution channel then route each slice to a second channel.
I’ve recently had to code a function to make the strips (either vertically or horizontally)
If you program yourself, you can get an idea from these functions in C#:
public class Slice
{
private double _width;
private double _height;
private Thickness _crop;
private double _targetWidth = 0;
private double _targetHeight = 0;
private double _targetX = 0;
private double _targetY = 0;
public Slice(double width, double height)
{
_width = width;
_height = height;
}
public void SetTarget(double width, double height, double x, double y)
{
_targetWidth = width;
_targetHeight = height;
_targetX = x;
_targetY = y;
}
public void SetCrop(double left, double top, double right, double bottom)
{
var crop_left = left / _width;
var crop_right = right / _width;
var crop_top = top / _height;
var crop_bottom = bottom / _height;
_crop = new Thickness(crop_left, crop_top, crop_right, crop_bottom);
}
public Thickness Crop
{
get
{
return _crop;
}
}
public Fill Fill
{
get
{
var pos_x = _targetX / _targetWidth;
var pos_y = _targetY / _targetHeight;
var size_x = _width / _targetWidth;
var size_y = _height / _targetHeight;
return new Fill(pos_x,pos_y,size_x, size_y);
}
}
}
public struct Fill
{
public Fill()
{
_PanX = 0;
_PanY = 0;
_ZoomX = 1;
_ZoomY = 1;
}
public Fill(double panX, double panY, double zoomX, double zoomY)
{
_PanX = panX;
_PanY = panY;
_ZoomX = zoomX;
_ZoomY = zoomY;
}
private double _PanX;
private double _PanY;
private double _ZoomX;
private double _ZoomY;
public double PanX => _PanX;
public double PanY => _PanY;
public double ZoomX => _ZoomX;
public double ZoomY => _ZoomY;
}
public static List<Slice> GetScreenSlices(double sourceWidth, double sourceHeight, double targetWidth, double targetHeight, double slices, bool vertical = false)
{
var sliceWidth = !vertical ? sourceWidth / slices : sourceWidth;
var sliceHeight = vertical ? sourceHeight / slices : sourceHeight;
List<Slice> sliceList = [];
for (int s = 0; s < slices; s++)
{
var slice = new Slice(sourceWidth, sourceHeight);
sliceList.Add(slice);
double x = 0;
double y = 0;
if (vertical)
{
x = sliceWidth * s;
y = 0 - sliceHeight * s;
}
else
{
x = 0 - sliceWidth * s;
y = sliceHeight * s;
}
slice.SetTarget(targetWidth, targetHeight, x, y);
var crop_x = vertical ? 0 : sliceWidth * s;
var crop_y = vertical ? sliceHeight * s : 0;
var crop_w = vertical ? sliceWidth : crop_x + sliceWidth;
var crop_h = vertical ? crop_y + sliceHeight : sliceHeight;
slice.SetCrop(crop_x, crop_y, crop_w, crop_h);
}
return sliceList;
}
internal void SetupMainLedScreen()
{
Rect MainLED = new(0, 0, 2962, 540);
Rect MainLED_channel = new(0, 0, 1920, 1080);
var main = App.Settings.MainLEDSetting;
var main_route = 2;
App.Servers[main.Server].SendToAll($"CLEAR {main_route}");
App.Servers[main.Server].SendToAll($"MIXER {main_route} CLEAR");
var main_slices = GetScreenSlices(MainLED.Width, MainLED.Height, MainLED_channel.Width, MainLED_channel.Height, 2);
var main_slice = 0;
foreach (Slice slice in main_slices)
{
main_slice++;
App.Servers[main.Server].SendToAll($"PLAY {main_route}-{main_slice} route://{main.Channel}");
App.Servers[main.Server].SendToAll($"MIXER {main_route}-{main_slice} CROP {F(slice.Crop.Left)} {F(slice.Crop.Top)} {F(slice.Crop.Right)} {F(slice.Crop.Bottom)}");
App.Servers[main.Server].SendToAll($"MIXER {main_route}-{main_slice} FILL {F(slice.Fill.PanX)} {F(slice.Fill.PanY)} {F(slice.Fill.ZoomX)} {F(slice.Fill.ZoomY)}");
}
}