Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Слайд шоу


Автор: Алексей 20.2.2008, 10:58
Нужно сделать слайд шоу, чтобы новая картинка замещала старую за счет случайного заполнения пикселей.
Проблема в том, что картинка заполняется не полностью. Все мои попытки это исправить привели лишь к зацикливанию.
Заранее спасибо.
Код

procedure TForm1.FormCreate(Sender: TObject);
var i:byte;
begin
   timer1.Enabled:=false;
   for i:=1 to 4 do
     begin
        Bm[i]:=TBitmap.Create;
        if OpenPictureDialog1.Execute then
        BM[i].LoadFromFile(OpenPictureDialog1.FileName);
     end;

end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  randomize;
   p:=1+random(4);
   rand;
end;

procedure TForm1.rand;
    var i,j,k,n:integer;
    begin
      k:=0;
      n:=form1.Width*form1.Height;
        for k:=1 to n do
           begin
                  randomize;
                  i:=random(form1.ClientWidth);
                  j:=random(form1.ClientHeight);
                  if form1.Canvas.Pixels[i,j]<> BM[p].Canvas.Pixels[i,j] then
                       form1.Canvas.Pixels[i,j]:=BM[p].Canvas.Pixels[i,j]
          end;    
  end;


Автор: Alexeis 20.2.2008, 12:31
Просто случайный Random будет закрашивать нереально долго, потому что будет очень много совпадений. При повторном выборе пикселя, нужно брать соседний, а если он уже выбран, то продолжать двигаться, пока не будет найден тот который еще не брали. 

Автор: Алексей 20.2.2008, 16:25
А, если не трудно, можно поподробней.  smile 

Автор: lukas 20.2.2008, 18:03
есть еще вариант, сгенирировать заранее список координат пикселей... естественно в случайном порядке, а потом просто по нему пройтись.... список без повторений генерить очень легко.... для этого нужна 2 списка... 1 - с всевозможными вариантами, а второй пустой,.. Далее просто генерим случайный индекс из 1ого списка, и переводим элемент этого индекса во 2ой список, а из 1ого удаляем.... и так до тех пор, пока в первом списке ничего не останется...

Автор: Alexeis 20.2.2008, 18:28
Цитата(lukas @  20.2.2008,  17:03 Найти цитируемый пост)
есть еще вариант, сгенирировать заранее список координат пикселей... естественно в случайном порядке, а потом просто по нему пройтись.... список без повторений генерить очень легко.... для этого нужна 2 списка... 1 - с всевозможными вариантами, а второй пустой,.. Далее просто генерим случайный индекс из 1ого списка, и переводим элемент этого индекса во 2ой список, а из 1ого удаляем.... и так до тех пор, пока в первом списке ничего не останется... 

  Заранее неизвестен ни размер экрана, ни размер картинки, потому не катит smile .

Автор: lukas 20.2.2008, 19:45
Alexeis, 

а причем тут заранее... мы же эти операции будем производить не заранее...  

Автор: Alexeis 20.2.2008, 20:21
Цитата(lukas @  20.2.2008,  18:45 Найти цитируемый пост)
мы же эти операции будем производить не заранее...  

Цитата(lukas @  20.2.2008,  17:03 Найти цитируемый пост)
есть еще вариант, сгенирировать заранее список координат пикселей...

  Так определись заранее или не заранее. 

Автор: bems 20.2.2008, 20:28
Цитата(Alexeis @  20.2.2008,  12:31 Найти цитируемый пост)
При повторном выборе пикселя, нужно брать соседний, а если он уже выбран, то продолжать двигаться, пока не будет найден тот который еще не брали.  

или если совпадение то увеличить размер области, переносимой за один раз. Типа сначала красим не пиксели, а круги еденичного диаметра. Если центр округа попал в уже перенесенную точку, то увеличиваем диаметр круга в Х раз. Этот Х подбираем методом тыка или вычисляем из площади битмапа.

Автор: Алексей 21.2.2008, 16:34
Не могли бы вы чуть чуть набросать свои вариантыsmile Что-то я не совсем понимаю  smile 

Автор: lukas 21.2.2008, 17:39
Alexeis, 

сорри.... я не то имел ввиду...  smile ... 

ну вот например:


Код

procedure RandomList(LS: TStrings): TStringList;
  Var
  I,Len,Id: Integer;
begin
Result := TStringList.Create;
 Len := LS.Count; 
   for i:=0 to Len - 1 do
     begin
          Id := Random(LS.Count);
          Result.Add(LS[Id]);
          LS.Delete(Id);
     end;
end;

Автор: bems 21.2.2008, 18:36
вот пример с простым закрашиванием. Чтобы переделать на смену картинки нужно сравнения canvas.Pixels[x,y]=clRed переделать в проверку перенесена ли уже точка, и написать перенос окружности с битмапа на битмап. Хотя наверное можно заменить на квадрат

Код

procedure TForm1.BitBtn1Click(Sender: TObject);
var n,m,MaxM:integer;rct:TRect;x,y,id:integer;d:real;refr:integer;
begin
with img.Picture.Bitmap do
 begin
 d:=2;
 MaxM:=5;
 refr:=((width+height) div 2);
 canvas.Brush.Color:=clRed;
 canvas.Pen.Color:=clRed;
 for n:=1 to Width*Height do //заменить на проверку остались ли неперенесенные точки
  begin
  m:=0;
  repeat
   x:=random(Width);
   y:=random(Height);
   inc(m);
  until (canvas.Pixels[x,y]<>clRed) or (m>=MaxM);
  if (m=MaxM) and (canvas.Pixels[x,y]=clRed) then dec(MaxM);
  id:=round(d*1.5);
  if canvas.Pixels[x,y]=clRed then inc(x,id);
  if canvas.Pixels[x,y]=clRed then dec(y,id);
  if canvas.Pixels[x,y]=clRed then dec(x,id);
  if canvas.Pixels[x,y]=clRed then dec(x,id);
  if canvas.Pixels[x,y]=clRed then inc(y,id);
  if canvas.Pixels[x,y]=clRed then inc(y,id);
  if canvas.Pixels[x,y]=clRed then inc(x,id);
  if canvas.Pixels[x,y]=clRed then inc(x,id);
  if canvas.Pixels[x,y]=clRed then d:=d*2;
  rct.Left:=round(x-d/2);
  rct.Top:=round(y-d/2);
  rct.Right:=round(x+d/2);
  rct.Bottom:=round(y+d/2);
  canvas.Ellipse(rct);
  if n mod refr=0 then img.Refresh;
  end;
 end;
end;


img это TImage.

Автор: Алексей 22.2.2008, 00:41
bems, когда запускаю пишет ошибку.

Код

Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 0044DA70 in module 'Project1.exe'. 
Read of address 00000168'. Process stoped. Use Step or Run to continue.

Автор: bems 22.2.2008, 14:38
поставь размеры img.picture.bitmap и введи критерий "перенесена вся картинка". 

Автор: diamondd 1.3.2008, 00:17
может так?

Код

procedure TForm1.Rand;
var
  //объявляешь массив из точек
  ar: array of TPoint;
  Temp: TPoint;
  i,N,T: Integer;
begin
  //считаешь необходимое кол-во точек
  N:=Form1.Width*Form1.Height;
  //устанавливаешь длину массива
  SetLength(ar,N);
  //заполняешь массив всеми точками
  //от (0,0) до (Form1.Width-1,Form1.Height-1)
  for i:=0 to (N-1) do
    ar[i]:=Point(i mod Form1.Width,i div Form1.Width);
  Randomize;
  //далее просто каждую точку из массива
  //меняешь местами со случайной
  for i:=0 to (N-1) do
    begin
    T:=Random(N);
    Temp:=ar[i];
    ar[i]:=ar[T];
    ar[T]:=Temp
    end;
  //в результате получается массив со всеми точками в случайном порядке
  //а затем меняешь их местами как хочешь :)
end;

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