Newsgroup: it.comp.os.linux.development
Titolo: sdl e jpeg [lungo]

salve, avrei un problema con le sdl e la jpeglib. Ho trovato in rete una 
funzione che dovrebbe permettermi di caricare un ' immagine jpeg in un surface
ve la scrivo(perdanate l'incolonnamento):
SDL_Surface  *SDL_LoadJPEG(char  *filename)
{
    struct jpeg_decompress_struct  file_info;
    FILE  *infile;
    struct my_error_mgr  std_error_mgr;
    Uint32  row_stride;
    JSAMPARRAY  buffer;
    Uint32 buffer_position, row_position, color, offset;
    Uint32  flags = SDL_SWSURFACE;
    Uint32  width, height, depth;
    Uint32  rmask, gmask, bmask, amask;
    SDL_Surface  *bitmap;
    char  *current_row;
    if ((infile = fopen(filename, "rb")) == NULL)
	return NULL;
    /* imposta i parametri necessari alla jpeglib */
    /* imposta l'error handler di default, quindi sovrascrive la funzione
       error_exit nella struttura file_info, in modo che in caso
       di errore sia richiamata una funzione definita da noi
       (my_error_exit()) */
    file_info.err = jpeg_std_error(&std_error_mgr.error_mgr);
    std_error_mgr.error_mgr.error_exit = my_error_exit;
    /* con setjmp viene impostato il punto del programma a cui la
       funzione di gestione della jpeglib passa il controllo in caso
       di errore */
    if (setjmp(std_error_mgr.setjmp_buffer)) {
	/* se sei in questo punto del programma si è verificato un errore
	   nella jpeglib e gli oggetti creati devono essere distrutti */
	jpeg_destroy_decompress(&file_info);
	fclose(infile);
	/* restituisce NULL ad indicare che la creazione della
	   SDL_Surface non è andata a buon fine */
	return NULL;
    }
    /* crea un oggetto di tipo decompress che descrive
       completamente un file jpeg su disco */
    jpeg_create_decompress(&file_info);
    /* imposta il canale di imput da cui legere i dati,
       puo essere un file o altro, in questo caso
       è il file aperto in precedenza */
    jpeg_stdio_src(&file_info, infile);
    /* legge le informazioni sul file */
    jpeg_read_header(&file_info, TRUE);
    /* inizia la decompressione */
    jpeg_start_decompress(&file_info);
    /* imposta lo profondità di colore a 24 bit */
    file_info.out_color_space = JCS_RGB;
    file_info.out_color_components = 3;
    file_info.output_components = 3;
    /* calcola e alloca la memoria necessaria a contenere una riga del file */
    row_stride = file_info.output_width * file_info.output_components;
    /* alloca la memoria usando la funzione messa a disposizione
       dalla jpeglib, non e necessario deallocarla, poichè sarà liberata
       automaticamente quando l'oggetto file_info sara distrutto con
       la funzione jpeg_destroy_decompres() */
    buffer = (*file_info.mem -> alloc_sarray)((j_common_ptr)&file_info,
					      JPOOL_IMAGE, row_stride, 1);
    if (!buffer)
      return NULL; /* se l'allocazione fallisce restituisci NULL */
    /* imposta i parametri necessari all'SDL per creare una SDL_Surface
       che contenga il file jpeg da caricare */
    width = file_info.output_width; /* larghezza in pixel */
    height = file_info.output_height; /* altezza in pixel */
    depth = 24; /* bits per pixel */
    amask = 0xff000000; /* maschera per il canale alpha */
    rmask = 0x00ff0000; /* maschera per il rosso */
    gmask = 0x0000ff00; /* maschera per il verde */
    bmask = 0x000000ff; /* maschera per il blu */
    /* crea la SDL_Surface per contenere i dati dell'immagine */
    bitmap = SDL_CreateRGBSurface(flags, width, height, depth,
				  rmask, gmask, bmask, amask);
    if (!bitmap)
	return NULL; /* se la creazione dell'SDL_Surface non va a buon fine
			restituisce NULL */
    /* legge i dati dell'immagine dal file e li salva in bitmap -> pixel */
    row_position = 0; /* posizione all'interno della riga corrente */
    /* punta ai pixel della linea corrente */
    current_row = (char *)bitmap -> pixels;
    while (file_info.output_scanline < file_info.output_height){
 
	/* legge una linea dal file */
	jpeg_read_scanlines(&file_info, buffer, 1);
	/* processa la linea appena letta */
 
	/* per ogni pixel della linea corrente ...*/
	for (buffer_position = 0 ; buffer_position < file_info.output_width ;
	     buffer_position++, row_position++){
 
	    /* converte un pixel della linea corrente dal formato RGB
	       al formato della SDL_Surface creata sopra*/
	    color = SDL_MapRGB(bitmap -> format,
			       buffer[0][buffer_position * 3],
			       buffer[0][buffer_position * 3 + 1],
			       buffer[0][buffer_position * 3 + 2]);
 
	    /* calcola la posizione in cui inserire il pixel
	       nella SDL_Surface */
	    offset = buffer_position * bitmap -> format -> BytesPerPixel;
	    /* copia il pixel creato nella memoria della SDL_Surface */
	    memcpy(current_row + offset, &color,
		   bitmap -> format -> BytesPerPixel);
	}
	/* sposta il puntatore all'inizio della riga successiva della
	   SDL_Surface di destinazione */
	current_row += bitmap -> pitch;
	row_position = 0; /* inizio della riga successiva */
    }
    /* termina la decompressione */
    jpeg_finish_decompress(&file_info);
    /* distrugge gli ogetti allocati */
    jpeg_destroy_decompress(&file_info);
    fclose(infile);
    return bitmap; /* restituisce un puntatore alla bitmap appena creata */
}
E' un po lunga, server per caricare un surface dell'image  ma il problema 
è che non funzia, ad esempio:
void display_jpeg(SDL_Surface *screen, char *filename, SDL_Rect pos)
{
 SDL_Surface *image;
 SDL_Rect frame ;
 
 /*Carica l'immagine*/ 
 
 image = SDL_LoadJPEG(filename);
 
 /*Controllo*/
 
 if (image == NULL) {
        fprintf(stderr, "Couldn't load %s: %s\n", filename, SDL_GetError());
        return;
    } 
 
 /*Imposta il rettangolo sullo schermo
 
 frame.x = frame.y = 0;   
 if (image -> w <= screen -> w)
	frame.w = image -> w; /* l'immagine è piu piccola dello schermo
				   sull'asse x */
    else
	frame.w = screen -> w; /* l'immagine è piu grande dello schermo
				   sull'asse x */
    if (image -> h <= screen -> h) 
	frame.h = image -> h; /* l'immagine è piu piccola dello schermo
				   sull'asse y */
    else
	frame.h = screen -> h; /* l'immagine è piu grande dello schermo
				   sull'asse y */
    /* esegue il blitting dell'immagine sullo schermo */
    SDL_BlitSurface(image, &frame, screen, &pos);
    SDL_UpdateRect(screen, pos.x, pos.y, pos.w, pos.h); /* la visualizza */
    SDL_FreeSurface(image);
}
Questa funzione scritta apposta per loadjpeg non mi visualizza nulla, avete 
idee?
grazie

...
Il mio consiglio e' semplice, se usi SDL, dimentica la libjpeg
e usa SDL_image, e' veramente ben fatta!
--
Davide

Davide

...

Ti consiglio di guardare gli esempi sul sito (demo, giochi, ecc.)
e di frequentare la mailinglist delle SDL, puoi lurkare i messaggi
anche da una pagina web sul sito della Loki (non ricordo l'URL)
oppure seguire il newsgroup "privato" che e' disponibile su
nntp://
news.lokigames.com
.
Bye,
--
Davide