📄 ulzmaencoder.pas
字号:
optimum.Prev2 := false;
end;//if curandlenprice
end;//none
end;//if lentest
end;//if not nextischar and ...
startLen := 2; // speed optimization
for repIndex := 0 to ULZMABase.kNumRepDistances -1 do begin
lenTest := _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
if lenTest < 2 then
continue;
lenTestTemp := lenTest;
repeat
while lenEnd < cur + lenTest do begin
inc(lenEnd);
_optimum[lenEnd].Price := kIfinityPrice;
end;//while lenEnd
curAndLenPrice := repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
optimum := _optimum[cur + lenTest];
if curAndLenPrice < optimum.Price then begin
optimum.Price := curAndLenPrice;
optimum.PosPrev := cur;
optimum.BackPrev := repIndex;
optimum.Prev1IsChar := false;
end;//if curandlen
dec(lenTest);
until not (lenTest >= 2);
lenTest := lenTestTemp;
if repIndex = 0 then
startLen := lenTest + 1;
// if (_maxMode)
if lenTest < numAvailableBytesFull then begin
t := min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
lenTest2 := _matchFinder.GetMatchLen(lenTest, reps[repIndex], t);
if lenTest2 >= 2 then begin
state2 := ULZMABase.StateUpdateRep(state);
posStateNext := (position + lenTest) and _posStateMask;
curAndLenCharPrice :=
repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
RangeEncoder.GetPrice0(_isMatch[(state2 shl ULZMABase.kNumPosStatesBitsMax) + posStateNext]) +
_literalEncoder.GetSubCoder(position + lenTest,
_matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true,
_matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)),
_matchFinder.GetIndexByte(lenTest - 1));
state2 := ULZMABase.StateUpdateChar(state2);
posStateNext := (position + lenTest + 1) and _posStateMask;
nextMatchPrice := curAndLenCharPrice + RangeEncoder.GetPrice1(_isMatch[(state2 shl ULZMABase.kNumPosStatesBitsMax) + posStateNext]);
nextRepMatchPrice := nextMatchPrice + RangeEncoder.GetPrice1(_isRep[state2]);
// for(; lenTest2 >= 2; lenTest2--)
begin
offset := lenTest + 1 + lenTest2;
while lenEnd < cur + offset do begin
inc(lenEnd);
_optimum[lenEnd].Price := kIfinityPrice;
end;//while lenEnd
curAndLenPrice := nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
optimum := _optimum[cur + offset];
if curAndLenPrice < optimum.Price then begin
optimum.Price := curAndLenPrice;
optimum.PosPrev := cur + lenTest + 1;
optimum.BackPrev := 0;
optimum.Prev1IsChar := true;
optimum.Prev2 := true;
optimum.PosPrev2 := cur;
optimum.BackPrev2 := repIndex;
end;//if curAndLenPrice < optimum.Price
end;//none
end;//if lenTest2 >= 2
end;//if lenTest < numAvailableBytesFull
end;//for repIndex
if newLen > numAvailableBytes then begin
newLen := numAvailableBytes;
numDistancePairs := 0;
while newLen > _matchDistances[numDistancePairs] do
numDistancePairs := numDistancePairs + 2;
_matchDistances[numDistancePairs] := newLen;
numDistancePairs := numDistancePairs + 2;
end;//if newLen > numAvailableBytes
if newLen >= startLen then begin
normalMatchPrice := matchPrice + RangeEncoder.GetPrice0(_isRep[state]);
while lenEnd < cur + newLen do begin
inc(lenEnd);
_optimum[lenEnd].Price := kIfinityPrice;
end;//while lenEnd
offs := 0;
while startLen > _matchDistances[offs] do
offs := offs + 2;
lenTest := startLen;
while (true) do begin
curBack := _matchDistances[offs + 1];
curAndLenPrice := normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
optimum := _optimum[cur + lenTest];
if curAndLenPrice < optimum.Price then begin
optimum.Price := curAndLenPrice;
optimum.PosPrev := cur;
optimum.BackPrev := curBack + ULZMABase.kNumRepDistances;
optimum.Prev1IsChar := false;
end;//if curAndLenPrice < optimum.Price
if lenTest = _matchDistances[offs] then begin
if lenTest < numAvailableBytesFull then begin
t := min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
lenTest2 := _matchFinder.GetMatchLen(lenTest, curBack, t);
if lenTest2 >= 2 then begin
state2 := ULZMABase.StateUpdateMatch(state);
posStateNext := (position + lenTest) and _posStateMask;
curAndLenCharPrice := curAndLenPrice +
RangeEncoder.GetPrice0(_isMatch[(state2 shl ULZMABase.kNumPosStatesBitsMax) + posStateNext]) +
_literalEncoder.GetSubCoder(position + lenTest,
_matchFinder.GetIndexByte(lenTest - 1 - 1)).
GetPrice(true,
_matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1),
_matchFinder.GetIndexByte(lenTest - 1));
state2 := ULZMABase.StateUpdateChar(state2);
posStateNext := (position + lenTest + 1) and _posStateMask;
nextMatchPrice := curAndLenCharPrice + RangeEncoder.GetPrice1(_isMatch[(state2 shl ULZMABase.kNumPosStatesBitsMax) + posStateNext]);
nextRepMatchPrice := nextMatchPrice + RangeEncoder.GetPrice1(_isRep[state2]);
offset := lenTest + 1 + lenTest2;
while lenEnd < cur + offset do begin
inc(lenEnd);
_optimum[lenEnd].Price := kIfinityPrice;
end;//while lenEnd
curAndLenPrice := nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
optimum := _optimum[cur + offset];
if curAndLenPrice < optimum.Price then begin
optimum.Price := curAndLenPrice;
optimum.PosPrev := cur + lenTest + 1;
optimum.BackPrev := 0;
optimum.Prev1IsChar := true;
optimum.Prev2 := true;
optimum.PosPrev2 := cur;
optimum.BackPrev2 := curBack + ULZMABase.kNumRepDistances;
end;//if curAndLenPrice < optimum.Price
end;//if lenTest2 >= 2
end;//lenTest < numAvailableBytesFull
offs :=offs + 2;
if offs = numDistancePairs then
break;
end;//if lenTest = _matchDistances[offs]
inc(lenTest);
end;//while(true)
end;//if newLen >= startLen
end;//while (true)
end;
function TLZMAEncoder.ChangePair(const smallDist, bigDist:integer):boolean;
var kDif:integer;
begin
kDif := 7;
result:= (smallDist < (1 shl (32 - kDif))) and (bigDist >= (smallDist shl kDif));
end;
procedure TLZMAEncoder.WriteEndMarker(const posState:integer);
var len,posSlot,lenToPosState,footerBits,posReduced:integer;
begin
if not _writeEndMark then
exit;
_rangeEncoder.Encode(_isMatch, (_state shl ULZMABase.kNumPosStatesBitsMax) + posState, 1);
_rangeEncoder.Encode(_isRep, _state, 0);
_state := ULZMABase.StateUpdateMatch(_state);
len := ULZMABase.kMatchMinLen;
_lenEncoder.Encode(_rangeEncoder, len - ULZMABase.kMatchMinLen, posState);
posSlot := (1 shl ULZMABase.kNumPosSlotBits) - 1;
lenToPosState := ULZMABase.GetLenToPosState(len);
_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
footerBits := 30;
posReduced := (1 shl footerBits) - 1;
_rangeEncoder.EncodeDirectBits(posReduced shr ULZMABase.kNumAlignBits, footerBits - ULZMABase.kNumAlignBits);
_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced and ULZMABase.kAlignMask);
end;
procedure TLZMAEncoder.Flush(const nowPos:integer);
begin
ReleaseMFStream;
WriteEndMarker(nowPos and _posStateMask);
_rangeEncoder.FlushData();
_rangeEncoder.FlushStream();
end;
procedure TLZMAEncoder.CodeOneBlock(var inSize,outSize:int64;var finished:boolean);
var progressPosValuePrev:int64;
posState,len,pos,complexState,distance,i,posSlot,lenToPosState:integer;
footerBits,baseVal,posReduced:integer;
curByte,matchByte:byte;
subcoder:TLZMAEncoder2;
begin
inSize := 0;
outSize := 0;
finished := true;
if _inStream <>nil then begin
_matchFinder.SetStream(_inStream);
_matchFinder.Init;
_needReleaseMFStream := true;
_inStream := nil;
end;
if _finished then
exit;
_finished := true;
progressPosValuePrev := nowPos64;
if nowPos64 = 0 then begin
if _matchFinder.GetNumAvailableBytes = 0 then begin
Flush(nowPos64);
exit;
end;
ReadMatchDistances;
posState := integer(nowPos64) and _posStateMask;
_rangeEncoder.Encode(_isMatch, (_state shl ULZMABase.kNumPosStatesBitsMax) + posState, 0);
_state := ULZMABase.StateUpdateChar(_state);
curByte := _matchFinder.GetIndexByte(0 - _additionalOffset);
_literalEncoder.GetSubCoder(integer(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
_previousByte := curByte;
dec(_additionalOffset);
inc(nowPos64);
end;
if _matchFinder.GetNumAvailableBytes = 0 then begin
Flush(integer(nowPos64));
exit;
end;
while true do begin
len := GetOptimum(integer(nowPos64));
pos := backRes;
posState := integer(nowPos64) and _posStateMask;
complexState := (_state shl ULZMABase.kNumPosStatesBitsMax) + posState;
if (len = 1) and (pos = -1) then begin
_rangeEncoder.Encode(_isMatch, complexState, 0);
curByte := _matchFinder.GetIndexByte(0 - _additionalOffset);
subCoder := _literalEncoder.GetSubCoder(integer(nowPos64), _previousByte);
if not ULZMABase.StateIsCharState(_state) then begin
matchByte := _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
end else subCoder.Encode(_rangeEncoder, curByte);
_previousByte := curByte;
_state := ULZMABase.StateUpdateChar(_state);
end else begin
_rangeEncoder.Encode(_isMatch, complexState, 1);
if pos < ULZMABase.kNumRepDistances then begin
_rangeEncoder.Encode(_isRep, _state, 1);
if pos = 0 then begin
_rangeEncoder.Encode(_isRepG0, _state, 0);
if len = 1 then
_rangeEncoder.Encode(_isRep0Long, complexState, 0)
else _rangeEncoder.Encode(_isRep0Long, complexState, 1);
end else begin
_rangeEncoder.Encode(_isRepG0, _state, 1);
if pos = 1 then
_rangeEncoder.Encode(_isRepG1, _state, 0)
else begin
_rangeEncoder.Encode(_isRepG1, _state, 1);
_rangeEncoder.Encode(_isRepG2, _state, pos - 2);
end;
end;
if len = 1 then
_state := ULZMABase.StateUpdateShortRep(_state)
else begin
_repMatchLenEncoder.Encode(_rangeEncoder, len - ULZMABase.kMatchMinLen, posState);
_state := ULZMABase.StateUpdateRep(_state);
end;
distance := _repDistances[pos];
if pos <> 0 then begin
for i := pos downto 1 do
_repDistances[i] := _repDistances[i - 1];
_repDistances[0] := distance;
end;
end else begin
_rangeEncoder.Encode(_isRep, _state, 0);
_state := ULZMABase.StateUpdateMatch(_state);
_lenEncoder.Encode(_rangeEncoder, len - ULZMABase.kMatchMinLen, posState);
pos := pos - ULZMABase.kNumRepDistances;
posSlot := GetPosSlot(pos);
lenToPosState := ULZMABase.GetLenToPosState(len);
_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
if posSlot >= ULZMABase.kStartPosModelIndex then begin
footerBits := integer((posSlot shr 1) - 1);
baseVal := ((2 or (posSlot and 1)) shl footerBits);
posReduced := pos - baseVal;
if posSlot < ULZMABase.kEndPosModelIndex then
UBitTreeEncoder.ReverseEncode(_posEncoders,
baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced)
else begin
_rangeEncoder.EncodeDirectBits(posReduced shr ULZMABase.kNumAlignBits, footerBits - ULZMABase.kNumAlignBits);
_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced and ULZMABase.kAlignMask);
inc(_alignPriceCount);
end;
end;
distance := pos;
for i := ULZMABase.kNumRepDistances - 1 downto 1 do
_repDistances[i] := _repDistances[i - 1];
_repDistances[0] := distance;
inc(_matchPriceCount);
end;
_previousByte := _matchFinder.GetIndexByte(len - 1 - _additionalOffset);
end;
_additionalOffset := _additionalOffset - len;
nowPos64 := nowPos64 + len;
if _additionalOffset = 0 then begin
// if (!_fastMode)
if _matchPriceCount >= (1 shl 7) then
FillDistancesPrices;
if _alignPriceCount >= ULZMABase.kAlignTableSize then
FillAlignPrices;
inSize := nowPos64;
outSize := _rangeEncoder.GetProcessedSizeAdd;
if _matchFinder.GetNumAvailableBytes = 0 then begin
Flush(integer(nowPos64));
exit;
end;
if (nowPos64 - progressPosValuePrev >= (1 shl 12)) then begin
_finished := false;
finished := false;
exit;
end;
end;
end;
end;
procedure TLZMAEncoder.ReleaseMFStream;
begin
if (_matchFinder <>nil) and _needReleaseMFStream then begin
_matchFinder.ReleaseStream;
_needReleaseMFStream := false;
end;
end;
procedure TLZMAEncoder.SetOutStream(const outStream:TStream);
begin
_rangeEncoder.SetStream(outStream);
end;
procedure TLZMAEncoder.ReleaseOutStream;
begin
_rangeEncoder.ReleaseStream;
end;
procedure TLZMAEncoder.ReleaseStreams;
begin
ReleaseMFStream;
ReleaseOutStream;
end;
procedure TLZMAEncoder.SetStreams(const inStream, outStream:TStream;const inSize, outSize:int64);
begin
_inStream := inStream;
_finished := false;
_Create();
SetOutStream(outStream);
Init();
// if (!_fastMode)
FillDistancesPrices;
FillAlignPrices;
_lenEncoder.SetTableSize(_numFastBytes + 1 - ULZMABase.kMatchMinLen);
_lenEncoder.UpdateTables(1 shl _posStateBits);
_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - ULZMABase.kMatchMinLen);
_repMatchLenEncoder.UpdateTables(1 shl _posStateBits);
nowPos64 := 0;
end;
procedure TLZMAEncoder.Code(const inStream, outStream:TStream;const inSize, outSize:int64);
var lpos:int64;
progint:int64;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -