Графические эффекты: линза

Реализация 1 — на Паскале.

Если линза на экpане — окpужность (x0,y0,r0), то в точках (x,y), для котоpых (x-x0)2+(y-y0)2<=r02,pисуется точка, котоpая, если бы линзы не было, изобpажалась бы в точке (x0+(x-x0)*k1,y0+(y-y0)*k), где k=const1 / ([sqrt]((x-x0)2+(y-y0)2) + const2). Можно заpанее пpосчитать таблицу смещений — array[-r0..r0,-r0..r0] of integer.

{$A+,B-,D+,E+,F-,G+,I+,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+,Y+} {$M 16384,0,655360} Uses CRT; Const vx0 = 3;       vy0 = 2;       v0  = vx0;       r0  = 50;       r02 = (r0-v0)*(r0-v0);       d   = r02 * 10 div 10; Type ScreenType = Array[0..199,0..319] of Byte;      DispType   = Array[-r0..r0,-r0..r0] of Integer; Var     Screen           : ScreenType Absolute $a000:$0000;     Buffer1, Buffer2 : ^ScreenType;     Disp             : ^DispType;     x,y,vx,vy,r2,c   : LongInt; Procedure Move(Var A,B; Count: Word); assembler; asm         push ds         mov  cx, Count         les  di, B         lds  si, A         shr  cx, 1         jz   @zero         rep  movsw @zero:  pop  ds end; BEGIN  asm   mov ax, $13   int $10  end;  New(Buffer1);  New(Buffer2);  New(Disp);  FillChar(Screen, SizeOf(Screen), 3);  y:=0;    repeat   For x:=0 to 319 do Screen[y,x]:=11;   Inc(y,10);  until y>199;  x:=0;  repeat   For y:=0 to 199 do Screen[y,x]:=11;   Inc(x,10);  until x>319;  Move(Screen, Buffer1^, SizeOf(Screen));  Move(Buffer1^,Screen,64000);  For y:=-r0 to r0 do  For x:=-r0 to r0 do   begin   r2:=x*x+y*y;   if r2>r02 then Disp^[y,x] := y*320+x    else    Disp^[y,x]:=(y*(r2+d)div(r02+d))*320+(x*(r2+d)div(r02+d));   end;  x:=r0;  y:=r0;  vx:=vx0;  vy:=vy0;  repeat   asm           mov     ax, Integer(y)           mov     bx, 320           imul    bx           add     ax, Integer(x)           mov     di, ax           mov     dx, -r0*320-r0           les     si, Disp           mov     ch, 2*r0+1 @next_dy: mov     cl, 2*r0+1 @next_dx:           mov     es, Word(Disp+2)           mov     bx, es:[si]           mov     es, Word(Buffer1+2)           mov     al, es:[di+bx]           mov     bx, Seg(Screen)           mov     es, bx           mov     bx, dx           mov     es:[di+bx], al           add     si, 2           inc     dx           dec     cl           jnz     @next_dx           add     dx, 320-(2*r0+1)           dec     ch           jnz     @next_dy   end;   if ((x+vx)>=r0)and ((x+vx)=r0)and ((y+vy)<=199-r0)then Inc(y,vy)                                        else vy:=-vy;   Delay(25);  until Port[$60]=$01;  Dispose(Buffer1);  Dispose(Buffer2);  Dispose(Disp);  asm   mov ax, $03   int $10  end; END. 

Реализация 2 - на Watcom C.

Пусть у нас есть матрица , которую нужно преобразовать. То есть у нас есть какой-то прямоугольный массив, который мы хотим показать в линзе. Итак у нас есть исходная матрица. Каждая пара координат в матрице (I,J) переходит в новую пару координат (X,Y). Формулу смотрите в исходнике. Тогда элемент матрицы с новыми координатами (X,Y) становиться равным смещению в матрице, которое соответствует координатам (I,J). Это первый этап, для дальнейшего ускорения вывода , расчитаем еще два массива. Один массив - это смещения по которому мы берем значение цвета точки. А второй массив - смещения по которым мы этот цвет будет ставить. Тогда весь вывод линзы сведеться к циклу, в котором мы берем точку по одному смещению , а ставим по другому.

#include  #include  #define PI      3.1415926 #define max     40 char bmp[64000]; char Scr[64000]; char p[1024]; int  matr[2*max][2*max]; int  glassnew[2*max][2*max]; int  glassold[2*max][2*max]; // Set Video Mode ################################################ extern void setvmode(int); #pragma aux setvmode = \   " int 10h " \   parm [eax] \   modify exact [eax]; // Wait Ret Race ################################################# void wait_retrace()  {   while ((inp(0x3DA) & 0x08) == 0);   while ((inp(0x3DA) & 0x08) != 0);  } // PutPixel ###################################################### void PutPixel(int x,int y,int Color)  {    if ((x>0)&&(y>0)&&(x<320)&&(y<200)) Scr[x+y*320]=Color;  } // GetPixel ###################################################### int GetPixel(int x,int y)  {    return(bmp[x+y*320]);  } void main(void)  {   FILE *f;   int i,j,xc,yc,c,yc1,xc1,foffset;   float s,x,y,a,b;   setvmode(0x13);   f=fopen("1.bmp", "rb");   fseek(f,1024+54,0);   fread(&bmp, 1, 64000, f);   fseek(f,54,0);   fread(&p, 1, 1024, f);   fclose(f);   // Готовим палитру   for(i=0;i> 2);     outp(0x3C9,p[(i*4)+1] >> 2);     outp(0x3C9,p[(i*4)+0] >> 2);    }    // Создаем таблицу переходов    for (i=-max;i//   wait_retrace();    memcpy((char*)0xA0000L, (char*)&Scr, 64000);    a=a+0.01;    b=b+0.01;   } while (!kbhit());   getch();   setvmode(0x03);  }  
Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: