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
)