algorytm.org

Implementacja w Delphi/Pascal



Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Model YUV - Implementacja w Delphi/Pascal
Ocena użytkownikóww: *****  / 1
SłabyŚwietny
Nadesłany przez Tomasz Lubiński, 27 listopada 2007 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.
Pobierz pełne rozwiązanie.

Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.

YUV - Delphi/Unit1.pas:
// Model YUV
// www.algorytm.org
// (c)2007 by Tomasz Lubinski

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Math;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    Model: TImage;
    Label1: TLabel;
    Button1: TButton;
    WidthVal: TEdit;
    GroupBox2: TGroupBox;
    ProbeLarge: TImage;
    ProbeSmall: TImage;
    Probe: TImage;
    YVal: TEdit;
    UVal: TEdit;
    VVal: TEdit;
    YButton: TRadioButton;
    UButton: TRadioButton;
    VButton: TRadioButton;
    GroupBox3: TGroupBox;
    AllLayers: TImage;
    LayerY: TImage;
    LayerU: TImage;
    LayerV: TImage;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    white: TRadioButton;
    black: TRadioButton;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure ReDrawProbe(Sender: TObject);
    procedure ReDrawRectangle(Sender: TObject);
    procedure YButtonClick(Sender: TObject);
    procedure UButtonClick(Sender: TObject);
    procedure VButtonClick(Sender: TObject);
    procedure YValChange(Sender: TObject);
    procedure UValChange(Sender: TObject);
    procedure VValChange(Sender: TObject);
    procedure ProbeLargeMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ProbeSmallMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormActivate(Sender: TObject);
    procedure DrawLayers();
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  PPixelRec = ^TPixelRec;
  TPixelRec = packed record
    B: Byte;
    G: Byte;
    R: Byte;
    Reserved: Byte;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}



procedure yuv2rgb(y: double; u: double; v: double; var r: double; var g: double; var b: double);
begin
   r := 1*y + 0*u + 1.13983*v;
   g := 1*y -0.39465*u + -0.58060*v;
   b := 1*y + 2.03211*u + 0*v;
   if (r>1) then r := 1;
   if (g>1) then g := 1;
   if (b>1) then b := 1;
   if (r<0) then r := 0;
   if (g<0) then g := 0;
   if (b<0) then b := 0;
end;

procedure rgb2yuv(var y: double; var u: double; var v: double; r: double; g: double; b: double);
begin
   y := 0.299*r + 0.587*g + 0.114*b;
   u := 0.493*(b - y);
   v := 0.877*(r - y);
end;


procedure TForm1.Button1Click(Sender: TObject);
var
   r, g, b, y, u, v : double;
   width, shift_x, shift_y, side, side_sign, i, j: Integer;

begin

   Model.Canvas.Brush.Color := clWhite;
   Model.Canvas.Rectangle(0, 0, Model.Width, Model.Height);

   width := StrToInt(WidthVal.Text);

   shift_x := Model.Width div 2 - Round(width / 1.5);
   shift_y := Round(width * 1.5 + 50);

   if (black.Checked) then
   begin
      side := 0;
      side_sign := -1;
   end
   else
   begin
      side := 1;
      side_sign := 1;
   end;

   for i:=0 to width-1 do
      for j:=0 to width-1 do
      begin
         y := side;
         u := (0.436 - (0.872/width)*i)*side_sign;
         v := (0.615 - (1.23/width)*j)*side_sign;
         YUV2RGB(y, u, v, r, g, b);
         if (i=0) or (j=0) or (j = width -1) then
         begin
           g := 0;
           b := 0;
           r := 0;
         end;
         Model.Canvas.Pixels[i+shift_x, shift_y-j] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16));
      end;

   for i:=0 to width-1 do
      for j:=0 to (width div 2)-1 do
      begin
         y := (side - j/(width/2.0))*side_sign;
         u := (0.436 - (0.872/width)*i)*side_sign;
         v := (-0.615)*side_sign;
         YUV2RGB(y, u, v, r, g, b);
         if (i=0) or (i = width -1) or (j = (width div 2)-1) then
         begin
           g := 0;
           b := 0;
           r := 0;
         end;
         Model.Canvas.Pixels[i+j+shift_x, shift_y-j-width] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16));
      end;

   for i:=0 to (width div 2)-1 do
      for j:=0 to width-1 do
      begin
         y := (side - i/(width/2.0))*side_sign;
         u := (-0.436)*side_sign;
         v := (0.615 - (1.23/width)*j)*side_sign;
         YUV2RGB(y, u, v, r, g, b);
         if (i=0) or (j=0) or (i = (width div 2)-1) then
         begin
           g := 0;
           b := 0;
           r := 0;
         end;
         Model.Canvas.Pixels[i+shift_x+width, shift_y-j-i-1] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16));
      end;

   Model.Canvas.MoveTo(shift_x, shift_y + 20);
   Model.Canvas.LineTo(shift_x + width, shift_y + 20);
   Model.Canvas.LineTo(shift_x + width - 5, shift_y + 15);
   Model.Canvas.MoveTo(shift_x + width, shift_y + 20);
   Model.Canvas.LineTo(shift_x + width - 5, shift_y + 25);
   Model.Canvas.TextOut(shift_x + 10, shift_y + 7, 'V');

   Model.Canvas.MoveTo(shift_x - 20, shift_y);
   Model.Canvas.LineTo(shift_x - 20, shift_y - width);
   Model.Canvas.LineTo(shift_x - 25, shift_y - width + 5);
   Model.Canvas.MoveTo(shift_x - 20, shift_y - width);
   Model.Canvas.LineTo(shift_x - 15, shift_y - width + 5);
   Model.Canvas.TextOut(shift_x - 15, shift_y - 20, 'Y');

   Model.Canvas.MoveTo(shift_x + width + 2, shift_y + 18);
   Model.Canvas.LineTo(Round(shift_x + width * 1.5 + 2), shift_y + 18 - width div 2);
   Model.Canvas.LineTo(Round(shift_x + width * 1.5 - 5), shift_y + 18 - width div 2);
   Model.Canvas.MoveTo(Round(shift_x + width * 1.5 + 2), shift_y + 18 - width div 2);
   Model.Canvas.LineTo(Round(shift_x + width * 1.5 + 2), shift_y + 25 - width div 2);
   Model.Canvas.TextOut(shift_x + width + 10, shift_y - 10, 'U');
end;

procedure TForm1.ReDrawProbe(Sender: TObject);
var
   r, g, b, y, u, v: double;
   i, j: Integer;
   P: PPixelRec;
begin
   y := StrToFloat(YVal.Text);
   u := StrToFloat(UVal.Text);
   v := StrToFloat(VVal.Text);
   YUV2RGB(y, u, v, r, g, b);
   ProbeSmall.Canvas.Brush.Color := clWhite;
   ProbeSmall.Canvas.Rectangle(0, 0, ProbeSmall.Width, ProbeSmall.Height);
   ProbeSmall.Picture.Bitmap.PixelFormat := pf32Bit;

   if (YButton.Checked) then
   begin
      for i:=0 to 255 do
      begin
         y := 1 - i/255.0;
         YUV2RGB(y, u, v, r, g, b);
         P := ProbeSmall.Picture.Bitmap.ScanLine[i];
         for j:=1 to ProbeSmall.Picture.Bitmap.Width do
         begin
            P.R := Round(r*255);
            P.G := Round(g*255);
            P.B := Round(b*255);
            Inc(P);
         end;
      end
   end
   else if (UButton.Checked) then
   begin
      for i:=0 to 255 do
      begin
         u := 0.436 - i/292.43;
         YUV2RGB(y, u, v, r, g, b);
         P := ProbeSmall.Picture.Bitmap.ScanLine[i];
         for j:=1 to ProbeSmall.Picture.Bitmap.Width do
         begin
            P.R := Round(r*255);
            P.G := Round(g*255);
            P.B := Round(b*255);
            Inc(P);
         end;
      end
   end
   else if (VButton.Checked) then
   begin
      for i:=0 to 255 do
      begin
         v := 0.615 - i/207.31;
         YUV2RGB(y, u, v, r, g, b);
         P := ProbeSmall.Picture.Bitmap.ScanLine[i];
         for j:=1 to ProbeSmall.Picture.Bitmap.Width do
         begin
            P.R := Round(r*255);
            P.G := Round(g*255);
            P.B := Round(b*255);
            Inc(P);
         end;
      end
   end;

   y := StrToFloat(YVal.Text);
   u := StrToFloat(UVal.Text);
   v := StrToFloat(VVal.Text);

   ProbeLarge.Canvas.Brush.Color := clWhite;
   ProbeLarge.Canvas.Rectangle(0, 0, ProbeLarge.Width, ProbeLarge.Height);

   ProbeLarge.Picture.Bitmap.PixelFormat := pf32Bit;
   if (YButton.Checked) then
   begin
      for j:=0 to 255 do
      begin
         P := ProbeLarge.Picture.Bitmap.ScanLine[255-j];
         for i:=0 to 255 do
         begin
            u := i/292.43 - 0.436;
            v := j/207.31 - 0.615;
            YUV2RGB(y, u, v, r, g, b);
            P.R := Round(r*255);
            P.G := Round(g*255);
            P.B := Round(b*255);
            Inc(P);
         end;
      end;
   end
   else if (UButton.Checked) then
   begin
      for j:=0 to 255 do
      begin
         P := ProbeLarge.Picture.Bitmap.ScanLine[255-j];
         for i:=0 to 255 do
         begin
            y := i/255.0;
            v := j/207.31 - 0.615;
            YUV2RGB(y, u, v, r, g, b);
            P.R := Round(r*255);
            P.G := Round(g*255);
            P.B := Round(b*255);
            Inc(P);
         end;
      end;
   end
   else if (VButton.Checked) then
   begin
      for j:=0 to 255 do
      begin
         P := ProbeLarge.Picture.Bitmap.ScanLine[255-j];
         for i:=0 to 255 do
         begin
            y := i/255.0;
            u := j/292.43 - 0.436;
            YUV2RGB(y, u, v, r, g, b);
            P.R := Round(r*255);
            P.G := Round(g*255);
            P.B := Round(b*255);
            Inc(P);
         end;
      end;
   end;

   ReDrawRectangle(Sender);
end;

procedure TForm1.ReDrawRectangle(Sender: TObject);
var
   r, g, b, y, u, v: double;
begin
   y := StrToFloat(YVal.Text);
   u := StrToFloat(UVal.Text);
   v := StrToFloat(VVal.Text);
   YUV2RGB(y, u, v, r, g, b);
   Probe.Canvas.Brush.Color := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16));
   Probe.Canvas.Rectangle(0, 0, Probe.Width, Probe.Height);

   if (YButton.Checked) then
   begin
      ProbeSmall.Canvas.Ellipse(5, Round((1-y)*255-3), 13, Round((1-y)*255+3));
      ProbeLarge.Canvas.Ellipse(Round((u+0.436)*292.43-3), Round((0.615-v)*207.31-3),
       Round((u+0.436)*292.43+3), Round((0.615-v)*207.31+3));
   end
   else if (UButton.Checked) then
   begin
      ProbeSmall.Canvas.Ellipse(5, Round((0.436-u)*292.43-3), 13, Round((0.436-u)*292.43+3));
      ProbeLarge.Canvas.Ellipse(Round(y*255-3), Round((0.615-v)*207.31-3), Round(y*255+3), Round((0.615-v)*207.31+3));
   end
   else if (VButton.Checked) then
   begin
      ProbeSmall.Canvas.Ellipse(5, Round((0.615-v)*207.31-3), 13, Round((0.615-v)*207.31+3));
      ProbeLarge.Canvas.Ellipse(Round(y*255-3), Round((0.436-u)*292.43-3), Round(y*255+3), Round((0.436-u)*292.43+3));
   end;
end;

procedure TForm1.YButtonClick(Sender: TObject);
begin
     ReDrawProbe(Sender);
end;

procedure TForm1.UButtonClick(Sender: TObject);
begin
     ReDrawProbe(Sender);     
end;

procedure TForm1.VButtonClick(Sender: TObject);
begin
     ReDrawProbe(Sender);
end;

procedure TForm1.YValChange(Sender: TObject);
begin
     ReDrawProbe(Sender);
end;

procedure TForm1.UValChange(Sender: TObject);
begin
     ReDrawProbe(Sender);
end;

procedure TForm1.VValChange(Sender: TObject);
begin
     ReDrawProbe(Sender);
end;

procedure TForm1.ProbeLargeMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   if (YButton.Checked) then
   begin
      UVal.Text := FloatToStr(X/292.43 - 0.436);
      VVal.Text := FloatToStr(0.615 - Y/207.31);
   end
   else if (UButton.Checked) then
   begin
      YVal.Text := FloatToStr(X/255.0);
      VVal.Text := FloatToStr(0.615 - Y/207.31);
   end
   else if (VButton.Checked) then
   begin
      YVal.Text := FloatToStr(X/255.0);
      UVal.Text := FloatToStr(0.436 - Y/292.43);
   end;
end;

procedure TForm1.ProbeSmallMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   if (YButton.Checked) then
   begin
      YVal.Text := FloatToStr(1 - Y/255.0);
   end
   else if (UButton.Checked) then
   begin
      UVal.Text := FloatToStr(0.436 - Y/292.43);
   end
   else if (VButton.Checked) then
   begin
      VVal.Text := FloatToStr(0.615 - Y/207.31);
   end;
end;

procedure TForm1.DrawLayers();
var
   color: TColor;
   r, g, b, y, u, v: double;
   i, j: Integer;
begin
   for j:=0 to AllLayers.Height-1 do
   begin
      for i:=0 to AllLayers.Width-1 do
      begin
          color := AllLayers.Canvas.Pixels[i, j];
          r := (color and $FF) / 255.0;
          g := ((color and $FF00) shr 8) / 255.0;
          b := ((color and $FF0000) shr 16) / 255.0;
          RGB2YUV(y, u, v, r, g, b);
          YUV2RGB(y, 0, 0, r, g, b);
          LayerY.Canvas.Pixels[i, j] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16));
          YUV2RGB(0, u, 0, r, g, b);
          LayerU.Canvas.Pixels[i, j] := (Round(255 - (u+0.416)*306) shl 8) + (Round((u+0.416)*306) shl 16);
          YUV2RGB(0, 0, v, r, g, b);
          LayerV.Canvas.Pixels[i, j] := Round(((v+0.615)*207) + (Round(255 - (v+0.615)*207) shl 8));
      end;
   end;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
   ReDrawProbe(Sender);
   Button1Click(Sender);
   DrawLayers();
end;

end.
Dodaj komentarz