Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > хитрый цикл


Автор: Racer 17.8.2010, 17:33
Добрый день. у меня есть тут 1 код. 
Код

var
  Form7: TForm7;

  rc, gc, bc: array of Byte;

implementation

{$R *.dfm}

function R(Col:TColor):Byte;
var
  Color: Longint;
begin
  Color := ColorToRGB(Col);
  Result:= Color;
end;

function G(Col:TColor):Byte;
var
  Color: Longint;
begin
  Color := ColorToRGB(Col);
  Result:= Color shr 8;
end;

function B(Col:TColor):Byte;
var
  Color: Longint;
begin
  Color := ColorToRGB(Col);
  Result:= Color shr 16;
end;

procedure TForm7.Button1Click(Sender: TObject);
var
  len: integer;
  startx, stopx, starty, stopy: Integer;
  i,j, k: Integer;
  s, s2, s3: int64;
  Rav, Gav, Bav: Integer;
begin
  startx:=1;
  stopx:= 20;
  starty:=1;
  stopy:= Image1.Height-30;


  len:= (stopx-startx) * (stopy-starty);
//  ShowMessage(IntToStr(len));
  SetLength(rc, 0);
  SetLength(gc, 0);
  SetLength(bc, 0);
  SetLength(rc, len+1);
  SetLength(gc, len+1);
  SetLength(bc, len+1);

  k:= 0;
  for i := 0 to (stopx-startx) do
    for j := 0 to (stopy-starty) do begin
      rc[k]:= R(GetPixel(Image1.Canvas.Handle, i, j));
      bc[k]:= B(GetPixel(Image1.Canvas.Handle, i, j));
      gc[k]:= G(GetPixel(Image1.Canvas.Handle, i, j));
      k:= k+1;
    end;

  try
    s:= 0;
    s2:= 0;
    s3:= 0;
    for i := 0 to Length(rc)-1 do
      s:= s+ rc[i];
    Rav:= Round(s/Length(rc));
    for i := 0 to Length(gc)-1 do
      s2:= s2+ gc[i];
    Gav:= Round(s2/Length(gc));
    for i := 0 to Length(bc)-1 do
      s3:= s3+ bc[i];
    Bav:= Round(s3/Length(bc));
  except

  end;

  ShowMessage(IntToStr(Rav)+ ' '+ IntToStr(Gav)+' '+IntToStr(Bav));
end;

procedure TForm7.Button2Click(Sender: TObject);
begin
  Image1.Canvas.Brush.Color:= RGB(Random(254), Random(254), Random(254));
  Image1.Canvas.Rectangle(0, 0, Round(Image1.Width), Round(Image1.Height/2));
  Image1.Canvas.Brush.Color:= RGB(Random(254), Random(254), Random(254));
  Image1.Canvas.Rectangle(0, Round(Image1.Height/2),
    Image1.Width, Image1.Height);
end;


вот такой. проблема: когда жму кнопку 1 иногда (в 30-40% случаев нажатия) выбрасывается AV. ИДЕ тыкает сюда       s2:= s2+ пc[i]; а иногда сюда.       s3:= s3+ bc[i]; не пойму в чем дело. оно то работает  то  нет. помогите пожалуйста

Автор: Frees 17.8.2010, 17:44
Код

rc, gc, bc: array of Byte;
 - сделай членами класса для начала

Автор: Frees 17.8.2010, 18:01
Цитата(Racer @  17.8.2010,  20:33 Найти цитируемый пост)
len+1

не может принять значение 0?


Автор: Racer 17.8.2010, 19:05
А зачем делать их членами класса?

нулем быть не может, т.к.
Код

  startx:=1;
  stopx:= 20;
  starty:=1;
  stopy:= Image1.Height-30;
  len:= (stopx-startx) * (stopy-starty);

Автор: БелАмор 17.8.2010, 23:24
Цитата(Racer @  17.8.2010,  17:33 Найти цитируемый пост)
проблема: когда жму кнопку 1 иногда (в 30-40% случаев нажатия) выбрасывается AV


Вы неправильно определяете размер массива:
Цитата(Racer @  17.8.2010,  17:33 Найти цитируемый пост)

  startx:=1;
  stopx:= 20;
  starty:=1;
  stopy:= Image1.Height-30;
  len:= (stopx-startx) * (stopy-starty);

Исправьте последнюю строчку на:
Код

  len:= (stopx-startx+1) * (stopy-starty+1);

Дополнительные замечания

1. Во время отладки всегда включайте опции Range Checking и Overflow Checking. Это поможет избежать кучи проблем.
2. В функциях R, G, B вы присваиваете байту значение Longint. Это некрасиво, кроме того, при включенной опции Overflow Checking вы сразу же получите исключение.
Кстати, возможно, вас заинтересует статья: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1388
3.
Цитата(Racer @  17.8.2010,  17:33 Найти цитируемый пост)
  SetLength(rc, 0);
  SetLength(gc, 0);
  SetLength(bc, 0);
  SetLength(rc, len+1);
  SetLength(gc, len+1);
  SetLength(bc, len+1);

Три первые строчки - лишние...
4.
Цитата(Racer @  17.8.2010,  19:05 Найти цитируемый пост)
А зачем делать их членами класса?

Для порядка. Допустим (теоретически), что у вас существует два экземпляра этой формы одновременно... И что будет? Посмотрите ссылку (поиск по слову "Самоделкин"): 
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=68068

Автор: БелАмор 18.8.2010, 05:51
Ещё немного об оптимизации и хороших манерах...
Чтобы слишком сильно не занудствовать, я немного обработал ваш код напильником для примера...
Код

unit Unit7;

interface

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

type
  TForm7 = class(TForm)
    Button1: TButton;                                
    Button2: TButton;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    rc, gc, bc: array of Byte;
    procedure SomeCounts;
    procedure RandomDraw;
  public
    { Public declarations }
  end;

  // Эти два типа взяты из статьи
  TRGBS = packed record
    Red, Green, Blue, System: Byte;
  end;

  TRgbsColor = record case Boolean of
    True : (Color: TColor);
    False: (RGBS : TRGBS );
  end;

var
  Form7: TForm7;

implementation

{$R *.dfm}

procedure TForm7.Button1Click(Sender: TObject);
begin
  SomeCounts;
end;

procedure TForm7.Button2Click(Sender: TObject);
begin
  RandomDraw;
end;

procedure TForm7.SomeCounts;
var
  len: integer;
  startx, stopx, starty, stopy: Integer;
  i,j, k: Integer;
  s, s2, s3: int64;
  Rav, Gav, Bav: Integer;
  RgbsColor: TRgbsColor;
begin
  startx:=1;
  stopx:= 20;
  starty:=1;
  stopy:= Image1.Height-30;

  len:= (stopx-startx+1) * (stopy-starty+1);
  SetLength(rc, len);
  SetLength(gc, len);
  SetLength(bc, len);

  k:= 0;
  for i := 0 to (stopx-startx) do
    for j := 0 to (stopy-starty) do begin
      RgbsColor.Color := GetPixel(Image1.Canvas.Handle, i, j);
      rc[k]:= RgbsColor.RGBS.Red;
      bc[k]:= RgbsColor.RGBS.Blue;
      gc[k]:= RgbsColor.RGBS.Green;
      k:= k+1;
    end;

  try
    s:= 0;
    s2:= 0;
    s3:= 0;
    for i := Low(rc) to High(rc) do
      s:= s+ rc[i];
    Rav:= Round(s/Length(rc));
    for i := Low(gc) to High(gc) do
      s2:= s2+ gc[i];
    Gav:= Round(s2/Length(gc));
    for i := Low(bc) to High(bc) do
      s3:= s3+ bc[i];
    Bav:= Round(s3/Length(bc));
  except

  end;

  ShowMessage(IntToStr(Rav)+ ' '+ IntToStr(Gav)+' '+IntToStr(Bav));
end;

procedure TForm7.RandomDraw;
begin
  Image1.Canvas.Brush.Color:= RGB(Random(254), Random(254), Random(254));
  Image1.Canvas.Rectangle(0, 0, Round(Image1.Width), Round(Image1.Height/2));
  Image1.Canvas.Brush.Color:= RGB(Random(254), Random(254), Random(254));
  Image1.Canvas.Rectangle(0, Round(Image1.Height/2),
  Image1.Width, Image1.Height);
end;

end.

Автор: БелАмор 18.8.2010, 09:10
Ну вот, заикнулся об оптимизации, а сам такое напиасал...
Если обработка ограничивается тем, что приведено в исходном коде (в чём я лично сомневаюсь), то всё можно ещё упростить:
Код

unit Unit7;

interface

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

type
  TForm7 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    procedure SomeCounts;
    procedure RandomDraw;
  public
    { Public declarations }
  end;

  // Эти два типа взяты из статьи
  TRGBS = packed record
    Red, Green, Blue, System: Byte;
  end;

  TRgbsColor = record case Boolean of
    True : (Color: TColor);
    False: (RGBS : TRGBS );
  end;

var
  Form7: TForm7;

implementation

{$R *.dfm}

procedure TForm7.Button1Click(Sender: TObject);
begin
  SomeCounts;
end;

procedure TForm7.Button2Click(Sender: TObject);
begin
  RandomDraw;
end;

procedure TForm7.SomeCounts;
var
  len: integer;
  startx, stopx, starty, stopy: Integer;
  i, j: Integer;
  s, s2, s3: int64;
  Rav, Gav, Bav: Integer;
  RgbsColor: TRgbsColor;
begin
  startx:=1;
  stopx:= 20;
  starty:=1;
  stopy:= Image1.Height-30;

  len:= (stopx-startx+1) * (stopy-starty+1);

  s:= 0;
  s2:= 0;
  s3:= 0;
  for i := 0 to (stopx-startx) do
    for j := 0 to (stopy-starty) do begin
      RgbsColor.Color := GetPixel(Image1.Canvas.Handle, i, j);
      s:= s + RgbsColor.RGBS.Red;
      s2:= s2 + RgbsColor.RGBS.Green;
      s3:= s3 + RgbsColor.RGBS.Blue;
    end;

  Rav:= Round(s/len);
  Gav:= Round(s2/len);
  Bav:= Round(s3/len);

  ShowMessage(Format('%d %d %d', [Rav, Gav, Bav]));
end;

procedure TForm7.RandomDraw;
begin
  Image1.Canvas.Brush.Color:= RGB(Random(254), Random(254), Random(254));
  Image1.Canvas.Rectangle(0, 0, Round(Image1.Width), Round(Image1.Height/2));
  Image1.Canvas.Brush.Color:= RGB(Random(254), Random(254), Random(254));
  Image1.Canvas.Rectangle(0, Round(Image1.Height/2),
  Image1.Width, Image1.Height);
end;

end.

Автор: Racer 18.8.2010, 11:30
Спасибо огромное вам. сейчас попробую переделать

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)