180 likes | 336 Views
PROGRAMACIO DE FUNCIONS VILI EN C. 1. Nivells de programació en ViLi 2. Funcions C de processament d’imatges tipus d’imatge atributs i funcions d’acces operacions de creació i eliminació d’imatges apuntadors, funcions pel recorregut, “ switch(ImType(ima)) ”
E N D
PROGRAMACIO DE FUNCIONS VILI EN C • 1. Nivells de programació en ViLi • 2. Funcions C de processament d’imatges • tipus d’imatge • atributs i funcions d’acces • operacions de creació i eliminació d’imatges • apuntadors, funcions pel recorregut, “switch(ImType(ima))” • excepcions : Raise(<missatge error>) • 3. Exemples : thr.c , sample2.c • 4. Funció C d’interficie • obtenció d’arguments Lisp : xlga<type>() , xllastarg() , moreargs() • desencapsulament : get<type>() • encapsulament : cv<type conversion>() • 5. Exemples : xthr.c , xsample2.c • 6. Integració de la nova funció • fitxers d’include usrfdef.h, usrflib.h, usrftab.h • makefile
1. Nivells de programació en ViLi Interpret de Lisp Nivell imatge nodes Lisp simbols Lisp taula de funcions de l’interpret Interficie Lisp C funció en C d’interficie arguments C • funcions C : • imlib.dll • (loadlibrary “... .dll”) Nivell pixel
2. Funcions C de processament d’imatges 2.1 Tipus d’imatges : include\image.h typedef struct Image { char *Ident; /* image identifier */ int Type; /* image type IMA_BYTE IMA_SHORT IMA_LONG IMA_FLOAT IMA_COMPLEX */ int NCol; /* number of columns */ int NLin; /* number of lines */ int NPlanes; /* number of planes 1=2d image, >1 3d image */ int NChannels; /* number of channels ex: colour image (RGB) = 3 */ int GridType; /* GRID_RECT, GRID_HEX */ void *Data; /* image data */ } *Image; /* image types */ #define IM_BYTE 1 #define IM_SHORT 2 #define IM_LONG 3 #define IM_FLOAT 4 #define IM_COMPLEX 5 /* grid types */ #define GRID_RECT 1 #define GRID_HEX 2 /* Tipo byte */ typedef unsigned char Byte; /* Tipo complejo */ typedef struct Complex { float Re,Im; /* parte real y parte imaginaria */ } Complex;
2. Funcions C de processament d’imatges 2.2 Atributs i funcions d’acces : include\image.h #define ImIdent(Im) ((Im)->Ident) #define ImType(Im) ((Im)->Type) #define ImNLin(Im) ((Im)->NLin) #define ImNCol(Im) ((Im)->NCol) #define ImNPlanes(Im) ((Im)->NPlanes) #define ImNChannels(Im) ((Im)->NChannels) #define ImGridType(Im) ((Im)->GridType) /* Dimensiones en Pixels de la imagen */ #define DimImage(Im) ((Im)->NChannels*(Im)->NPlanes*(Im)->NLin*(Im)->NCol) #define DimChannel(Im) ((Im)->NPlanes*(Im)->NLin*(Im)->NCol) #define DimPlane(Im) ((Im)->NLin*(Im)->NCol) #define DimLine(Im) ((Im)->NCol) 2.3 Operacions de creació i eliminació d’imatges extern Image NewImage ARGS((char *Ident,int Type,int NCol, int NLin, int NPlanes,int NChannels,int GridType)); extern void DelImage ARGS((Image)); #define NewTypeIm(IM,Ident) NewImage((Ident), \ (IM)->Type, \ (int) (IM)->NCol,(int) (IM)->NLin,(int) (IM)->NPlanes, \ (int) (IM)->NChannels,(IM)->GridType) extern void ImRename ARGS((Image,char *)); extern void SetImToVal ARGS((Image,double)); extern Image ImCpy ARGS((Image));
2. Funcions C de processament d’imatges 2.4 Apuntadors, funcions pel recorregut , “switch(ImType(ima))” Image Out; register Byte *pOut; : : Out = NewImage(”Resultat",IM_BYTE, ncol, nlin, npla, ncha, GRID_RECT); pout = ImageB(Out); for (y=0 ; y<nlin ; y++) { for (x=0 ; x<ncol ; x++) { *pout = .... pout ++; } } • les funcions ImageB, ImageS, ImageL, ImageF, ImageC retornen respectivament • l’adreça del primer pixel d’una imatge d’un byte, short, long, float, complex per pixel. • els apuntadors de recorregut es declaran register per intentar que el compilador es assigni • als registres de la CPU • depenent del tipus d’imatge a generar/recorrer, el proces es el mateix pero el tipus dels • apuntadors no. Ho distingim fer un “switch(ImType(ima))” (veure exemples).
2. Funcions C de processament d’imatges • Quan es detecta un error per qualsevol causa, voldrem imprimir un missatge d’explicació • i retornar a l’interpret Lisp, no pas sortir del ViLi. • Ho fem cridant la funció de gestió d’exceptions ViLi, Raise(“Missatge d’error\n”);
3. Exemples : thr( ) Image thr(In, Umbral, Dentro, Fuera) Image In; double Umbral, Dentro, Fuera; { Image Out; register int NPix; NPix=DimImage(In); Out=NewTypeIm(In,"Thr"); switch (ImType(In)) { case IM_BYTE: { register Byte *PIn, *POut; register Byte u,d,f; u=Umbral; d= Dentro; f= Fuera; for (PIn=ImageB(In), POut=ImageB(Out); NPix>0; --NPix) if (*PIn++ >= u) *POut++ = d; else *POut++ = f; break; } case IM_SHORT: { register short *PIn, *POut; register short u,d,f; u=Umbral; d= Dentro; f= Fuera; for (PIn=ImageS(In), POut=ImageS(Out); NPix>0; --NPix) if (*PIn++ >= u) *POut++ = d; else *POut++ = f; break; }
case IM_LONG: { register long *PIn, *POut; register long u,d,f; u=Umbral; d= Dentro; f= Fuera; for (PIn=ImageL(In), POut=ImageL(Out); NPix>0; --NPix) if (*PIn++ >= u) *POut++ = d; else *POut++ = f; break; } case IM_FLOAT: { register float *PIn, *POut; register float u,d,f; u=Umbral; d= Dentro; f= Fuera; for (PIn=ImageF(In), POut=ImageF(Out); NPix>0; --NPix) if (*PIn++ >= u) *POut++ = d; else *POut++ = f; break; } default: DelImage(Out); Raise(ErrTypeIm); } /* switch */ return Out; } /* thr */
3. Exemples : sample2( ) /* Funcio que mostreja una imatge seleccionant punts cada un cert pas. Parametres : - Imatge d'entrada - pas per columna, fila, pla i canal Retorna una imatge del mateix tipus que la d'entrada, mostrejada. Errors : algun dels passos es menor que 1 */ Image sample2(In, stepcol, steprow, steppla, stepcha) Image In; int stepcol, steprow, steppla, stepcha ; { Image Out; int filinp, colinp, plainp, chainp ; int filout, colout, plaout, chaout ; register short fil, col, pla, cha ; /* per recorrer la imatge In */ /* controls sobre els parametres */ if ((steprow < 1) || (stepcol < 1) || (steppla < 1) || (stepcha < 1)) Raise(”Sample2 : step less than 1\n") ;
3. Exemples : sample2( ) /* nombre de files, columnes, plans i canals de la imatge d'entrada */ filinp = ImNLin(In); colinp = ImNCol(In); plainp = ImNPlanes(In); chainp = ImNChannels(In); /* nombre de files, columnes, plans i canals de la imatge de sortida */ filout = ceil( (float) filinp / steprow ) ; colout = ceil( (float) colinp / stepcol ) ; plaout = ceil( (float) plainp / steppla ) ; chaout = ceil( (float) chainp / stepcha ) ; /* creem la imatge de sortida */ Out = NewImage("Sample",ImType(In), colout, filout, plaout, chaout, GRID_RECT); switch (ImType(In)) { case IM_BYTE: { register Byte *pin, *pout; pin = ImageB(In) ; pout = ImageB(Out) ; for (cha = 0 ; cha < chainp ; cha += stepcha) for (pla = 0 ; pla < plainp ; pla += steppla) for (fil = 0 ; fil < filinp ; fil += steprow) { pin = LineB(In, fil, pla, cha) ; for (col = 0 ; col < colinp ; col += stepcol, pin += stepcol, pout++) *pout = *pin ; } break; }
3. Exemples : sample2( ) case IM_SHORT: { register short *pin, *pout; pin = ImageS(In); pout = ImageS(Out); for (cha = 0 ; cha < chainp ; cha += stepcha) for (pla = 0 ; pla < plainp ; pla += steppla) for (fil = 0 ; fil < filinp ; fil += steprow) { pin = LineS(In, fil, pla, cha) ; for (col = 0 ; col < colinp ; col += stepcol, pin += stepcol, pout++) *pout = *pin ; } break; } case IM_LONG: { register long *pin, *pout; pin = ImageL(In); pout = ImageL(Out); for (cha = 0 ; cha < chainp ; cha += stepcha) for (pla = 0 ; pla < plainp ; pla += steppla) for (fil = 0 ; fil < filinp ; fil += steprow) { pin = LineL(In, fil, pla, cha) ; for (col = 0 ; col < colinp ; col += stepcol, pin += stepcol, pout++) *pout = *pin ; } break; }
3. Exemples : sample2( ) case IM_FLOAT: { register float *pin, *pout ; pin = ImageF(In); pout = ImageF(Out); for (cha = 0 ; cha < chainp ; cha += stepcha) for (pla = 0 ; pla < plainp ; pla += steppla) for (fil = 0 ; fil < filinp ; fil += steprow) { pin = LineF(In, fil, pla, cha) ; for (col = 0 ; col < colinp ; col += stepcol, pin += stepcol, pout++) *pout = *pin ; } break; } default: DelImage(Out); Raise(ErrTypeIm); } /* switch */ return Out; } /* sample2 */
4. Funció C d’interficie Què fa la funció d’interficie ? 1. Protegeix els arguments en front al mecanisme d’alliberament de memoria del Lisp 2. Obté i verifica el tipus dels arguments passats a la funció de l’interpret 3. Verificar el número de argumentos 4. Desencapsula els arguments (transforma de Lisp a C) 5. Crida la funció de processament en C 6. Encapsula el resultat (en fa un node Lisp) 7. Desprotegeix els arguments protegits abans 8. Retorna el resultat xlsave1(LVAL) xlga<tipus>() getArgument() xllastarg() : si n’hi ha més, error moreargs() : n’hi ha més encara ? get<tipus>(LVAL) <variable C> = sample2(...) cv<tipus>(<variable C>) xlpop(), xlpopn(m) m nombre d’arguments protegits return LVAL
4. Funció C d’interficie • Funcions per obtenir i verificar arguments • Lisp de diferents tipus : • xlgacons() • xlgalist() • xlgasymbol() • xlgastring() • xlgaobject() • xlgafixnum() • xlgaflonum() • xlganum() • xlgachar() • xlgavector() • xlgastream() • xlgaustream() • xlgastruct() • xlgaclosure() • xlgaimage() • Funcions de desencapsulament • getfixnum(x) • getflonum(x) • getchcode(x) • getnum() • getstring(x) • getfile(x) • getImage(x) sencers flotants sencers o flotants • Funcions d’encapsulament • LVAL cvsymbol(char*); • LVAL cvstring(char*); • LVAL cvfile(FILE*); • LVAL cvfixnum(int); • LVAL cvflonum(double); • LVAL cvchar(char); • LVAL cvImageNode(Image);
5. Exemples : xthr( ) /* Interficie de xthr. Format: (thr <Image> <umbral> [<Dentro> <Fuera>]) */ LVAL xthr() { LVAL Out,Arg; double Umbral, Dentro, Fuera; xlsave1(Arg); Arg=xlgaimage(); Umbral=getnum(xlganum()); Dentro=255.0; Fuera=0.0; if (moreargs()) { Dentro=getnum(xlganum()); Fuera=getnum(xlganum()); } xllastarg(); Out=cvImageNode(Thr(getImage(Arg), Umbral, Dentro, Fuera)); xlpop(); return Out; }
5. Exemples : xsample2( ) /* Interficie de sample2 Format : ( sample2 <Image> [<int> [<int> [<int> [<int>] ] ] ] ) Parametres : imatge a mostrejar i pas per columna, fila, pla i canal en aquest ordre. Per defecte el pas es 1 */ LVAL xsample2 () { LVAL Arg, Out; int ArgNum[4]; /* maxim 4 arguments de pas */ int i ; xlsave1(Arg); Arg=xlgaimage(); /* llegim els passos i posem valors per defecte */ for (i=0; i<4; ++i) ArgNum[i] = 1; for (i=0; i<4; ++i) { if (!moreargs()) break; ArgNum[i]=getfixnum(xlgafixnum()); } xllastarg(); Out = cvImageNode ( sample2 (getImage(Arg), ArgNum[0], ArgNum[1], ArgNum[2], ArgNum[3]) ) ; xlpop(); return Out ; }
6. Integració d’una nova funció (Visual C++) • Cal crear una DLL amb Visual C++ que contingui la nova funció a afegir al ViLi. • Crear un arxiu <funcio>.cpp que contingui : • a) includes ViLi : f) funció (fixe) DllMain( ) com • #include <xlisp.h>als exemples Sample2 i • #include <image.h> diamferet de • \CrossVisions\Examples\ViLi\ • b) altres includes necessaris, com ara : • #include <math.h> • c) codi funció, <funcio>(), per exemple sample2() • d) codi interficie de la funció x<funcio>(), per exemple xsample2() • e) #define S SUBR • #define F FSUBR • FUNDEF localFunTab[]={ • { "SAMPLE2", S, xsample2 }, • { 0, 0, 0} • };
6. Integració d’una nova funció (Visual C++) • 2. Entrar en Visual C++ i crear un projecte nou de DLL, seguint al peu de la lletra • les instruccions de l’arxiu • CrossVisions\Doc\Readme.txt • a l’apartat “DLL ViLi o VisionOk” • 3. Copiar la DLL creada a \Debug al directori de ViLi • CrossVisions\lib\ • 4. Executar entrant en ViLi i fent • ViLi> (loadlibrary“… .dll”) • Consells : • editar l’arxiu d’exemple Sample2.cpp per fer el vostre. • provar en ViLi la funció polar amb testpol.lsp