📄 wavelet_form.pas
字号:
GetMem(Cb, NWidth * NHeight * SizeOf(wv_pel));
GetMem(Cr, NWidth * NHeight * SizeOf(wv_pel));
wv_rgb_to_ycbcr(NWidth * NHeight, Channels[NumChannels].Data, Channels[NumChannels + 1].Data,
Channels[NumChannels + 2].Data, Y, Cb, Cr);
FreeMem(Channels[NumChannels].Data);
Channels[NumChannels].Data := Y;
FreeMem(Channels[NumChannels + 1].Data);
Channels[NumChannels + 1].Data := Cb;
FreeMem(Channels[NumChannels + 2].Data);
Channels[NumChannels + 2].Data := Cr;
end;
Inc(NumChannels, 3);
end;
SourceImage.Free();
end;
end;
if (node <> Nil) then
TreeViewChannels.Selected := node; // and display
TrackBarSizeBPPChange(TrackBarSizeBPP);
ProgRec.Bar := ProgressBar1;
ProgRec.MaxChannel := NumChannels - old_num_channels;
if (PageControlSettings.ActivePage = TabSheetQuality) then
max_bits := 0
else
max_bits := (Int64(NumChannels) * Int64(ImageWidth) * Int64(ImageHeight) * Int64(TrackBarSizeBPP.Position)) div Int64(1000);
for i := old_num_channels to NumChannels - 1 do with Channels[i] do begin // initialise the new channels
ProgRec.CurChannel := i - old_num_channels;
Channel := wv_init_channel(ImageWidth, ImageHeight, Data, max_bits, 0, NumBlocks, ReorderTable, @wv_progress, @ProgRec);
if (Channel = Nil) then
break; // abort loop if we quit
end;
EnableUI();
end;
procedure TFormWavelet.CheckBoxGreyScaleClick(Sender: TObject);
begin
CheckBoxYCbCr.Enabled := not CheckBoxGreyScale.Checked;
end;
procedure TFormWavelet.TreeViewChannelsChange(Sender: TObject; Node: TTreeNode);
var
idx, subidx: Integer;
row: PByteArray;
x, y: Integer;
r, g, b: pawv_pel;
SourceImage: TBitmap;
did_cstats: Boolean;
mse: Single;
begin
if (Node = Nil) then
Exit;
did_cstats := False;
idx := Integer(Node.Data) shr 16;
subidx := Integer(Node.Data) and $ffff;
if (idx + subidx < NumChannels) then begin
SourceImage := TBitmap.Create();
SourceImage.PixelFormat := pf24bit;
SourceImage.Width := ImageWidth;
SourceImage.Height := ImageHeight;
if ((Node.Parent = Nil) and not (Channels[idx].IsGreyScale)) then begin // got a group (rgb or yuv)
if (Channels[idx].DidYCbCr) then begin
GetMem(r, NWidth * NHeight * SizeOf(wv_pel));
GetMem(g, NWidth * NHeight * SizeOf(wv_pel));
GetMem(b, NWidth * NHeight * SizeOf(wv_pel));
wv_ycbcr_to_rgb(NWidth * NHeight, Channels[idx].Data, Channels[idx + 1].Data,
Channels[idx + 2].Data, r, g, b);
end else begin
r := Channels[idx + 0].Data;
g := Channels[idx + 1].Data;
b := Channels[idx + 2].Data;
end;
end else begin // grey
if (Channels[idx + subidx].max_mse = 0.0) then
TrackBarPSNR.Position := TrackBarPSNR.Min
else
TrackBarPSNR.Position := TrackBarPSNR.Max - Round(TrackBarPSNR.PageSize * mse_to_psnr(Channels[idx + subidx].max_mse));
TrackBarDeltaMSE.Position := TrackBarDeltaMSE.Max div 2 + Round(Channels[idx + subidx].delta_mse * 1000.0);
if (Channels[idx + subidx].CData <> Nil) then begin
did_cstats := True;
EditOutRMSE.Text := Format('%7.3f', [Sqrt(Channels[idx + subidx].out_mse)]);
EditOutMSE.Text := Format('%7.3f', [Channels[idx + subidx].out_mse]);
if (Channels[idx + subidx].out_mse = 0.0) then
EditOutPSNR.Text := 'lossless'
else
EditOutPSNR.Text := Format('%7.3f', [mse_to_psnr(Channels[idx + subidx].out_mse)]);
end;
r := Channels[idx + subidx].Data;
g := Channels[idx + subidx].Data;
b := Channels[idx + subidx].Data;
end;
for y := 0 to ImageHeight - 1 do begin
row := SourceImage.ScanLine[y];
for x := 0 to ImageWidth - 1 do begin
row[x * 3 + ofs_R] := Min(255, Max(0, r[y * NWidth + x]));
row[x * 3 + ofs_G] := Min(255, Max(0, g[y * NWidth + x]));
row[x * 3 + ofs_B] := Min(255, Max(0, b[y * NWidth + x]));
end;
end;
if (not did_cstats) then begin
mse := 0.0;
x := 0;
for y := 0 to NumChannels - 1 do if (Channels[y].CData <> Nil) then begin
mse := mse + Channels[y].out_mse;
Inc(x);
end;
if (x > 0) then begin
mse := mse / x;
EditOutRMSE.Text := Format('%7.3f', [Sqrt(mse)]);
EditOutMSE.Text := Format('%7.3f', [mse]);
if (mse = 0.0) then
EditOutPSNR.Text := 'lossless'
else
EditOutPSNR.Text := Format('%7.3f', [mse_to_psnr(mse)]);
end else begin
EditOutRMSE.Text := '';
EditOutMSE.Text := '';
EditOutPSNR.Text := '';
end;
end;
FormImage.Constraints.MaxWidth := ImageWidth + ScrollBarX;
FormImage.Constraints.MaxHeight := ImageHeight + ScrollBarY;
FormImage.Image.Width := ImageWidth;
FormImage.Image.Height := ImageHeight;
FormImage.Image.Picture.Bitmap := SourceImage;
FormImage.Visible := True;
if (Channels[idx].CData <> Nil) then begin // now for compressed image
if ((Node.Parent = Nil) and not (Channels[idx].IsGreyScale)) then begin // got a group (rgb or yuv)
if (Channels[idx].DidYCbCr) then begin
wv_ycbcr_to_rgb(NWidth * NHeight, Channels[idx].CData, Channels[idx + 1].CData,
Channels[idx + 2].CData, r, g, b);
end else begin
r := Channels[idx + 0].CData;
g := Channels[idx + 1].CData;
b := Channels[idx + 2].CData;
end;
end else begin
r := Channels[idx + subidx].CData;
g := Channels[idx + subidx].CData;
b := Channels[idx + subidx].CData;
end;
for y := 0 to ImageHeight - 1 do begin
row := SourceImage.ScanLine[y];
for x := 0 to ImageWidth - 1 do begin
row[x * 3 + ofs_R] := Min(255, Max(0, r[y * NWidth + x]));
row[x * 3 + ofs_G] := Min(255, Max(0, g[y * NWidth + x]));
row[x * 3 + ofs_B] := Min(255, Max(0, b[y * NWidth + x]));
end;
end;
FormCImage.Constraints.MaxWidth := ImageWidth + ScrollBarX;
FormCImage.Constraints.MaxHeight := ImageHeight + ScrollBarY;
FormCImage.Image.Width := ImageWidth;
FormCImage.Image.Height := ImageHeight;
FormCImage.Image.Picture.Bitmap := SourceImage;
FormCImage.Visible := True;
end;
if ((Node.Parent = Nil) and Channels[idx].DidYCbCr) then begin
FreeMem(r);
FreeMem(g);
FreeMem(b);
end;
SourceImage.Free();
end;
end;
procedure TFormWavelet.CheckBoxStayOnTopClick(Sender: TObject);
begin
if (CheckBoxStayOnTop.Checked) then
FormStyle := fsStayOnTop
else
FormStyle := fsNormal;
end;
procedure TFormWavelet.ButtonClearClick(Sender: TObject);
var
i: Integer;
begin
for i := 0 to NumChannels - 1 do with Channels[i] do begin
if (Data <> Nil) then
FreeMem(Data);
if (CData <> Nil) then
FreeMem(CData);
wv_done_channel(Channel, Integer(i = 0));
Data := Nil;
CData := Nil;
Channel := Nil;
end;
NumChannels := 0;
NWidth := 0;
NHeight := 0;
ImageWidth := 0;
ImageHeight := 0;
ReorderTable := Nil;
NumBlocks := 0;
TrackBarSizeBPPChange(TrackBarSizeBPP);
TreeViewChannels.Items.Clear();
FormImage.Visible := False;
FormImage.Image.Picture := Nil;
FormCImage.Visible := False;
FormCImage.Image.Picture := Nil;
ButtonKompress.Enabled := False;
GroupBoxChannels.Caption := 'Channels:';
EditBits.Clear();
EditKiloBytes.Clear();
EditBPP.Clear();
EditOutPSNR.Clear();
EditOutMSE.Clear();
EditOutRMSE.Clear();
end;
procedure TFormWavelet.TrackBarPSNRChange(Sender: TObject);
var
idx, subidx: Integer;
begin
if (Sender is TTrackBar) then begin
if ((Sender as TTrackBar).Position = (Sender as TTrackBar).Min) then begin
EditPSNR.Text := 'lossless';
EditMSE.Text := Format('%7.3f', [0.0]);
end else begin
EditPSNR.Text := Format('%7.3f', [((Sender as TTrackBar).Max - (Sender as TTrackBar).Position) / (Sender as TTrackBar).PageSize]);
EditMSE.Text := Format('%7.3f', [Sqrt(psnr_to_mse(((Sender as TTrackBar).Max - (Sender as TTrackBar).Position) / (Sender as TTrackBar).PageSize))]);
end;
if (TreeViewChannels.Selected <> Nil) then begin
idx := Integer(TreeViewChannels.Selected.Data) shr 16;
subidx := Integer(TreeViewChannels.Selected.Data) and $ffff;
if ((TreeViewChannels.Selected.Parent = Nil) and not (Channels[idx].IsGreyScale)) then begin // got a group (rgb or yuv)
ApplySettings([SMaxMSE], Channels[idx + 0]);
ApplySettings([SMaxMSE], Channels[idx + 1]);
ApplySettings([SMaxMSE], Channels[idx + 2]);
end else begin
ApplySettings([SMaxMSE], Channels[idx + subidx]);
end;
end;
end;
end;
procedure TFormWavelet.ButtonKompressClick(Sender: TObject);
var
ChPar: array[0..wv_MAX_CHANNELS - 1] of t_wv_mchannel_params;
Sets: array[0..wv_MAX_CHANNELS - 1] of tp_wv_csettings;
i, bits: Integer;
bf: tp_bit_file;
mem: PByteArray;
dc: tp_wv_dchannels;
MaxBits: Integer;
fname: String;
save_as_bmp: Boolean;
begin
for i := 0 to wv_MAX_CHANNELS - 1 do
Sets[i] := Nil;
EditBits.Text := '';
EditKiloBytes.Text := '';
EditBPP.Text := '';
EditOutPSNR.Text := '';
EditOutMSE.Text := '';
EditOutRMSE.Text := '';
if (NumChannels > 0) then begin
if (PageControlSettings.ActivePage = TabSheetQuality) then begin
for i := 0 to NumChannels - 1 do begin
ChPar[i].cc := Channels[i].Channel;
ChPar[i].max_mse := Channels[i].max_mse;
end;
bits := wv_init_multi_channels(0, 1.0, NumChannels, @ChPar, @Sets);
end else begin
for i := 0 to NumChannels - 1 do begin
ChPar[i].cc := Channels[i].Channel;
ChPar[i].max_mse := Sqr(Sqr(Channels[i].delta_mse));
if (Channels[i].delta_mse > 0.0) then
ChPar[i].max_mse := -ChPar[i].max_mse; // reverse sign
end;
MaxBits := (Int64(NumChannels) * Int64(ImageWidth) * Int64(ImageHeight) * Int64(TrackBarSizeBPP.Position)) div Int64(1000);
bits := wv_init_multi_channels(MaxBits, 0.0, NumChannels, @ChPar, @Sets);
end;
if (bits > 0) then begin
bf := Nil;
fname := '';
save_as_bmp := False;
if (CheckBoxSave.Checked and SaveDialog1.Execute()) then begin
fname := SaveDialog1.FileName;
save_as_bmp := AnsiCompareFileName(ExtractFileExt(fname), '.BMP') = 0;
end;
if ((fname <> '') and (not save_as_bmp)) then begin
bf := bit_open(PChar(fname), 'wb', 0);
if (bf = Nil) then
fname := '';
end;
if (bf = Nil) then
bf := bit_open(Nil, 'wm', wv_MAX_HEADER_SIZE + bits);
if (bf <> Nil) then begin
bit_write(Integer(Channels[0].DidYCbCr), 1, bf);
wv_encode_channels(NumChannels, @Sets, bf);
mem := Nil;
bits := bit_close(bf, @mem);
if (mem <> Nil) then
bf := bit_open(Pointer(mem), 'rm', bits) // open from mem
else
bf := bit_open(PChar(fname), 'rb', bits);
bit_read(1, bf); // skip YCbCr flag
dc := wv_init_decode_channels(bf);
if (dc <> Nil) then begin
for i := 0 to NumChannels - 1 do with Channels[i] do begin
if (CData <> Nil) then
FreeMem(CData);
GetMem(CData, dc^.width * dc^.height * SizeOf(wv_pel));
Move(dc^.channels^[i]^, CData^, dc^.width * dc^.height * SizeOf(wv_pel));
wv_calc_psnr(Data, CData, ImageWidth, ImageHeight, NWidth, out_mse);
end;
wv_done_decode_channels(dc);
EditBits.Text := IntToStr(bits);
EditKiloBytes.Text := Format('%7.3f', [bits / 8192.0]);
EditBPP.Text := Format('%7.3f', [bits / (NumChannels * ImageWidth * ImageHeight)]);
TreeViewChannelsChange(Self, TreeViewChannels.Selected);
if ((fname <> '') and save_as_bmp) then
FormCImage.Image.Picture.SaveToFile(fname);
end;
bit_close(bf, Pointer(mem)); // frees the pointer
end;
end;
for i := 0 to NumChannels - 1 do
if (Sets[i] <> Nil) then
wv_done_channel_settings(Sets[i]);
end;
end;
procedure TFormWavelet.TrackBarSizeBPPChange(Sender: TObject);
begin
if (Sender is TTrackBar) then begin
EditSizeBPP.Text := Format('%.3f', [(Sender as TTrackBar).Position / 1000.0]);
EditSizeSize.Text := Format('%.3f', [(Int64(NumChannels) * Int64(ImageWidth) * Int64(ImageHeight) * Int64((Sender as TTrackBar).Position)) / (1024.0 * 1000.0 * 8.0)]);
end;
end;
procedure TFormWavelet.UpDownSizeChangingEx(Sender: TObject;
var AllowChange: Boolean; NewValue: Smallint;
Direction: TUpDownDirection);
begin
if ((NewValue < TrackBarSizeBPP.Min) or (NewValue > TrackBarSizeBPP.Max)) then
AllowChange := False
else
TrackBarSizeBPP.Max := MaxSizeTrack shr NewValue;
end;
procedure TFormWavelet.TrackBarDeltaMSEChange(Sender: TObject);
var
idx, subidx: Integer;
d: Single;
begin
if (Sender is TTrackBar) then begin
d := ((Sender as TTrackBar).Position - (Sender as TTrackBar).Max div 2) / 1000.0;
if (d < 0) then
d := -Sqr(d)
else
d := Sqr(d);
EditDeltaMSE.Text := Format('%6.3f', [d]);
if (TreeViewChannels.Selected <> Nil) then begin
idx := Integer(TreeViewChannels.Selected.Data) shr 16;
subidx := Integer(TreeViewChannels.Selected.Data) and $ffff;
if ((TreeViewChannels.Selected.Parent = Nil) and not (Channels[idx].IsGreyScale)) then begin // got a group (rgb or yuv)
ApplySettings([SDeltaMSE], Channels[idx + 0]);
ApplySettings([SDeltaMSE], Channels[idx + 1]);
ApplySettings([SDeltaMSE], Channels[idx + 2]);
end else begin
ApplySettings([SDeltaMSE], Channels[idx + subidx]);
end;
end;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -