📄 aicdecoder.pas
字号:
unit AICDecoder;
{ Advanced Image Coding (AIC)
===========================
The main decoder class }
interface
uses
AICBase, AICCommon, AICCabacDecoder, Graphics, Classes;
type
TAICDecoder = class(TAICBase)
{ The main decoder class }
private
FCabac: TAICCabacDecoder;
{ The Contact Adaptive Binary Arithmetic Decoder uses for decoding
values from the stream }
procedure ReadHeader;
{ Reads the header from the stream }
procedure Decode;
{ The main decoding method }
public
constructor Create(const SrcFilename: String; const Dst: TBitmap); overload;
{ Creates the decoder and decompresses the file SrcFilename to the
Dst bitmap }
constructor Create(const SrcStream: TStream; const Dst: TBitmap); overload;
{ Creates the decoder and decompresses the stream SrcStream to the
Dst bitmap }
destructor Destroy; override;
{ Cleanup }
class procedure Expand(const SrcFilename: String; const Dst: TBitmap); overload;
{ Helper class method to decompress a file to a bitmap.
Just uses this class to do the actual decompression. }
class procedure Expand(const SrcStream: TStream; const Dst: TBitmap); overload;
{ Helper class method to decompress a stream to a bitmap.
Just uses this class to do the actual decompression. }
end;
implementation
uses
SysUtils, AICInvColorConversion, AICInvDCT;
{ TAICDecoder }
constructor TAICDecoder.Create(const SrcFilename: String;
const Dst: TBitmap);
var
Stream: TStream;
begin
Stream := TFileStream.Create(SrcFilename,fmOpenRead or fmShareDenyWrite);
Create(Stream,Dst);
OwnsStream := True;
end;
constructor TAICDecoder.Create(const SrcStream: TStream;
const Dst: TBitmap);
begin
inherited Create(SrcStream);
ReadHeader;
FCabac := TAICCabacDecoder.Create(Quality,Stream);
Decode;
if ImageFormat = ifGreyscale then
ConvertGreyscaleChannelToBitmap(Channels[ctY],Dst,Width,Height)
else
ConvertYCbCrChannelsToBitmap(Channels,Dst,Width,Height);
end;
procedure TAICDecoder.Decode;
var
X, Y, Z, XB, YB, XI, YI: Integer;
Mode: TAICPredictionMode;
Predicted: TAICByteBlock;
DCT: TAICIntBlock;
CT: TAICChannelType;
begin
{ Process all 8x8 blocks in the image }
for CT := ctY to ctMax do begin
YB := 0; YI := 0;
while YB < PaddedHeight do begin
XB := 0; XI := 0;
while XB < PaddedWidth do begin
if CT = ctY then begin
{ The prediction mode is only stored for Y-channels }
Mode := PredictPredictionMode(XI,YI);
X := FCabac.ReadPredictionMode;
if X >= 0 then
if X < Ord(Mode) then
Mode := TAICPredictionMode(X)
else
Mode := TAICPredictionMode(X + 1);
PreviousPredictionModes[YI,XI] := Mode;
end else
{ Cb and Cr channels use the same prediction mode as for the
corresponding block in the Y channel }
Mode := PreviousPredictionModes[YI,XI];
Predict(Mode,Channels[CT],XB,YB,Predicted);
FCabac.ReadCoefficients(CT,DCT);
DequantizeAndInverseDCT(DCT,InvQuant);
Z := 0;
for Y := 0 to RowColSize - 1 do
for X := 0 to RowColSize - 1 do begin
Channels[CT,YB + Y,XB + X] := AICByteClip[Predicted[Z] + DCT[Z]];
Inc(Z);
end;
Inc(XB,RowColSize); Inc(XI);
end;
Inc(YB,RowColSize); Inc(YI);
end;
end;
end;
destructor TAICDecoder.Destroy;
begin
FCabac.Free;
inherited;
end;
class procedure TAICDecoder.Expand(const SrcFilename: String;
const Dst: TBitmap);
begin
Self.Create(SrcFilename,Dst).Free;
end;
class procedure TAICDecoder.Expand(const SrcStream: TStream;
const Dst: TBitmap);
begin
Self.Create(SrcStream,Dst).Free;
end;
procedure TAICDecoder.ReadHeader;
var
Header: TAICFileHeader;
begin
Stream.ReadBuffer(Header,SizeOf(Header));
if Header.FileID <> AICFileID then
AICError('Invalid AIC file');
if Header.FileVersion > AICFileVersion then
AICError('Unknown AIC file version');
SetImageProperties(Header.ImageWidth,Header.ImageHeight,Header.ImageFormat,
Header.Quality);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -