c un framebuffer prenant une place minuscule, pouvant etre utilisé sur de nombreux systeme, http://gaffer.org
mon systeme scanne des images 32 bits, vire la transparence et crée un objet Gfm contenant les infos utile pour jumper et blitter ds le framebuffer
le framebuffer peut etre de nimporte quelle taille, mais les images blitté ac un clipping à la fois à gauche et à droite ne sont pas suportés
la fonction pour transformer une image en objet Gfm :
int* scanImg(int *img, int sx, int sy, int *trClr) { int *start, *lend; int tfull=0, ttr=0 ; int line=0 ; int *dta = (int*)malloc((sx*sy+sy*42*6)*4) ; int size ; int * jmp = dta+sx*sy ; int * sze = jmp + sy*42*2 ; int * cln = sze + sy*42*2 ; int * jmpPtr = jmp ; int * szePtr = sze ; int * dtaPtr = dta ; int * clnPtr = cln ; int h=sy ; img = img + sx*sy ; img -= sx ; lend = img + sx ; while(h--) { *clnPtr = 0 ; while(img < lend) { (*clnPtr)++ ; start=img ; while(img < lend && *img == *trClr) ++img ; size = img-start ; ttr+=size ; start=img ; *jmpPtr++ = size ; while(img < lend && *img != *trClr) ++img ; size = img-start ; *szePtr++ = size ; if(size) { memcpy(dtaPtr,start,size*4) ; line++ ; dtaPtr+=size ; } else { (*clnPtr)-- ; szePtr-- ; jmpPtr-- ; } }; clnPtr++ ; lend -= sx ; img = lend-sx ; }; tfull = dtaPtr-dta ; int objectSize = 16 + (sy + line*2 + tfull)*4 ; int *out = (int *)malloc(objectSize) ; // alloc size for the Gfm data #ifdef VERBOSE printf("\nalloc %i bytes for the object.",objectSize) ; #endif int *o = out ; *o++ = 0x6d6647 ; // put signature "Gfm\0" *o++ = objectSize ; // put Gfm object size *o++ = sx<<16 | (sy & 65535) ; // put frame size x and y #ifdef VERBOSE printf("\n\nscan result\n") ; #endif int c=0 ; jmpPtr=jmp ; szePtr=sze ; dtaPtr=dta ; int cn ; while(c < sy) { *o++ = cln[c] ; #ifdef VERBOSE printf("\nline %i\t %i full lines\t{ ",sy-c,cln[c]) ; #endif for(cn=0;cn < cln[c];cn++) { #ifdef VERBOSE if(*jmpPtr) printf("+%i ",*jmpPtr) ; printf("w%i ",*szePtr) ; #endif *o++ = *jmpPtr ; *o++ = *szePtr ; memcpy(o,dtaPtr,(*szePtr)*4) ; dtaPtr += *szePtr ; o += *szePtr ; jmpPtr++ ; szePtr++ ; }; c++ ; #ifdef VERBOSE printf("}") ; #endif }; *o++ = 0x2a2a2a2a ; // end check with "****" #ifdef VERBOSE printf("\n\nobject size : %i bytes", (o-out)*4) ; printf("\n\n* total : \ntr %i\nfull %i\nsum %i\n%i lines\nsx * sy = %i * %i = %i\n",ttr,tfull,ttr+tfull,line,sx,sy,sx*sy) ; #endif free(dta) ; return out ; }
celles pour sauver ou charger un fichier Gfm :
void saveGfm(int *Gfm, const char *path) { if(*Gfm != 0x6d6647) return ; FILE *f = fopen(path,"w") ; fwrite(Gfm,Gfm[1],1,f) ; fclose(f) ; } int *loadGfm(const char *path) { FILE * f = fopen(path,"r") ; int sz[2] ; fread(sz,8,1,f) ; rewind(f) ; if(sz[0] != 0x6d6647) { fclose(f) ; return NULL ; } int *out = (int*)malloc(sz[1]) ; fread(out,sz[1],1,f) ; fclose(f) ; return out ; }
celle pour blitter un objet sans clipping en x :
void udrawGfm(int *Gfm, int * scr) // draw a Gfm unclipped on x { #ifdef ALL_CHECK if(*Gfm++ != 0x6d6647) return ; Gfm++ ; // is a Gfm ? #else Gfm+=2 ; #endif int sx = *Gfm>>16 , sy = (*Gfm++)&65535 ; static int * scrEnd = pixel + WIDTH*HEIGHT - 1 ; int lnb, sze ; if(scr > scrEnd) return ; // out of screen at up int upClip = (scr + sy*WIDTH > scrEnd) ; // is clipped at up ? if(scr < pixel) // is clipped at down ? { if(scr + sy*WIDTH < pixel) return ; // out of screen at down do{ lnb = *Gfm++ ; while(lnb--) { Gfm++ ; Gfm += *Gfm++ ; }; scr += WIDTH ; sy-- ; } while(scr < pixel) ; } int *screen = scr ; int c = 0 ; while(c < sy) { lnb = *Gfm++ ; while(lnb--) { scr += *Gfm++ ; sze = *Gfm++ ; memcpy(scr,Gfm,sze*4) ; Gfm += sze ; scr+=sze ; }; scr = screen + WIDTH*(++c) ; if(upClip) if(scr > scrEnd) return ; }; #ifdef ALL_CHECK if(*Gfm != 0x2a2a2a2a) { printf("\n* draw error, is your Gfm corupt ? chk : 0x%x\n",*Gfm) ; system("pause") ; } #endif }
et celle de blit ac un clipping total (à part à gauche et à droite au mm moment) :
void drawGfm(int *Gfm, int x, int y) { #ifdef ALL_CHECK if(*Gfm != 0x6d6647) return ; // is a Gfm ? #endif int sx = Gfm[2]>>16 ; int sy = Gfm[2]&65535 ; static int * scrEnd = pixel + WIDTH*HEIGHT - 1 ; if(x >= 0 && x + sx < WIDTH){ udrawGfm(Gfm,pixel + y*WIDTH + x) ; return ; } if(x < -sx || x > WIDTH) return ;// out of screen on x if(x >= 0) // clip right only { int max = WIDTH-x ; int lnb, sze ; int * scr = pixel + y*WIDTH + x ; if(scr > scrEnd) return ; // out of screen at up int upClip = (scr + sy*WIDTH > scrEnd) ; // is clipped at up ? Gfm += 3 ; if(scr < pixel) // is clipped at down ? { if(scr + sy*WIDTH < pixel) return ; // out of screen at down do{ lnb = *Gfm++ ; while(lnb--) { Gfm++ ; Gfm += *Gfm++ ; }; scr += WIDTH ; sy-- ; } while(scr < pixel) ; } int *screen = scr ; int c = 0 ; int * lend ; while(c < sy) { lnb = *Gfm++ ; lend = scr + max ; while(lnb--) { scr += *Gfm++ ; sze = *Gfm++ ; if(scr + sze < lend) memcpy(scr,Gfm,sze*4) ; else if(scr < lend) memcpy(scr,Gfm,(lend-scr)*4) ; Gfm += sze ; scr+=sze ; }; scr = screen + WIDTH*(++c) ; if(upClip) if(scr > scrEnd) return ; }; } else if(x+sx < WIDTH) { // clip left only int lnb, sze ; int *s = pixel + y*WIDTH ; int *scr = s+x ; if(s > scrEnd) return ; // out of screen at up int upClip = (s + sy*WIDTH > scrEnd) ; // is clipped at up ? Gfm += 3 ; if(s < pixel) // is clipped at down ? { if(s + sy*WIDTH < pixel) return ; // out of screen at down do{ lnb = *Gfm++ ; while(lnb--) { Gfm++ ; Gfm += *Gfm++ ; }; s += WIDTH ; sy-- ; } while(s < pixel) ; } scr = s+x ; int *screen = scr ; int c=0 ; int size ; while(c < sy) { lnb = *Gfm++ ; while(lnb--) { scr += *Gfm++ ; sze = *Gfm++ ; if(scr >= s) memcpy(scr,Gfm,sze*4) ; else if(scr + sze > s) { size = (scr + sze)-s ; memcpy(s,Gfm+(sze-size),size*4) ; } Gfm += sze ; scr+=sze ; }; scr = screen + WIDTH*(++c) ; s = scr-x ; if(upClip) if(s > scrEnd) return ; }; } else { // clip left and right #ifdef VERBOSE printf("\nyet, not implemented\n") ; system("pause") ; #endif return ; } #ifdef ALL_CHECK if(*Gfm != 0x2a2a2a2a) { printf("\n* draw error, is your Gfm corupt ? chk : 0x%x\n",*Gfm) ; system("pause") ; } #endif }
le code est en c++ mais peut facilement etre adapté en c (l'objet Gfm n'est pas un objet, juste une zone de memoire)
vous devez utiliser le meme environement que pour le template de tinyPtc,
cad la hauteur de la fenettre doit etre mise ds le define HEIGHT, la longueur ds WIDTH, et le framebuffer doit s'apeller pixel :
#define WIDTH 320
#define HEIGHT 240
#define SIZE WIDTH*HEIGHT
static int pixel[SIZE];
2 define pour *configurer* les fct de blit :
#define VERBOSE indique si l'on doit afficher les info de debug
#define ALL_CHECK indique si les fct de blit doivent tester la validité de l'objet
[edit] corection de qq petites erreurs