Кадрирование показывает кадр из клипа, а не из середины файла
Окно кадрирования брало кадр на десятой части от начала исходного файла, не глядя, какой клип правят. Клип обычно вырезан из середины долгой съёмки, и в окне была совсем другая сцена: прицелиться увеличением было нечем. Теперь для клипа берётся его собственное время: место курсора, если он внутри клипа, иначе середина клипа. Кадрирование файла целиком из списка работает как раньше. Проверено на съёмке с дрона: клип из 900-й секунды, окно показало кадр именно оттуда (совпал с эталонным кадром на 900 с), раньше показывало кадр на пятой секунде.
This commit is contained in:
parent
0ba3bd40a6
commit
569d0382f7
2 changed files with 46 additions and 18 deletions
|
|
@ -3012,6 +3012,7 @@ var
|
|||
T: TMediaTransform;
|
||||
Key: TColorKey;
|
||||
Applied: Boolean;
|
||||
At: Double;
|
||||
begin
|
||||
if AClip = nil then
|
||||
Exit;
|
||||
|
|
@ -3041,12 +3042,23 @@ begin
|
|||
end;
|
||||
|
||||
T := AClip.Transform;
|
||||
{ Кадр окну — из самого клипа, а не из середины исходного файла.
|
||||
|
||||
Клип обычно вырезан из середины долгой съёмки, и кадр «десятая часть
|
||||
от начала файла» показывал совсем другую сцену: прицелиться
|
||||
кадрированием было нечем. Берём то место, где стоит курсор, если он
|
||||
внутри клипа, иначе середину клипа — то, на что человек и смотрит. }
|
||||
At := FTimeline.Playhead;
|
||||
if (At < AClip.TlStart) or (At > AClip.TlEnd) then
|
||||
At := AClip.TlStart + AClip.Duration / 2;
|
||||
At := AClip.SrcIn + (At - AClip.TlStart);
|
||||
|
||||
{ Ключ отдаётся окну по ссылке: правку он подтверждает сам, и «Отмена»
|
||||
кадрирования её не отменяет. }
|
||||
Key := AClip.ColorKey;
|
||||
Applied := EditTransform(Self, Item.EffectivePath, Item.Info,
|
||||
FProject.Master.Width, FProject.Master.Height, T,
|
||||
FProject.CacheDir + 'pancrop.png', @Key);
|
||||
FProject.CacheDir + 'pancrop.png', @Key, At);
|
||||
if (not Applied) and SameColorKey(Key, AClip.ColorKey) then
|
||||
Exit;
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ type
|
|||
у заготовки для файла, у которой клипа ещё нет), и кнопки не
|
||||
будет. }
|
||||
FKey: PColorKey;
|
||||
{ Какое место исходника показывать в окне. }
|
||||
FAtTime: Double;
|
||||
FSourceInfo: TMediaInfo;
|
||||
FDstWidth: Integer;
|
||||
FDstHeight: Integer;
|
||||
|
|
@ -106,11 +108,18 @@ type
|
|||
procedure WriteControls;
|
||||
procedure ScheduleRefresh;
|
||||
procedure RefreshPreview(Sender: TObject);
|
||||
{ Время кадра в исходнике: заданное снаружи или своё. }
|
||||
function FrameTime: Double;
|
||||
public
|
||||
{ Готовит окно. ADstWidth и ADstHeight — кадр проекта. }
|
||||
{ AAtTime — какое место исходника показывать. Меньше нуля — выбрать
|
||||
самим: десятая часть от начала файла. Для клипа передаётся его
|
||||
собственное время, иначе прицелиться нечем: клип вырезан из середины
|
||||
съёмки, а в окне показывалась совсем другая сцена. }
|
||||
procedure Setup(const APath: string; const AInfo: TMediaInfo;
|
||||
ADstWidth, ADstHeight: Integer; const ATransform: TMediaTransform;
|
||||
const APreviewFile: string; AKey: PColorKey = nil);
|
||||
const APreviewFile: string; AKey: PColorKey = nil;
|
||||
AAtTime: Double = -1);
|
||||
property Transform: TMediaTransform read FTransform;
|
||||
end;
|
||||
|
||||
|
|
@ -124,7 +133,7 @@ type
|
|||
function EditTransform(AOwner: TComponent; const APath: string;
|
||||
const AInfo: TMediaInfo; ADstWidth, ADstHeight: Integer;
|
||||
var ATransform: TMediaTransform; const APreviewFile: string;
|
||||
AKey: PColorKey = nil): Boolean;
|
||||
AKey: PColorKey = nil; AAtTime: Double = -1): Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
|
|
@ -201,6 +210,21 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
{ Какое место исходника показывать.
|
||||
|
||||
Задано снаружи — берём его: у клипа это его собственное время, и только
|
||||
по нему можно прицелиться кадрированием. Не задано (кадрирование файла
|
||||
целиком из списка) — десятая часть от начала, но не дальше пятой
|
||||
секунды: первые кадры съёмки часто пустые. }
|
||||
function TPanCropForm.FrameTime: Double;
|
||||
begin
|
||||
if FSourceInfo.Kind = mkImage then
|
||||
Exit(0);
|
||||
if FAtTime >= 0 then
|
||||
Exit(Max(0, Min(FAtTime, Max(0, FSourceInfo.Duration - 0.05))));
|
||||
Result := Min(5, Max(0, FSourceInfo.Duration * 0.1));
|
||||
end;
|
||||
|
||||
procedure TPanCropForm.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
FreeAndNil(FSourceBmp);
|
||||
|
|
@ -211,8 +235,9 @@ end;
|
|||
|
||||
procedure TPanCropForm.Setup(const APath: string; const AInfo: TMediaInfo;
|
||||
ADstWidth, ADstHeight: Integer; const ATransform: TMediaTransform;
|
||||
const APreviewFile: string; AKey: PColorKey);
|
||||
const APreviewFile: string; AKey: PColorKey; AAtTime: Double);
|
||||
begin
|
||||
FAtTime := AAtTime;
|
||||
FKey := AKey;
|
||||
btnKey.Visible := AKey <> nil;
|
||||
FSourcePath := APath;
|
||||
|
|
@ -321,10 +346,7 @@ var
|
|||
begin
|
||||
if FKey = nil then
|
||||
Exit;
|
||||
if FSourceInfo.Kind = mkImage then
|
||||
AtTime := 0
|
||||
else
|
||||
AtTime := Min(5, Max(0, FSourceInfo.Duration * 0.1));
|
||||
AtTime := FrameTime;
|
||||
EditColorKey(FKey^, FSourcePath, AtTime, FPreviewFile + '.key.png');
|
||||
end;
|
||||
|
||||
|
|
@ -515,10 +537,7 @@ begin
|
|||
Exit;
|
||||
|
||||
Path := FPreviewFile + '.src.png';
|
||||
if FSourceInfo.Kind = mkImage then
|
||||
AtTime := 0
|
||||
else
|
||||
AtTime := Min(5, Max(0, FSourceInfo.Duration * 0.1));
|
||||
AtTime := FrameTime;
|
||||
|
||||
{ Пустая цепочка фильтров: нужен именно исходный кадр, без вписывания и
|
||||
полей — иначе рамку не по чему тянуть. }
|
||||
|
|
@ -677,10 +696,7 @@ begin
|
|||
PrevW, PrevH);
|
||||
lblFilter.Caption := Filter;
|
||||
|
||||
if FSourceInfo.Kind = mkImage then
|
||||
AtTime := 0
|
||||
else
|
||||
AtTime := Min(5, Max(0, FSourceInfo.Duration * 0.1));
|
||||
AtTime := FrameTime;
|
||||
|
||||
Res := RunProcess(FfmpegExe,
|
||||
ArgsPreviewFrame(FSourcePath, FPreviewFile, AtTime, Filter),
|
||||
|
|
@ -720,14 +736,14 @@ end;
|
|||
function EditTransform(AOwner: TComponent; const APath: string;
|
||||
const AInfo: TMediaInfo; ADstWidth, ADstHeight: Integer;
|
||||
var ATransform: TMediaTransform; const APreviewFile: string;
|
||||
AKey: PColorKey): Boolean;
|
||||
AKey: PColorKey; AAtTime: Double = -1): Boolean;
|
||||
var
|
||||
Form: TPanCropForm;
|
||||
begin
|
||||
Form := TPanCropForm.Create(AOwner);
|
||||
try
|
||||
Form.Setup(APath, AInfo, ADstWidth, ADstHeight, ATransform, APreviewFile,
|
||||
AKey);
|
||||
AKey, AAtTime);
|
||||
Result := Form.ShowModal = mrOK;
|
||||
if Result then
|
||||
ATransform := Form.Transform;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue