Programadores => Código de la Semana => Mensaje iniciado por: ethernet en 11 de Noviembre de 2002, 12:10:19 pm

Título: Función de desenfoque
Publicado por: ethernet en 11 de Noviembre de 2002, 12:10:19 pm
Código: [Seleccionar]

void Superficie::Desenfoque()

{

int maxlinea,pixelsx,pixelsy,bypp,bpp,incxlinea,maxlinea2,contpixel;

unsigned char *dirw;

dirw=m_lpBuffer;

maxlinea=m_lPitch;

bypp=m_bypp;  

bpp=m_bpp;

pixelsx=m_Rect.Width()-2;

pixelsy=m_Rect.Height()-2;

_asm{

  mov eax,maxlinea

  mov esi,eax

  shl eax,1

  mov maxlinea2,eax

  mov eax,pixelsx

  imul bypp

  mov edx,esi

  sub edx,eax

  mov incxlinea,edx

  sub esi,bypp

  mov edi,dirw

  add edi,maxlinea

  add edi,bypp

  psrld mm7,32

linea:

  mov eax,pixelsx

  mov contpixel,eax

  cmp bpp,32

  jz linea32

  cmp bpp,24

  jz linea24

  cmp bpp,16

  jz linea16

linea15:

  sub esi,maxlinea2

  mov ax,word ptr [edi+esi]

  mov bx,word ptr [edi+esi+2]

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,3

  shr ecx,3

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,3

  shr ecx,3

  shrd edx,eax,13

  shrd ecx,ebx,13

  movd mm0,edx

  punpcklbw mm0,mm7

  movd mm1,ecx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  mov ax,word ptr [edi+esi+4]

  add esi,maxlinea

  mov bx,word ptr [edi+esi]

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,3

  shr ecx,3

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,3

  shr ecx,3

  shrd edx,eax,13

  shrd ecx,ebx,13

  movd mm1,edx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,ecx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  mov ax,word ptr [edi+esi+2]

  mov bx,word ptr [edi+esi+4]

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,3

  shr ecx,3

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,3

  shr ecx,3

  shrd edx,eax,13

  shrd ecx,ebx,13

  movd mm1,edx

  punpcklbw mm1,mm7

  psllw mm1,3

  paddw mm0,mm1

  movd mm1,ecx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  add esi,maxlinea

  mov ax,word ptr [edi+esi]

  mov bx,word ptr [edi+esi+2]

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,3

  shr ecx,3

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,3

  shr ecx,3

  shrd edx,eax,13

  shrd ecx,ebx,13

  movd mm1,edx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,ecx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  mov ax,word ptr [edi+esi+4]

  shrd edx,eax,5

  shr eax,5

  shr edx,3

  shrd edx,eax,5

  shr eax,5

  shr edx,3

  shrd edx,eax,13

  movd mm1,edx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  psrlw mm0,4

  packuswb mm0,mm0

  movd eax,mm0

  shr eax,3

  shrd edx,eax,5

  shr eax,8

  shrd edx,eax,5

  shr eax,8

  shrd edx,eax,22

  mov word ptr [edi],dx

  add edi,2

  dec contpixel

  jnz linea15

  mov eax,pixelsx

  mov contpixel,eax

  add edi,incxlinea

  dec pixelsy

  jnz linea15

  jmp final

linea16:

  sub esi,maxlinea2

  mov ax,word ptr [edi+esi]

  mov bx,word ptr [edi+esi+2]

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,2

  shr ecx,2

  shrd edx,eax,6

  shrd ecx,ebx,6

  shr eax,6

  shr ebx,6

  shr edx,3

  shr ecx,3

  shrd edx,eax,13

  shrd ecx,ebx,13

  movd mm0,edx

  punpcklbw mm0,mm7

  movd mm1,ecx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  mov ax,word ptr [edi+esi+4]

  add esi,maxlinea

  mov bx,word ptr [edi+esi]

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,2

  shr ecx,2

  shrd edx,eax,6

  shrd ecx,ebx,6

  shr eax,6

  shr ebx,6

  shr edx,3

  shr ecx,3

  shrd edx,eax,13

  shrd ecx,ebx,13

  movd mm1,edx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,ecx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  mov ax,word ptr [edi+esi+2]

  mov bx,word ptr [edi+esi+4]

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,2

  shr ecx,2

  shrd edx,eax,6

  shrd ecx,ebx,6

  shr eax,6

  shr ebx,6

  shr edx,3

  shr ecx,3

  shrd edx,eax,13

  shrd ecx,ebx,13

  movd mm1,edx

  punpcklbw mm1,mm7

  psllw mm1,3

  paddw mm0,mm1

  movd mm1,ecx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  add esi,maxlinea

  mov ax,word ptr [edi+esi]

  mov bx,word ptr [edi+esi+2]

  shrd edx,eax,5

  shrd ecx,ebx,5

  shr eax,5

  shr ebx,5

  shr edx,2

  shr ecx,2

  shrd edx,eax,6

  shrd ecx,ebx,6

  shr eax,6

  shr ebx,6

  shr edx,3

  shr ecx,3

  shrd edx,eax,13

  shrd ecx,ebx,13

  movd mm1,edx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,ecx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  mov ax,word ptr [edi+esi+4]

  shrd edx,eax,5

  shr eax,5

  shr edx,2

  shrd edx,eax,6

  shr eax,6

  shr edx,3

  shrd edx,eax,13

  movd mm1,edx

  punpcklbw mm1,mm7

  paddw mm0,mm1

  psrlw mm0,4

  packuswb mm0,mm0

  movd eax,mm0

  shr eax,3

  shrd edx,eax,5

  shr eax,7

  shrd edx,eax,6

  shr eax,9

  shrd edx,eax,21

  mov word ptr [edi],dx

  add edi,2

  dec contpixel

  jnz linea16

  mov eax,pixelsx

  mov contpixel,eax

  add edi,incxlinea

  dec pixelsy

  jnz linea16

  jmp final

linea24:

  sub esi,maxlinea2

  movd mm0,dword ptr [edi+esi]

  punpcklbw mm0,mm7

  movd mm1,dword ptr [edi+esi+3]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+6]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  add esi,maxlinea

  movd mm1,dword ptr [edi+esi]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+3]

  punpcklbw mm1,mm7

  psllw mm1,3

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+6]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  add esi,maxlinea

  movd mm1,dword ptr [edi+esi]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+3]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+6]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  psrlw mm0,4

  packuswb mm0,mm0

  movd eax,mm0

  mov word ptr [edi],ax

  shr eax,16

  mov byte ptr [edi+2],al

  add edi,3

  dec contpixel

  jnz linea24

  mov eax,pixelsx

  mov contpixel,eax

  add edi,incxlinea

  dec pixelsy

  jnz linea24

  jmp final

linea32:

  sub esi,maxlinea2

  movd mm0,dword ptr [edi+esi]

  punpcklbw mm0,mm7

  movd mm1,dword ptr [edi+esi+4]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+8]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  add esi,maxlinea

  movd mm1,dword ptr [edi+esi]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+4]

  punpcklbw mm1,mm7

  psllw mm1,3

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+8]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  add esi,maxlinea

  movd mm1,dword ptr [edi+esi]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+4]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  movd mm1,dword ptr [edi+esi+8]

  punpcklbw mm1,mm7

  paddw mm0,mm1

  psrlw mm0,4

  packuswb mm0,mm0

  movd dword ptr [edi],mm0

  add edi,4

  dec contpixel

  jnz linea32

  mov eax,pixelsx

  mov contpixel,eax

  add edi,incxlinea

  dec pixelsy

  jnz linea32

final:

  emms

}

}



Título: Función de desenfoque
Publicado por: synchrnzr en 12 de Noviembre de 2002, 06:53:48 pm
                                Ola! Como nadie pone nada, lo pongo yo :D

Notad que el filtrado es anisotrópico (para los no iniciados, quiere decir que no filtra igual en todas las direcciones ;))

Sync                                
Título: Función de desenfoque
Publicado por: fiero en 12 de Noviembre de 2002, 08:17:42 pm
                                vaya churro!
He de decir que aunque parezca un lio de instrucciones es bastante facil, solo fijaros en la parte de 32 o 24 bits. Lo que lía la cosa son los bucles de 16 y 15 bits, ya que hay que pasar los colores a 32 bits para descomponer los valores RGB he ir sumandolos en los registros mmx.

No me habia parado a pensar en eso de "anisotropias"  :ojo: , de todas formas hacerlo de derecha a izquierda o de abajo a arriba no seria muy perceptible a nuestros cansados ojos no sync?

un saludo                                
Título: Función de desenfoque
Publicado por: fiero en 12 de Noviembre de 2002, 08:22:22 pm
                                bueno, no puedo editar, así que escribo otro....

[synchrnzr]
Se me ocurre que para que fuese un filtro perfecto habria que usar diferentes imagenes de entrada y salida no? para no ir machacando los colores...                                
Título: Función de desenfoque
Publicado por: ethernet en 13 de Noviembre de 2002, 12:07:00 pm
No he mirado demasiado el codigo (mode flame ON) el codigo ensamblador me produce nauseas. Creo q en c /c++ hubiera estado mejor por 2 cosas. Mas claridad, mas rapidez (estaria por jugarme el cuello) . De q sirve tener un codgo muy bueno si despues nadie lo puede entender o es dificil su lectura?.
Por otro lado es el tipico caso de filtro. Supongo q habras usado una convolucion para obtener el resultado. Se puede demostrar q es mucho mas eficiente cara al numero de operaciones q  es mucho mejor hacerlo con FFT's. Moraleja: trata de optimizar los algoritmos y no tu codigo.
(mode flame OFF)
saludos. si tengo algun tiempo tratare de descifrarlo :))
Título: Función de desenfoque
Publicado por: synchrnzr en 13 de Noviembre de 2002, 12:26:09 pm
                                Este filtrado convolutivo no filtra igual las direcciones horizontales o verticales que las diagonales, aunque es lo más utilizado en la demoscene para efectos de soften y desenfoque ;)

Pos no sé qué formas hay de hacer un filtrado isotrópico, yo sólo sé hacer filtrados isotrópicos a partir de la transformada de Fourier de la imagen que es lo que me enseñaron en la asignatura de proceso de imágenes:

[abstenerse no iniciados :I]

La idea es hacer una convolución con una imagen cuyo espectro sea una función gaussiana del mismo tamaño que la imagen. La FFT se aplica en este proceso porque acelera mucho los cálculos (una convolución en el domino espacial es una simple multiplicación en el domino frecuencial) aunque para aplicar la FFT necesitamos que la imagen tenga unas dimensiones concretas (imagen cuadrada, potencia de 2...)

La metodología sería:

a) Tenemos una imagen nxm
B) La convertimos en una imagen qxq (q es un número potencia de 2) y la pasamos a una imagen de complejos para poder aplicar la FFT
c) Hacemos la FFT de la imagen
d) Generamos el espectro de una gaussiana (es más fácil y rápido generar el espectro directamente)
e) Multiplicamos ambos espectros
f) Antitransformamos la imagen resultante
g) Devolvemos a la imagen resultante la profundidad de bits que corresponde (después de la convolución, los valores de cada pixel habran aumentado una burrada)

Cuando hablo de espectro me refiero al módulo de la imagen compleja, supongo que se da por supuesto ;)

Sync

PD: Por cierto, aunque parezca muy complicado y rebuscado, se puede hacer a tiempo real con un coste parecido al del otro método gracias a la FFT

PPD: Más info sobre el tema en www.cvc.uab.es :X9:                                
Título: Función de desenfoque
Publicado por: Loover en 13 de Noviembre de 2002, 12:50:28 pm
                                ¿Tiempo real? Mola. ¿Puedes postear un código que use ese método? Quizás para la semana que viene, :D                                
Título: Función de desenfoque
Publicado por: fiero en 13 de Noviembre de 2002, 12:57:58 pm
                                [ethernet]
La verdad es que tengo la manía de hacer los bucles muy repetitivos en ensamblador, aunque sé que en muchos casos no merece la pena...
Sin embargo en este caso hacerlo en C sería improductivo. No se me ocurre ninguna forma más rápida de sumar dos colores RGB que esta:
Código: [Seleccionar]

      movd mm0,dword ptr [edi+esi]     //Primer color en mm0=00000RGB

      punpcklbw mm0,mm7                  //Desempaquetado de los componentes (de bytes a words)  mm0=000R0G0B

      movd mm1,dword ptr [edi+esi+4] //Segundo color en mm1=00000RGB

      punpcklbw mm1,mm7                 //Desempaquetado de los componentes (de bytes a words) mm1=000R0G0B

      paddw mm0,mm1                       //Suma de los componentes en words



//Después de la suma:



      psrlw mm0,1                              //Se dividen el resultado entre 2

      packuswb mm0,mm0                  //Se empaquetan los componentes (de words a bytes) mm0= 0RGB0RGB

      movd dword ptr [edi],mm0         //Se almacena el color de 32 bits





Si se haria el código en C no se sumarian las 3 componentes a la vez en una misma instrucción, ya que los compiladores no suelen meter mmx (de esto no estoy muy seguro)


[synchrnzr]
En cuanto a lo de usar FFT, no tengo ni idea de hacer filtros así  :oops: , aunque bueno es saberlo... :ojo:

saludos                                
Título: Función de desenfoque
Publicado por: synchrnzr en 13 de Noviembre de 2002, 01:33:44 pm
                                Loover: lo único que tengo es en ViLi, una especie de versión visual del Lisp desarrollado en el propio CVC. Además no es muy didáctico porque lo que es hacer la FFT ya está implementado en el propio lenguaje. En C supongo que sabría hacerlo, pero la verdad es que no me he puesto nunca porque me dedico más a cosillas de sonido :loco:

En cualquier caso no creo que sea el código de la semana que viene pero a lo mejor algun dia de estos me animo y envio algo sobre sonido, si tengo tiempo :)

Sync                                
Título: Función de desenfoque
Publicado por: ethernet en 14 de Noviembre de 2002, 10:22:30 am
Quizas eso q comentas de sumar dos colores sea lo mas rapido. Yo no digo q no se use asm, por ejemplo para ese caso es util, pero el resto del codigo en c estoy casi seguro q el compilador lo haria mas optimo. Para muestra, un boton :) -> http://www.codepixel.com/modules.php?op=mo...ewthread&tid=53

saludos
Título: Función de desenfoque
Publicado por: fiero en 14 de Noviembre de 2002, 11:03:33 am
                                Examinando ese código de codepixel me parecía muy raro que ganara C. Estos con los resultados que he obtenido yo con ese mismo código:

time_c++: 1.121921
time_asm: 0.106562

(compilado con VC6)

Por cierto, he leido algo sobre el memcpy() en ese mismo hilo. Esa función de microsoft está integramente realizada en asm, hay un fichero por el visual studio llamado memcpy.c en el que está tol cotarro...

Lo que me resulta extraño son tus tiempos ethernet  :-?

un saludo

PD: ethernet, una vez dijiste que con el compilador de intel te salia un botoncito en la barra del VC, ¿como se hace para que salga?                                
Título: Función de desenfoque
Publicado por: ethernet en 14 de Noviembre de 2002, 11:38:02 am
Juro por dios q me daba esos tiempos, ademas lo probe un monton de veces cambiando la memoria el tamaño y demas. Por cierto, con intel me daba mas lento q con vc++.

fiero: no es un boton. En project->settings->c/c++-> preprocesor definitions pones: USE_INTEL_COMPILER (creo q es eso, en la ayuda delcompilador te pone lo q debes poner)
Título: Función de desenfoque
Publicado por: MChiz en 14 de Noviembre de 2002, 12:30:48 pm
                                Hola!
He probado el codigo de codepixel y en Debug me va mas lento el codigo en C ( casi que es normal :b )
En release obtengo estos resultados:

time_c++: 0.062924
time_asm: 0.099366

Parece mentira!!
Un saludo!                                
Título: Función de desenfoque
Publicado por: fiero en 14 de Noviembre de 2002, 01:33:47 pm
                                ups, error mio, lo estaba probando en modo debug. En modo release:

time_c++: 0.073878
time_asm: 0.158920

 :o  realmente increible!!!

voy a destriparlo a ver lo que hace el compilador con ese bucle for.....

un saludo                                
Título: Función de desenfoque
Publicado por: Lord Trancos en 14 de Noviembre de 2002, 03:24:08 pm
                                poned el codigo en C pa q los q no controlamos asm le echemos un vistazo :)                                
Título: Función de desenfoque
Publicado por: Lord Trancos en 14 de Noviembre de 2002, 05:35:57 pm
                               
Citar

es que... si se pone en C, ya no se usa mmx  :)


¬_¬;

mejor, no? es mas rapido y no es necesario MMX :P                                
Título: Función de desenfoque
Publicado por: seryu en 14 de Noviembre de 2002, 06:04:24 pm
                                Dos cosas, como yo vengo diciendo de hace mucho tiempo, hay qe ser un pro para poder codificar en asm mejor qe un compilador actual.

Y lo otro, cuando tais en esas opciones tan horrorosas del vc podreis ver cosas como generar codigo optimizado para X para Y etc.. al activar eso el compilador utilizara instrucciones mmx sse o lo qe sea.

Si ta claro, C se hizo para no codificar en ASM, xqe volver a pegarse con lo mismo?                                
Título: Función de desenfoque
Publicado por: ethernet en 14 de Noviembre de 2002, 06:14:53 pm
Fiero -> compilar en debug no tiene perdon xDDD

En c SI se puede usar mmx en las partes q se necesiten.
el vc++7.0 optimiza para mmx y otro tipo de tecnologias similares ?
Título: Compilador más rápido que asm a mano
Publicado por: barkley en 20 de Noviembre de 2002, 03:51:16 pm
                                Hola,

he estado leyendo las "discusiones" acerca de qué es mejor si C/C++ o ensamblador embebido. Personalmente, dudo mucho que se pueda mejorar la eficiencia de un código compilado con un ensamblador decente (en modo de máxima optimización, claro, -o3 en la mayoría de compiladores). Además, la ganancia en claridad y portabilidad del código es muy grande. Yo ni he intentado leer el código en ensamblador puro que habías puesto arriba, demasiado complejo para mí (paso de mirarme las instrucciones MMX y SSE2 que creo que utilizas)  :) .
Así que me sumo a los de la opinión que el código en C compilado es más rápido que en ensamblador. Además, por otro lado, es lógico. Los compiladores se hacen específicamente por gente bastante inteligente y documentada. Planean desenrollados y desordenados de código mirando dependencias, etc. Eso, además de ser muy costoso hacerlo a mano (a mí me lo van a decir que me lo piden para el jodido examen de febrero) es muy fácil que, debido a los bloques de paso de parámetros, etc. no podamos optimizarlo tanto como el compilador. Así que nada, me sumo al grupo de los que se ponen en modo Flame OFF. Saludos,

Barkley